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 {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
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