mirror of
https://github.com/discourse/discourse.git
synced 2025-05-24 14:12:10 +08:00
REFACTOR: local dates to improve reliability with DST and recurrence (#9379)
This commit improves testing and separates local-date generation from dates with zone manipulations.
This commit is contained in:
@ -0,0 +1,89 @@
|
||||
const { getProperties } = Ember;
|
||||
|
||||
/*
|
||||
DateWithZoneHelper provides a limited list of helpers
|
||||
to manipulate a moment object with timezones
|
||||
|
||||
- add(count unit) adds a COUNT of UNITS to a date
|
||||
- subtract(count unit) subtracts a COUNT of UNITS to a date
|
||||
- format(format) formats a date with zone in a consitent way, optional moment format
|
||||
- isDST() allows to know if a date in a specified timezone is currently under DST
|
||||
- datetimeWithZone(timezone) returns a new moment object with timezone applied
|
||||
- datetime returns the moment object
|
||||
- repetitionsBetweenDates(duration, date) return the number of repertitions of
|
||||
duration between two dates, eg for duration: "1.weeks", "2.months"...
|
||||
*/
|
||||
export default class DateWithZoneHelper {
|
||||
constructor(params = {}) {
|
||||
this.timezone = params.timezone || "UTC";
|
||||
this.localTimezone = params.localTimezone || moment.tz.guess();
|
||||
|
||||
this.datetime = moment.tz(
|
||||
getProperties(params, [
|
||||
"year",
|
||||
"month",
|
||||
"day",
|
||||
"hour",
|
||||
"minute",
|
||||
"second"
|
||||
]),
|
||||
this.timezone
|
||||
);
|
||||
}
|
||||
|
||||
isDST() {
|
||||
return this.datetime.tz(this.localTimezone).isDST();
|
||||
}
|
||||
|
||||
repetitionsBetweenDates(duration, date) {
|
||||
const [count, unit] = duration.split(".");
|
||||
const diff = this.datetime.diff(date, unit);
|
||||
const repetitions = diff / parseInt(count, 10);
|
||||
return Math.abs((Math.round(repetitions * 10) / 10).toFixed(1));
|
||||
}
|
||||
|
||||
add(count, unit) {
|
||||
return this._fromDatetime(
|
||||
this.datetime.clone().add(count, unit),
|
||||
this.timezone,
|
||||
this.localTimezone
|
||||
);
|
||||
}
|
||||
|
||||
subtract(count, unit) {
|
||||
return this._fromDatetime(
|
||||
this.datetime.clone().subtract(count, unit),
|
||||
this.timezone,
|
||||
this.localTimezone
|
||||
);
|
||||
}
|
||||
|
||||
datetimeWithZone(timezone) {
|
||||
return this.datetime.clone().tz(timezone);
|
||||
}
|
||||
|
||||
format(format) {
|
||||
if (format) {
|
||||
return this.datetime.tz(this.localTimezone).format(format);
|
||||
}
|
||||
|
||||
return this.datetime.tz(this.localTimezone).toISOString(true);
|
||||
}
|
||||
|
||||
static fromDatetime(datetime, timezone, localTimezone) {
|
||||
return new DateWithZoneHelper({
|
||||
year: datetime.year(),
|
||||
month: datetime.month(),
|
||||
day: datetime.date(),
|
||||
hour: datetime.hour(),
|
||||
minute: datetime.minute(),
|
||||
second: datetime.second(),
|
||||
timezone,
|
||||
localTimezone
|
||||
});
|
||||
}
|
||||
|
||||
_fromDatetime(datetime, timezone, localTimezone) {
|
||||
return DateWithZoneHelper.fromDatetime(datetime, timezone, localTimezone);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user