mirror of
https://github.com/quantum5/qcal.git
synced 2025-04-24 09:41:57 -04:00
Implement time-of-day display
This commit is contained in:
parent
2d1dbcc03c
commit
fe94f995c0
|
@ -1,6 +1,7 @@
|
||||||
import React, {FormEvent} from 'react';
|
import React, {FormEvent} from 'react';
|
||||||
import {Calendar} from './Calendar';
|
import {Calendar} from './Calendar';
|
||||||
import {endGregorian, endJD, frSupportedYear, gregorianJDN, jdnFrench, Month, startGregorian, startJD} from './dates';
|
import {endGregorian, endJD, frSupportedYear, gregorianJDN, jdnFrench, Month, startGregorian, startJD} from './dates';
|
||||||
|
import {TimeOfDay} from './TimeOfDay';
|
||||||
|
|
||||||
type YearMonth = {
|
type YearMonth = {
|
||||||
year: number;
|
year: number;
|
||||||
|
@ -101,6 +102,10 @@ class App extends React.Component<{}, AppState> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDateChange = (todayJDN: number) => {
|
||||||
|
this.setState({todayJDN});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <>
|
return <>
|
||||||
<Calendar
|
<Calendar
|
||||||
|
@ -109,6 +114,8 @@ class App extends React.Component<{}, AppState> {
|
||||||
this.setState({year, month});
|
this.setState({year, month});
|
||||||
}}/>
|
}}/>
|
||||||
|
|
||||||
|
<TimeOfDay onDateChange={this.onDateChange}/>
|
||||||
|
|
||||||
<div className="navigate">
|
<div className="navigate">
|
||||||
<h4>Go to a date</h4>
|
<h4>Go to a date</h4>
|
||||||
<form className="input-group" onSubmit={this.goToGregorian.bind(this)}>
|
<form className="input-group" onSubmit={this.goToGregorian.bind(this)}>
|
||||||
|
|
33
src/TimeOfDay.scss
Normal file
33
src/TimeOfDay.scss
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
@import 'bootstrap/scss/functions';
|
||||||
|
@import 'bootstrap/scss/variables';
|
||||||
|
@import 'bootstrap/scss/mixins';
|
||||||
|
@import 'bootstrap/scss/forms';
|
||||||
|
@import 'bootstrap/scss/grid';
|
||||||
|
@import 'bootstrap/scss/buttons';
|
||||||
|
@import './consts';
|
||||||
|
|
||||||
|
.TimeOfDay {
|
||||||
|
@include make-container();
|
||||||
|
}
|
||||||
|
|
||||||
|
.TimeOfDay-Rows {
|
||||||
|
@include make-row();
|
||||||
|
|
||||||
|
> * {
|
||||||
|
@include make-col-ready();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.TimeOfDay-Style {
|
||||||
|
strong::after {
|
||||||
|
content: ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
@include make-col();
|
||||||
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
.TimeOfDay-Rows {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
125
src/TimeOfDay.tsx
Normal file
125
src/TimeOfDay.tsx
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
import React from 'react';
|
||||||
|
import './TimeOfDay.scss';
|
||||||
|
import {gregorianJDN} from './dates';
|
||||||
|
|
||||||
|
type TimeStamp = {
|
||||||
|
hour: number,
|
||||||
|
minute: number,
|
||||||
|
second: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
type DecimalTimeStamp = TimeStamp;
|
||||||
|
type NormalTimeStamp = TimeStamp;
|
||||||
|
|
||||||
|
function currentDayMs(): number {
|
||||||
|
const now = new Date();
|
||||||
|
return now.getHours() * 3_600_000 + now.getMinutes() * 60_000 + now.getSeconds() * 1000 + now.getMilliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dayMsToDecimal(dayMs: number): DecimalTimeStamp {
|
||||||
|
const dayFrac = dayMs / 86_400_000;
|
||||||
|
const hour = Math.floor(dayFrac * 10);
|
||||||
|
const minute = Math.floor(dayFrac * 10 % 1 * 100);
|
||||||
|
const second = Math.floor(dayFrac * 1000 % 1 * 100);
|
||||||
|
return {hour, minute, second};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decimalToDayMs({hour, minute, second}: DecimalTimeStamp): number {
|
||||||
|
return 864 * (hour * 10_000 + minute * 100 + second);
|
||||||
|
}
|
||||||
|
|
||||||
|
function timePad(value: number): string {
|
||||||
|
return value.toString().padStart(2, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
type TimeOfDayProps = {
|
||||||
|
onDateChange?: (jdn: number) => void,
|
||||||
|
};
|
||||||
|
|
||||||
|
type TimeOfDayState = {
|
||||||
|
decimal: DecimalTimeStamp,
|
||||||
|
decimalTimer: number,
|
||||||
|
normal: NormalTimeStamp,
|
||||||
|
normalTimer: number,
|
||||||
|
jdn: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class TimeOfDay extends React.Component<TimeOfDayProps, TimeOfDayState> {
|
||||||
|
constructor(props: TimeOfDayProps) {
|
||||||
|
super(props);
|
||||||
|
const zero = {hour: 0, minute: 0, second: 0};
|
||||||
|
this.state = {
|
||||||
|
decimal: zero,
|
||||||
|
decimalTimer: 0,
|
||||||
|
normal: zero,
|
||||||
|
normalTimer: 0,
|
||||||
|
jdn: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.updateDecimalTime();
|
||||||
|
this.updateNormalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.state.decimalTimer) {
|
||||||
|
clearTimeout(this.state.decimalTimer);
|
||||||
|
}
|
||||||
|
if (this.state.normalTimer) {
|
||||||
|
clearTimeout(this.state.normalTimer);
|
||||||
|
}
|
||||||
|
this.setState({decimalTimer: 0, normalTimer: 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDecimalTime = () => {
|
||||||
|
const now = currentDayMs();
|
||||||
|
const {hour, minute, second} = dayMsToDecimal(now);
|
||||||
|
const nextTick = decimalToDayMs({hour, minute, second: second + 1});
|
||||||
|
const decimalTimer = window.setTimeout(this.updateDecimalTime, nextTick - now);
|
||||||
|
this.setState({decimal: {hour, minute, second}, decimalTimer});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNormalTime = () => {
|
||||||
|
const now = new Date();
|
||||||
|
const jdn = gregorianJDN(now.getFullYear(), now.getMonth() + 1, now.getDate());
|
||||||
|
if (this.props.onDateChange && jdn !== this.state.jdn) {
|
||||||
|
this.props.onDateChange(jdn);
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalTimer = window.setTimeout(this.updateNormalTime, 1000 - now.getMilliseconds());
|
||||||
|
this.setState({
|
||||||
|
normal: {
|
||||||
|
hour: now.getHours(),
|
||||||
|
minute: now.getMinutes(),
|
||||||
|
second: now.getSeconds()
|
||||||
|
},
|
||||||
|
normalTimer,
|
||||||
|
jdn,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <div className="TimeOfDay">
|
||||||
|
<h4>Time of Day</h4>
|
||||||
|
<div className="TimeOfDay-Rows">
|
||||||
|
<div className="TimeOfDay-Style">
|
||||||
|
<strong>Decimal time:</strong>
|
||||||
|
<span className="TimeOfDay-Value">
|
||||||
|
{this.state.decimal.hour}:
|
||||||
|
{timePad(this.state.decimal.minute)}:
|
||||||
|
{timePad(this.state.decimal.second)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="TimeOfDay-Style">
|
||||||
|
<strong>24-hour time:</strong>
|
||||||
|
<span className="TimeOfDay-Value">
|
||||||
|
{timePad(this.state.normal.hour)}:
|
||||||
|
{timePad(this.state.normal.minute)}:
|
||||||
|
{timePad(this.state.normal.second)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue