Skip to content

Commit

Permalink
T1185479: Scheduler - Incorrect date shown for recurrence in the New …
Browse files Browse the repository at this point in the history
…Zealand timezone (#25531)

Co-authored-by: Ilya Vinogradov <[email protected]>
  • Loading branch information
williamvinogradov and Ilya Vinogradov authored Sep 12, 2023
1 parent 04b7c1c commit 3e3263b
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
39 changes: 33 additions & 6 deletions packages/devextreme/js/__internal/scheduler/m_recurrence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ const loggedWarnings: any = [];
const MS_IN_HOUR = 1000 * 60 * 60;
const MS_IN_DAY = MS_IN_HOUR * 24;

const RRULE_BROKEN_TIMEZONES = [
'Etc/GMT-13',
'MIT',
'Pacific/Apia',
'Pacific/Enderbury',
'Pacific/Tongatapu',
'Etc/GMT-14',
'Pacific/Kiritimati',
];

let recurrence: RecurrenceProcessor | null = null;

export function getRecurrenceProcessor() {
Expand Down Expand Up @@ -92,13 +102,8 @@ class RecurrenceProcessor {
}

_convertRruleResult(rruleIntervalParams, options, rruleDate) {
const localTimezoneOffset = timeZoneUtils.getClientTimezoneOffset(rruleDate);
// NOTE: Workaround for the RRule bug with timezones greater than GMT+12 (e.g. Apia Standard Time GMT+13)
// GitHub issue: https://github.com/jakubroztocil/rrule/issues/555
const additionalWorkaroundOffsetForRrule = localTimezoneOffset / MS_IN_HOUR <= -13 ? -MS_IN_DAY : 0;
const convertedBackDate = timeZoneUtils.setOffsetsToDate(rruleDate, [
localTimezoneOffset,
additionalWorkaroundOffsetForRrule,
...this._getLocalMachineOffset(rruleDate),
-options.appointmentTimezoneOffset,
rruleIntervalParams.startIntervalDateDSTShift,
]);
Expand All @@ -114,6 +119,28 @@ class RecurrenceProcessor {
return resultDate;
}

_getLocalMachineOffset(rruleDate) {
const machineTimezoneOffset = timeZoneUtils.getClientTimezoneOffset(rruleDate);
const machineTimezoneName = dateUtils.getMachineTimezoneName();
const result = [machineTimezoneOffset];

// NOTE: Workaround for the RRule bug with timezones greater than GMT+12 (e.g. Apia Standard Time GMT+13)
// GitHub issue: https://github.com/jakubroztocil/rrule/issues/555
// UPD: 05.09.2023 - The issue still hasn't been fixed in the Rule package.
// RRule returns results that are one day greater than expected.
// Therefore, for broken from RRule point of view timezones, we subtract one day from the result.
const brokenTimezonesOffset = -13;
const isTimezoneOffsetInBrokenRange = machineTimezoneOffset / MS_IN_HOUR <= brokenTimezonesOffset;
const isTimezoneNameInBrokenNames = !machineTimezoneName
|| RRULE_BROKEN_TIMEZONES.some((timezone) => machineTimezoneName.includes(timezone));

if (isTimezoneOffsetInBrokenRange && isTimezoneNameInBrokenNames) {
result.push(-MS_IN_DAY);
}

return result;
}

hasRecurrence(options) {
return !!this.generateDates(options).length;
}
Expand Down
12 changes: 11 additions & 1 deletion packages/devextreme/js/core/utils/date.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* globals Intl */
import { isObject, isString, isDate, isDefined, isNumeric } from './type';
import { adjust } from './math';
import { each } from './iterator';
Expand Down Expand Up @@ -680,6 +681,13 @@ const createDateWithFullYear = function(year) {
return result;
};

const getMachineTimezoneName = () => {
const hasIntl = typeof Intl !== 'undefined';
return hasIntl
? Intl.DateTimeFormat().resolvedOptions().timeZone
: null;
};

const dateUtils = {
dateUnitIntervals: dateUnitIntervals,

Expand Down Expand Up @@ -740,7 +748,9 @@ const dateUtils = {

getDatesOfInterval: getDatesOfInterval,

createDateWithFullYear: createDateWithFullYear
createDateWithFullYear: createDateWithFullYear,

getMachineTimezoneName: getMachineTimezoneName,
};

dateUtils.sameView = function(view, date1, date2) {
Expand Down

0 comments on commit 3e3263b

Please sign in to comment.