Skip to content

Commit de2ab9f

Browse files
committed
fix: fix bug
1 parent fbf26f9 commit de2ab9f

5 files changed

Lines changed: 78 additions & 4 deletions

File tree

packages/devextreme/js/__internal/scheduler/m_utils_time_zone.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,18 @@ const isLocalTimeMidnightDST = (date: Date): boolean => {
258258
return startDayDate.getHours() === 1;
259259
};
260260

261+
const adjustDayIntervalMinForMidnightDST = (
262+
dayIntervalMin: number,
263+
startDayHour: number,
264+
): number => {
265+
const date = createDateFromUTCWithLocalOffset(new Date(dayIntervalMin));
266+
const isMidnightDST = startDayHour === 0 && isLocalTimeMidnightDST(date);
267+
268+
return isMidnightDST
269+
? dayIntervalMin + date.getHours() * 60 * 60 * 1000
270+
: dayIntervalMin;
271+
};
272+
261273
const utils = {
262274
getDaylightOffset,
263275
getDaylightOffsetInMs,
@@ -285,6 +297,7 @@ const utils = {
285297
cacheTimeZones,
286298

287299
isLocalTimeMidnightDST,
300+
adjustDayIntervalMinForMidnightDST,
288301
};
289302

290303
export default utils;

packages/devextreme/js/__internal/scheduler/view_model/common/trim_interval.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import type { DateInterval } from '../types';
22

3+
export const clampIntervalMin = (interval: DateInterval, minFloor: number): DateInterval => ({
4+
...interval,
5+
min: Math.max(interval.min, minFloor),
6+
});
7+
38
export const trimInterval = ({
49
min,
510
max,

packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/options/get_minutes_cell_intervals.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import timeZoneUtils from '../../../m_utils_time_zone';
12
import { splitIntervalByDay } from '../../common/split_interval_by_days';
23
import type { CellInterval, DateInterval } from '../../types';
34

@@ -30,8 +31,12 @@ export const getMinutesCellIntervals = ({
3031

3132
let columnIndex = 0;
3233
filterBySkippedDays(dayIntervals, skippedDays).forEach((dayInterval) => {
33-
const date = new Date(dayInterval.min);
34-
while (date.getTime() < dayInterval.max) {
34+
const firstAvailableDayTime = timeZoneUtils
35+
.adjustDayIntervalMinForMidnightDST(dayInterval.min, startDayHour);
36+
const intervalMin = Math.max(firstAvailableDayTime, interval.min);
37+
const intervalMax = Math.min(dayInterval.max, interval.max);
38+
const date = new Date(intervalMin);
39+
while (date.getTime() < intervalMax) {
3540
const min = date.getTime();
3641
let max = date.setUTCMinutes(date.getUTCMinutes() + durationMinutes);
3742

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* @timezone Africa/Cairo
3+
*/
4+
5+
import {
6+
describe, expect, it,
7+
} from '@jest/globals';
8+
9+
import { getWeekIntervals } from './get_week_intervals';
10+
11+
describe('getWeekIntervals', () => {
12+
it('T1327394: should not add a timeline cell before the first available local time on midnight DST', () => {
13+
const intervals = getWeekIntervals({
14+
startDayHour: 0,
15+
endDayHour: 24,
16+
min: Date.UTC(2026, 3, 24, 1),
17+
max: Date.UTC(2026, 3, 25),
18+
skippedDays: [],
19+
}, 60, 0, true);
20+
21+
expect(intervals.cells[0]).toEqual({
22+
min: Date.UTC(2026, 3, 24, 1),
23+
max: Date.UTC(2026, 3, 24, 2),
24+
rowIndex: 0,
25+
columnIndex: 0,
26+
cellIndex: 0,
27+
});
28+
});
29+
30+
it('T1327394: should not add a timeline week cell before the first available local time on midnight DST', () => {
31+
const intervals = getWeekIntervals({
32+
startDayHour: 0,
33+
endDayHour: 24,
34+
min: Date.UTC(2026, 3, 20),
35+
max: Date.UTC(2026, 3, 27),
36+
skippedDays: [],
37+
}, 60, 0, true);
38+
39+
expect(intervals.cells.find((cell) => cell.min === Date.UTC(2026, 3, 24))).toBeUndefined();
40+
expect(intervals.cells.find((cell) => cell.min === Date.UTC(2026, 3, 24, 1))).toEqual({
41+
min: Date.UTC(2026, 3, 24, 1),
42+
max: Date.UTC(2026, 3, 24, 2),
43+
rowIndex: 0,
44+
columnIndex: 96,
45+
cellIndex: 96,
46+
});
47+
});
48+
});

packages/devextreme/js/__internal/scheduler/view_model/generate_view_model/options/get_week_intervals.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { shiftIntervals } from '../../common/shift_intervals';
22
import { splitIntervalByDay } from '../../common/split_interval_by_days';
3-
import { trimInterval } from '../../common/trim_interval';
3+
import { clampIntervalMin, trimInterval } from '../../common/trim_interval';
44
import type { CompareOptions, LayoutIntervals } from '../../types';
55
import { getMinutesCellIntervals } from './get_minutes_cell_intervals';
66

@@ -14,12 +14,15 @@ export const getWeekIntervals = (
1414
const trimmedInterval = trimInterval(dateInterval);
1515
const splitIntervals = splitIntervalByDay(compareOptions);
1616
const intervals = isTimeline ? [trimmedInterval] : splitIntervals;
17+
const cellIntervals = isTimeline
18+
? [clampIntervalMin(trimmedInterval, dateInterval.min)]
19+
: intervals;
1720
const shiftedIntervals = shiftIntervals(intervals, viewOffset);
1821
const shiftedSplitIntervals = shiftIntervals(splitIntervals, viewOffset);
1922

2023
const cells = getMinutesCellIntervals({
2124
...compareOptions,
22-
intervals,
25+
intervals: cellIntervals,
2326
durationMinutes: cellDurationMinutes,
2427
});
2528
const shiftedCells = shiftIntervals(cells, viewOffset);

0 commit comments

Comments
 (0)