Skip to content

Commit

Permalink
Merge pull request #191 from lsst-ts/feature/centralized-clock
Browse files Browse the repository at this point in the history
Feature/centralized clock
  • Loading branch information
sfehlandt authored Apr 22, 2020
2 parents 7a6c00b + 99db6ac commit 5dee31a
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 175 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ DigitalClock.defaultProps = {
}

export default function DigitalClock ({ timestamp, hideDate }) {
const t = parseTimestamp(timestamp);
const t = timestamp === 0 ? 0 : parseTimestamp(timestamp);
return (
<div className={styles.container}>
<div className={styles.time}>
{ t.toFormat('HH:mm:ss') }
{ t ? t.toFormat('HH:mm:ss') : '--:--:--' }
</div>
{ !hideDate && (
<div className={styles.date}>
{ t.toFormat('EEE, MMM dd yyyy') }
{t ? t.toFormat('EEE, MMM dd yyyy') : '---' }
</div>
)}
</div>
Expand Down
4 changes: 2 additions & 2 deletions love/src/components/Layout/Layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import MenuIcon from '../icons/MenuIcon/MenuIcon';
import HeartbeatIcon from '../icons/HeartbeatIcon/HeartbeatIcon';
import NotchCurve from './NotchCurve/NotchCurve';
import EditIcon from '../icons/EditIcon/EditIcon';
import Clock from '../Time/Clock/Clock';
import ClockContainer from '../Time/Clock/Clock.container';
import styles from './Layout.module.css';
import LabeledStatusTextContainer from '../GeneralPurpose/LabeledStatusText/LabeledStatusText.container';
import { HEARTBEAT_COMPONENTS } from '../../Config';
Expand Down Expand Up @@ -351,7 +351,7 @@ class Layout extends Component {
this.props.mode === modes.EDIT && !this.state.toolbarOverflow ? styles.hidden : '',
].join(' ')}
>
<Clock timeData={this.props.timeData} hideAnalog hideOffset={true} />
<ClockContainer timezone='local' hideAnalog hideOffset={true} />
</div>
</div>

Expand Down
11 changes: 6 additions & 5 deletions love/src/components/Time/Clock/Clock.container.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { connect } from 'react-redux';
import { getTimeData } from '../../../redux/selectors';
import { getClock } from '../../../redux/selectors';
import Clock from './Clock';

export const schema = {
Expand Down Expand Up @@ -62,11 +62,12 @@ export const schema = {
type: 'string',
description:
`Timezone string used to configure which UTC offset to use.
Null or empty if current should be used. 'UTC' for UTC. Null by default.
'local' if current should be used. 'local' by default.
The format for the timezone string can be a fixed string (for UTC or TAI); a fixed-offset string (e.g. UTC+5);
or a location string in the format <Continent>/<City> (use camelcase with underscores instead of spaces, like America/New_York).
For example:
- For local time use local
- For UTC use UTC
- For TAI use TAI
- For Greenwich Sidereal Time use sidereal-greenwich
Expand All @@ -78,7 +79,7 @@ export const schema = {
Note that not every city is available, check the IANA DB documentation for more info: https://www.iana.org/time-zones
See the default value as an example`,
isPrivate: false,
default: null,
default: 'local',
},
},
};
Expand All @@ -92,8 +93,8 @@ const ClockContainer = ({ ...props }) => {
};

const mapStateToProps = (state) => {
const timeData = getTimeData(state);
return { timeData };
const clock = getClock(state);
return { clock };
};

