Skip to content

Commit 95b6e12

Browse files
author
Dohyung Ahn
authored
Merge pull request #1222 from nhn/fix/adjust-dst-difference
2 parents a1e6596 + c2c9e08 commit 95b6e12

File tree

3 files changed

+114
-4
lines changed

3 files changed

+114
-4
lines changed

apps/calendar/src/hooks/timezone/useEventsWithTimezone.ts

+27-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { createEventCollection } from '@src/controller/base';
55
import { useTZConverter } from '@src/hooks/timezone/useTZConverter';
66
import type EventModel from '@src/model/eventModel';
77
import { primaryTimezoneSelector } from '@src/selectors/timezone';
8+
import TZDate from '@src/time/date';
9+
import { isUsingDST } from '@src/time/timezone';
810
import type Collection from '@src/utils/collection';
911
import { clone } from '@src/utils/object';
1012

@@ -17,6 +19,7 @@ export function useEventsWithTimezone(events: Collection<EventModel>) {
1719
return events;
1820
}
1921

22+
const isSystemUsingDST = isUsingDST(new TZDate());
2023
const {
2124
timedEvents = createEventCollection(),
2225
totalEvents = createEventCollection(),
@@ -26,8 +29,30 @@ export function useEventsWithTimezone(events: Collection<EventModel>) {
2629

2730
timedEvents.each((eventModel) => {
2831
const clonedEventModel = clone(eventModel);
29-
clonedEventModel.start = tzConverter(primaryTimezoneName, clonedEventModel.start);
30-
clonedEventModel.end = tzConverter(primaryTimezoneName, clonedEventModel.end);
32+
33+
let zonedStart = tzConverter(primaryTimezoneName, clonedEventModel.start);
34+
let zonedEnd = tzConverter(primaryTimezoneName, clonedEventModel.end);
35+
36+
// Adjust the start and end time to the system timezone.
37+
if (isSystemUsingDST) {
38+
if (!isUsingDST(zonedStart)) {
39+
zonedStart = zonedStart.addHours(1);
40+
}
41+
if (!isUsingDST(zonedEnd)) {
42+
zonedEnd = zonedEnd.addHours(1);
43+
}
44+
} else {
45+
if (isUsingDST(zonedStart)) {
46+
zonedStart = zonedStart.addHours(-1);
47+
}
48+
if (isUsingDST(zonedEnd)) {
49+
zonedEnd = zonedEnd.addHours(-1);
50+
}
51+
}
52+
53+
clonedEventModel.start = zonedStart;
54+
clonedEventModel.end = zonedEnd;
55+
3156
totalEvents.add(clonedEventModel);
3257
});
3358

apps/calendar/src/time/timezone.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export function calculateTimezoneOffset(timezoneName: string, targetDate: TZDate
3232
'Intl.DateTimeFormat is not fully supported. So It will return the local timezone offset only.\nYou can use a polyfill to fix this issue.'
3333
);
3434

35-
return -targetDate.getTimezoneOffset();
35+
return -targetDate.toDate().getTimezoneOffset();
3636
}
3737

3838
validateIANATimezoneName(timezoneName);
@@ -63,7 +63,8 @@ export function isUsingDST(targetDate: TZDate, timezoneName?: string) {
6363
}
6464

6565
return (
66-
Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()) !== targetDate.getTimezoneOffset()
66+
Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()) !==
67+
targetDate.toDate().getTimezoneOffset()
6768
);
6869
}
6970

apps/calendar/stories/e2e/week.stories.tsx

+84
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { h } from 'preact';
22

3+
import moment from 'moment-timezone';
4+
35
import { mockWeekViewEvents } from '@stories/mocks/mockWeekViewEvents';
46
import type { CalendarExampleStory } from '@stories/util/calendarExample';
57
import { CalendarExample } from '@stories/util/calendarExample';
68

9+
import type { EventObject } from '@t/events';
10+
711
export default { title: 'E2E/Week View' };
812

913
const Template: CalendarExampleStory = (args) => <CalendarExample {...args} />;
@@ -170,6 +174,86 @@ DaylightSavingTimeTransitionSouthern.args = {
170174
},
171175
};
172176

177+
// NOTE: For manual testing purposes
178+
const timezoneNameForSystemTimezoneTest = 'US/Pacific';
179+
// const timezoneNameForSystemTimezoneTest = 'Asia/Seoul';
180+
export const SystemTimezoneTest = Template.bind({});
181+
SystemTimezoneTest.args = {
182+
...Template.args,
183+
options: {
184+
...Template.args.options,
185+
useFormPopup: false,
186+
timezone: {
187+
zones: [
188+
{
189+
timezoneName: timezoneNameForSystemTimezoneTest,
190+
},
191+
],
192+
},
193+
},
194+
onInit: (cal) => {
195+
const convert = (d: Date) =>
196+
moment
197+
.tz(
198+
moment([
199+
d.getFullYear(),
200+
d.getMonth(),
201+
d.getDate(),
202+
d.getHours(),
203+
d.getMinutes(),
204+
d.getSeconds(),
205+
]).format('YYYY-MM-DD HH:mm:ss'),
206+
timezoneNameForSystemTimezoneTest
207+
)
208+
.toISOString();
209+
210+
cal.setDate('2022-03-09T00:00:00Z');
211+
212+
cal.createEvents([
213+
{
214+
id: 'pst',
215+
title: 'PST',
216+
start: '2022-03-09T09:00:00Z', // 01:00 UTC-08, 18:00 UTC+09
217+
end: '2022-03-09T10:00:00Z', // 02:00 UTC-08, 19:00 UTC+09
218+
},
219+
{
220+
id: 'pdt',
221+
title: 'PDT',
222+
start: '2022-03-16T08:00:00Z', // 01:00 UTC-07, 17:00 UTC+09
223+
end: '2022-03-16T09:00:00Z', // 02:00 UTC-07, 18:00 UTC+09
224+
},
225+
]);
226+
227+
cal.on('selectDateTime', (info) => {
228+
const startDate = info.start;
229+
const endDate = info.end;
230+
231+
cal.createEvents([
232+
{
233+
id: Date.now().toString(32).slice(0, 8),
234+
title: 'New Event',
235+
start: convert(startDate),
236+
end: convert(endDate),
237+
category: 'time',
238+
},
239+
]);
240+
241+
cal.clearGridSelections();
242+
});
243+
244+
cal.on('beforeUpdateEvent', ({ event, changes }) => {
245+
const zonedChanges = Object.keys(changes).reduce<EventObject>((acc, _k) => {
246+
const key = _k as keyof EventObject;
247+
acc[key] = convert(changes[key]);
248+
249+
return acc;
250+
}, {});
251+
252+
cal.updateEvent(event.id, event.calendarId, zonedChanges);
253+
});
254+
},
255+
};
256+
173257
export const CustomTemplate = Template.bind({});
174258
CustomTemplate.args = {
175259
...Template.args,

0 commit comments

Comments
 (0)