Implement time-of-day display

This commit is contained in:
Quantum 2022-02-27 03:13:42 -05:00
parent 2d1dbcc03c
commit fe94f995c0
3 changed files with 165 additions and 0 deletions

View file

@ -1,6 +1,7 @@
import React, {FormEvent} from 'react';
import {Calendar} from './Calendar';
import {endGregorian, endJD, frSupportedYear, gregorianJDN, jdnFrench, Month, startGregorian, startJD} from './dates';
import {TimeOfDay} from './TimeOfDay';
type YearMonth = {
year: number;
@ -101,6 +102,10 @@ class App extends React.Component<{}, AppState> {
});
}
onDateChange = (todayJDN: number) => {
this.setState({todayJDN});
}
render() {
return <>
<Calendar
@ -109,6 +114,8 @@ class App extends React.Component<{}, AppState> {
this.setState({year, month});
}}/>
<TimeOfDay onDateChange={this.onDateChange}/>
<div className="navigate">
<h4>Go to a date</h4>
<form className="input-group" onSubmit={this.goToGregorian.bind(this)}>

33
src/TimeOfDay.scss Normal file
View 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
View 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>;
}
}