const mapDispatchToProps = (dispatch) => {
Expand Down
160 changes: 58 additions & 102 deletions love/src/components/Time/Clock/Clock.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,11 @@ import PropTypes from 'prop-types';
import styles from './Clock.module.css';
import AnalogClock from '../../GeneralPurpose/AnalogClock/AnalogClock';
import DigitalClock from '../../GeneralPurpose/DigitalClock/DigitalClock';
import { DateTime } from 'luxon';
import { siderealSecond } from '../../../Utils';

/**
* Component that displays time, date and an analog clock, with options to display only some of those elements.
*/
// Clock.propTypes = {
// /** Optional name to display above the clock */
// name: PropTypes.string,
// /** Date-able object or float, if float it must be in milliseconds */
// timestamp: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
// /** Flag to hide or not the analog clock, false by default */
// hideAnalog: PropTypes.bool,
// /** Flag to hide or not the date, false by default */
// hideDate: PropTypes.bool,
// /** Flag to hide or not the UTC offset besides the name, false by default */
// hideOffset: PropTypes.bool,
// }

// Clock.defaultProps = {
// name: null,
// timestamp: DateTime.local(),
// hideDate: false,
// hideAnalog: false,
// hideOffset: false,
// }

export default class Clock extends React.Component {
static propTypes = {
/** Optional name to display above the clock */
name: PropTypes.string,
/** Date-able object or float, if float it must be in milliseconds. If null, an internal clock will be defined by the component*/
timestamp: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
/** Flag to hide or not the analog clock, false by default */
hideAnalog: PropTypes.bool,
/** Flag to hide or not the date, false by default */
Expand All @@ -45,103 +17,87 @@ export default class Clock extends React.Component {
/** Locale string used to configure how to display the UTC Offset. en-GB by default (so it is displayed as GMT always).
* Null or empty to use the browser locale */
locale: PropTypes.string,
/** The timezone to display the timestamps. Null or empty if current should be used 'UTC' for UTC. Null by default.
/** The timezone to display the timestamps. 'local' if current should be used. 'local' by default.
* The format for this string must be: <Continent (camelcase)>-<City (camelcase)>.
* For example:
* - For local time use local
* - For UTC use UTC
* - For TAI use TAI
* - For 'La Serena' use 'America/Santiago' (yes America, not Chile)
* - For 'Arizona' use 'America/Phoenix'
* - For 'Illinois' use 'America/Chicago'
*/
timezone: PropTypes.string,
/** Time Data from the server */
timeData: PropTypes.object,
/**
* Current time clocks from the server in the following format:
* {
utc: <utc time in seconds>,
tai: <tai time in seconds>,
mjd: <modified julian date in days>,
sidereal_summit: <Local (summit) Apparent Sidereal Time in seconds>,
sidereal_greenwich: <Greenwich Apparent Sidereal Time (GAST) in seconds>,
}
*/
clock: PropTypes.shape({
utc: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
tai: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
mjd: PropTypes.number,
sidereal_summit: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
sidereal_greenwich: PropTypes.oneOfType([PropTypes.number, PropTypes.object]),
}),
};

static defaultProps = {
name: null,
timestamp: null,
hideDate: false,
hideAnalog: false,
hideOffset: false,
locale: 'en-GB',
timezone: null,
timeData: {
request_time: 0,
receive_time: 0,
server_time: {
utc: 0,
tai: 0,
mjd: 0,
sidereal_summit: 0,
sidereal_greenwhich: 0,
tai_to_utc: 0,
},
},
};

constructor(props) {
super(props);
this.state = {
timestamp: 0,
};
}

componentDidMount() {
if (this.props.timestamp) return;
this.timerID = setInterval(() => this.tick(), 1000);
}

componentWillUnmount() {
if (this.props.timestamp) return;
clearInterval(this.timerID);
}

tick() {
const diffLocalUtc = DateTime.utc().toSeconds() - (this.props.timeData.receive_time + this.props.timeData.request_time) / 2;
let timestamp = 0;
if (this.props.timezone === 'sidereal-summit') {
timestamp = DateTime.fromSeconds(
this.props.timeData.server_time.sidereal_summit * 3600 + siderealSecond * diffLocalUtc
);
} else if (this.props.timezone === 'sidereal-greenwich') {
timestamp = DateTime.fromSeconds(
this.props.timeData.server_time.sidereal_greenwich * 3600 + siderealSecond * diffLocalUtc
);
} else if (this.props.timezone === 'MJD') {
timestamp = this.props.timeData.server_time.mjd + diffLocalUtc / (3600 * 24);
} else {
timestamp = DateTime.fromSeconds(this.props.timeData.server_time.utc + diffLocalUtc);
clock: {
utc: 0,
tai: 0,
mjd: 0,
sidereal_summit: 0,
sidereal_greenwich: 0,
}
if (timestamp !== this.state.timestamp) {
this.setState({ timestamp });
}
}
};

render() {
let timestamp = this.props.timestamp ? this.props.timestamp : this.state.timestamp;
let hideAnalog = this.props.hideAnalog;
let mjd = false;
let offset = timestamp.offsetNameShort;
let hideDate = this.props.hideDate;
if (timestamp) {
if (this.props.timezone) {
if (this.props.timezone === 'TAI') {
timestamp = timestamp.setZone('UTC').minus({ seconds: this.props.timeData.server_time.tai_to_utc });
offset = 'TAI';
} else if (this.props.timezone === 'MJD') {
hideAnalog = true;
mjd = true;
offset = 'MJD';
hideDate = true;
} else if (this.props.timezone === 'sidereal-summit' || this.props.timezone === 'sidereal-greenwich') {
timestamp = timestamp.setZone('UTC');
offset = this.props.timezone === 'sidereal-greenwich' ? 'GAST' : 'Summit-AST';
hideDate = true;
} else {
timestamp = timestamp.setZone(this.props.timezone);
}
let mjd = false;
let offset = null;
let timestamp = 0;
if (this.props.clock.utc !== 0) {
if (this.props.timezone === 'UTC') {
timestamp = this.props.clock.utc;
offset = 'UTC';
}
else if (this.props.timezone === 'TAI') {
timestamp = this.props.clock.tai;
offset = 'TAI';
}
else if (this.props.timezone === 'MJD') {
timestamp = this.props.clock.mjd;
hideAnalog = true;
mjd = true;
offset = 'MJD';
hideDate = true;
}
else if (this.props.timezone === 'sidereal-summit') {
timestamp = this.props.clock.sidereal_summit;
offset = 'Summit-AST';
hideDate = true;
}
else if (this.props.timezone === 'sidereal-greenwich') {
timestamp = this.props.clock.sidereal_greenwich;
offset = 'GAST';
hideDate = true;
}
else {
timestamp = this.props.clock.utc.setZone(this.props.timezone);
offset = timestamp.offsetNameShort;
}
if (!mjd && this.props.locale) {
timestamp = timestamp.setLocale(this.props.locale);
Expand Down
13 changes: 7 additions & 6 deletions love/src/components/Time/TimeDisplay.container.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { connect } from 'react-redux';
import { getTimeData } from '../../redux/selectors';
import { getClock } from '../../redux/selectors';
import TimeDisplay from './TimeDisplay';

export const schema = {
Expand Down Expand Up @@ -34,7 +34,7 @@ export const schema = {
isPrivate: false,
default: 'en-GB',
},
clocks: {
clocks_layout: {
type: 'array',
description:
`Layout of clocks in JSON format.
Expand All @@ -45,11 +45,12 @@ export const schema = {
2. hideAnalog: (boolean = false) flag to hide the analog clock.
3. hideDate: (boolean = false) flag to hide the date.
4. hideOffset: (boolean = false) flag to hide the UTC offset, displayed at the right of the name
5. timezone: timezone string used to configure which UTC offset to use. Null or empty if current should be used. Null by default.
5. timezone: timezone string used to configure which UTC offset to use. 'local' if current should be used. 'local' by default.
The format for the timezone string can be a fixed string (for UTC or TAI); a fixed-offset string (e.g. UTC+5);
or a location string in the format <Continent>/<City> (use camelcase with underscores instead of spaces, like America/New_York)
For example:
- For local time use local
- For UTC use UTC
- For TAI use TAI
- For Greenwich Sidereal Time use sidereal-greenwich
Expand All @@ -68,7 +69,7 @@ export const schema = {
hideAnalog: false,
hideDate: false,
hideOffset: false,
timezone: null,
timezone: 'local',
},
{
name: 'Sidereal Time',
Expand Down Expand Up @@ -140,8 +141,8 @@ const TimeDisplayContainer = ({ ...props }) => {
};

const mapStateToProps = (state) => {
const timeData = getTimeData(state);
return { timeData };
const clock = getClock(state);
return { clock };
};

const mapDispatchToProps = (dispatch) => {
Expand Down
Loading

0 comments on commit 5dee31a

Please sign in to comment.