Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timezones #6822

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# Change Log

#### next release (8.3.2)
#### next release (8.3.3)

- [The next improvement]

#### 8.3.2 - 2023-07-14

- Add 2 traits for WMS layers `dateFormat` and `timeZone` to enable control over display of Date/Time

#### 8.3.1 - 2023-06-29

- **Breaking changes:**
Expand Down
6 changes: 6 additions & 0 deletions lib/Core/DateUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export function getOffsetMinutes(timeZone: string): number {
const [hoursString, minutesString] = timeZone.split(":");
const hours = parseInt(hoursString);
const minutes = parseInt(minutesString);
return hours * 60 + minutes;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fails when a timeZone of "+11" is used. I think it'd be good to support that form of timezone too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added regex check, so the function now checks for the timeZone to be in the format +/- HH:MM or +/-HH if not it will return 0 in which case no offset will be applied

4 changes: 3 additions & 1 deletion lib/ModelMixins/DiscretelyTimeVaryingMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,9 @@ function DiscretelyTimeVaryingMixin<

namespace DiscretelyTimeVaryingMixin {
export interface Instance
extends InstanceType<ReturnType<typeof DiscretelyTimeVaryingMixin>> {}
extends InstanceType<ReturnType<typeof DiscretelyTimeVaryingMixin>> {
[x: string]: any;
}

export function isMixedInto(model: any): model is Instance {
return model && model.hasDiscreteTimes;
Expand Down
1 change: 1 addition & 0 deletions lib/ReactViews/BottomDock/Timeline/CesiumTimeline.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const CesiumTimeline = createReactClass({
defined(layer.dateFormat) &&
defined(layer.dateFormat.timelineTic)
) {
console.log("layer.dateFormat", layer.dateFormat);
sixlighthouses marked this conversation as resolved.
Show resolved Hide resolved
return dateFormat(
JulianDate.toDate(time),
layer.dateFormat.timelineTic
Expand Down
42 changes: 39 additions & 3 deletions lib/ReactViews/BottomDock/Timeline/Timeline.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import JulianDate from "terriajs-cesium/Source/Core/JulianDate";
import CommonStrata from "../../../Models/Definition/CommonStrata";
import withControlledVisibility from "../../HOCs/withControlledVisibility";
import CesiumTimeline from "./CesiumTimeline";
import { formatDateTime } from "./DateFormats";
import { getOffsetMinutes } from "../../../Core/DateUtils";
// import { formatDateTime } from "./DateFormats";
import DateTimePicker from "./DateTimePicker";
import Styles from "./timeline.scss";
import TimelineControls from "./TimelineControls";
Expand Down Expand Up @@ -67,7 +68,26 @@ class Timeline extends React.Component {
}
const { t } = this.props;

const jsDate = JulianDate.toDate(catalogItem.currentTimeAsJulianDate);
let jsDate;

if (defined(catalogItem.timeZone)) {
try {
const offset = getOffsetMinutes(catalogItem.timeZone);
const offsetTime = new JulianDate();
const adjTime = JulianDate.addMinutes(
catalogItem.currentDiscreteJulianDate,
offset,
offsetTime
);
jsDate = JulianDate.toDate(adjTime);
} catch (e) {
console.log(e);
jsDate = JulianDate.toDate(catalogItem.currentTimeAsJulianDate);
}
} else {
jsDate = JulianDate.toDate(catalogItem.currentTimeAsJulianDate);
}

const timelineStack = this.props.terria.timelineStack;
let currentTime;
if (defined(timelineStack.top) && defined(timelineStack.top.dateFormat)) {
Expand All @@ -76,7 +96,23 @@ class Timeline extends React.Component {
this.props.terria.timelineStack.top.dateFormat
);
} else {
currentTime = formatDateTime(jsDate, this.props.locale);
if (defined(catalogItem.timeZone)) {
const offset = getOffsetMinutes(catalogItem.timeZone);
const offsetTime = new JulianDate();
const adjTime = JulianDate.addMinutes(
catalogItem.currentDiscreteJulianDate,
offset,
offsetTime
);
if (defined(catalogItem.dateFormat)) {
console.log("adjusted dateFormat", catalogItem.dateFormat);
sixlighthouses marked this conversation as resolved.
Show resolved Hide resolved
currentTime = dateFormat(adjTime, catalogItem.dateFormat);
} else {
currentTime = dateFormat(adjTime, "isoDate");
}
} else {
currentTime = dateFormat(jsDate, "isoDate");
}
}

const discreteTimes = catalogItem.discreteTimesAsSortedJulianDates;
Expand Down
20 changes: 16 additions & 4 deletions lib/ReactViews/Workbench/Controls/DateTimeSelectorSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { GLYPHS, StyledIcon } from "../../../Styled/Icon";
import Spacing from "../../../Styled/Spacing";
import Text, { TextSpan } from "../../../Styled/Text";
import { formatDateTime } from "../../BottomDock/Timeline/DateFormats";
import { getOffsetMinutes } from "../../../Core/DateUtils";
import DateTimePicker from "../../BottomDock/Timeline/DateTimePicker";

interface IState {
Expand Down Expand Up @@ -53,6 +54,7 @@ class DateTimeSelectorSection extends React.Component<IProps, IState> {

runInAction(() => {
// Set the time on the item, set it to use its own clock, update the imagery and repaint.
console.log(item);
sixlighthouses marked this conversation as resolved.
Show resolved Hide resolved
item.setTrait(
CommonStrata.user,
"currentTime",
Expand Down Expand Up @@ -144,12 +146,22 @@ class DateTimeSelectorSection extends React.Component<IProps, IState> {
}

if (isDefined(item.currentDiscreteJulianDate)) {
const time = JulianDate.toDate(item.currentDiscreteJulianDate);
let time = JulianDate.toDate(item.currentDiscreteJulianDate);
if (isDefined(item.timeZone)) {
const offset = getOffsetMinutes(item.timeZone);
const offsetTime = new JulianDate();
const adjTime = JulianDate.addMinutes(
item.currentDiscreteJulianDate,
offset,
offsetTime
);
time = JulianDate.toDate(adjTime);
}

if (isDefined(item.dateFormat)) {
format = item.dateFormat;
discreteTime = dateFormat(time, item.dateFormat);
} else {
discreteTime = formatDateTime(time);
discreteTime = dateFormat(time, "isoDate");
}
}

Expand All @@ -161,7 +173,7 @@ class DateTimeSelectorSection extends React.Component<IProps, IState> {
{item.timeLabel ?? t("dateTime.selectorLabel")}
</Text>
<Spacing bottom={1} />
<Box fullWidth justifySpaceBetween styledHeight={"30px"} gap>
<Box fullWidth justifySpaceBetween gap>
<Box
backgroundColor="rgba(250, 250, 250, 0.2)"
css={`
Expand Down
23 changes: 23 additions & 0 deletions lib/Traits/TraitsClasses/DateTimeTraits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import ModelTraits from "../ModelTraits";
import primitiveTrait from "../Decorators/primitiveTrait";

export class DateTimeTraits extends ModelTraits {
@primitiveTrait({
type: "string",
name: "Timezone",
description:
"If the DateTime attribute values do not have timezone information" +
" (e.g. 2018-01-01T00:00:00), specify the ISO timezone with offset from UTC (e.g. +10:00)"
})
timeZone?: string;

@primitiveTrait({
type: "string",
name: "Date format",
description:
"See available formats here https://github.com/felixge/node-dateformat"
})
dateFormat?: string;
}

export default DateTimeTraits;
4 changes: 3 additions & 1 deletion lib/Traits/TraitsClasses/WebMapServiceCatalogItemTraits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import mixTraits from "../mixTraits";
import ModelTraits from "../ModelTraits";
import { traitClass } from "../Trait";
import CatalogMemberTraits from "./CatalogMemberTraits";
import DateTimeTraits from "./DateTimeTraits";
import DiffableTraits from "./DiffableTraits";
import ExportWebCoverageServiceTraits from "./ExportWebCoverageServiceTraits";
import GetCapabilitiesTraits from "./GetCapabilitiesTraits";
Expand Down Expand Up @@ -175,7 +176,8 @@ export default class WebMapServiceCatalogItemTraits extends mixTraits(
MappableTraits,
CatalogMemberTraits,
LegendOwnerTraits,
MinMaxLevelTraits
MinMaxLevelTraits,
DateTimeTraits
) {
@primitiveTrait({
type: "string",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,9 @@ describe("DateTimeSelectorSection", function () {
it("A datetime selector is rendered", function () {
expect(buttons).toBeDefined();
expect(buttons.length).toEqual(5);
// Need to do it the longer way because Travis runs in a diff locale
const expectedDateStr = formatDateTime(
new Date("2014-01-01T00:00:00.000Z")
);

// the date will default this "2014-01-01T00:00:00.000Z" to the isoDate format
const expectedDateStr = "2014-01-01";

expect(currentDateBtn.children[0].children[0].children[0]).toEqual(
expectedDateStr
Expand Down