Skip to content

Commit fc0aa72

Browse files
Test coverage
1 parent c4f30fb commit fc0aa72

File tree

3 files changed

+751
-1650
lines changed

3 files changed

+751
-1650
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"babel-jest": "^30.0.2",
6666
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
6767
"core-js": "^3.46.0",
68+
"date-fns-tz": "^3.2.0",
6869
"eslint": "^9.19.0",
6970
"eslint-config-prettier": "^10.0.1",
7071
"eslint-plugin-import": "^2.31.0",
@@ -96,9 +97,9 @@
9697
"typescript-eslint": "^8.22.0"
9798
},
9899
"peerDependencies": {
100+
"date-fns-tz": "^3.0.0",
99101
"react": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc",
100-
"react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc",
101-
"date-fns-tz": "^3.0.0"
102+
"react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc"
102103
},
103104
"peerDependenciesMeta": {
104105
"date-fns-tz": {

src/test/timezone_test.test.tsx

Lines changed: 167 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
} from "../date_utils";
77

88
describe("Timezone utility functions", () => {
9+
// Use a fixed UTC date for consistent testing
910
const testDate = new Date("2024-06-15T12:00:00Z");
1011

1112
describe("toZonedTime", () => {
@@ -19,20 +20,36 @@ describe("Timezone utility functions", () => {
1920
expect(result).toBe(testDate);
2021
});
2122

22-
it("should return the original date when date-fns-tz is not installed", () => {
23-
// Suppress console.warn for this test
24-
const warnSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
25-
26-
// Since date-fns-tz is not installed, it should return the original date
23+
it("should convert UTC date to specified timezone", () => {
24+
// 2024-06-15T12:00:00Z in America/New_York (EDT, UTC-4) should be 08:00
2725
const result = toZonedTime(testDate, "America/New_York");
28-
expect(result).toBe(testDate);
26+
expect(result).toBeInstanceOf(Date);
27+
// The result should represent 08:00 in New York time
28+
expect(result.getHours()).toBe(8);
29+
expect(result.getMinutes()).toBe(0);
30+
});
2931

30-
// Should have warned about missing date-fns-tz
31-
expect(warnSpy).toHaveBeenCalledWith(
32-
expect.stringContaining("date-fns-tz"),
33-
);
32+
it("should handle UTC timezone", () => {
33+
const result = toZonedTime(testDate, "UTC");
34+
expect(result).toBeInstanceOf(Date);
35+
// toZonedTime returns a date that represents the time in the target timezone
36+
// When displayed locally, it should show 12:00 (the UTC time)
37+
expect(result.getHours()).toBe(12);
38+
expect(result.getMinutes()).toBe(0);
39+
});
3440

35-
warnSpy.mockRestore();
41+
it("should handle different timezones", () => {
42+
// Test with Europe/London (BST in June, UTC+1)
43+
const londonResult = toZonedTime(testDate, "Europe/London");
44+
expect(londonResult).toBeInstanceOf(Date);
45+
// 12:00 UTC should be 13:00 in London during BST
46+
expect(londonResult.getHours()).toBe(13);
47+
48+
// Test with Asia/Tokyo (JST, UTC+9)
49+
const tokyoResult = toZonedTime(testDate, "Asia/Tokyo");
50+
expect(tokyoResult).toBeInstanceOf(Date);
51+
// 12:00 UTC should be 21:00 in Tokyo
52+
expect(tokyoResult.getHours()).toBe(21);
3653
});
3754
});
3855

@@ -47,15 +64,28 @@ describe("Timezone utility functions", () => {
4764
expect(result).toBe(testDate);
4865
});
4966

50-
it("should return the original date when date-fns-tz is not installed", () => {
51-
// Suppress console.warn for this test
52-
const warnSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
67+
it("should convert zoned time to UTC", () => {
68+
// Create a date representing 08:00 in New York (which is 12:00 UTC in June)
69+
const nyDate = new Date("2024-06-15T08:00:00");
70+
const result = fromZonedTime(nyDate, "America/New_York");
71+
expect(result).toBeInstanceOf(Date);
72+
// The result should be 12:00 UTC
73+
expect(result.getUTCHours()).toBe(12);
74+
});
5375

54-
// Since date-fns-tz is not installed, it should return the original date
55-
const result = fromZonedTime(testDate, "America/New_York");
56-
expect(result).toBe(testDate);
76+
it("should handle UTC timezone", () => {
77+
const utcDate = new Date("2024-06-15T12:00:00");
78+
const result = fromZonedTime(utcDate, "UTC");
79+
expect(result).toBeInstanceOf(Date);
80+
expect(result.getUTCHours()).toBe(12);
81+
});
5782

58-
warnSpy.mockRestore();
83+
it("should be inverse of toZonedTime", () => {
84+
const timezone = "America/Los_Angeles";
85+
const zonedTime = toZonedTime(testDate, timezone);
86+
const backToUtc = fromZonedTime(zonedTime, timezone);
87+
// The round-trip should give us back the original UTC time
88+
expect(backToUtc.getTime()).toBe(testDate.getTime());
5989
});
6090
});
6191

@@ -66,19 +96,38 @@ describe("Timezone utility functions", () => {
6696
expect(result).toBe("2024-06-15");
6797
});
6898

69-
it("should use standard format when date-fns-tz is not installed", () => {
70-
// Suppress console.warn for this test
71-
const warnSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
72-
73-
// Since date-fns-tz is not installed, it should fall back to standard format
99+
it("should format date in specified timezone", () => {
100+
// 2024-06-15T12:00:00Z formatted in America/New_York should show 08:00
74101
const result = formatInTimeZone(
75102
testDate,
76-
"yyyy-MM-dd",
103+
"yyyy-MM-dd HH:mm",
77104
"America/New_York",
78105
);
79-
expect(result).toBe("2024-06-15");
106+
expect(result).toBe("2024-06-15 08:00");
107+
});
108+
109+
it("should format date in UTC timezone", () => {
110+
const result = formatInTimeZone(testDate, "yyyy-MM-dd HH:mm", "UTC");
111+
expect(result).toBe("2024-06-15 12:00");
112+
});
113+
114+
it("should format date in different timezones", () => {
115+
// Europe/London (BST in June, UTC+1)
116+
const londonResult = formatInTimeZone(testDate, "HH:mm", "Europe/London");
117+
expect(londonResult).toBe("13:00");
80118

81-
warnSpy.mockRestore();
119+
// Asia/Tokyo (JST, UTC+9)
120+
const tokyoResult = formatInTimeZone(testDate, "HH:mm", "Asia/Tokyo");
121+
expect(tokyoResult).toBe("21:00");
122+
});
123+
124+
it("should handle complex format strings", () => {
125+
const result = formatInTimeZone(
126+
testDate,
127+
"EEEE, MMMM d, yyyy 'at' h:mm a",
128+
"America/New_York",
129+
);
130+
expect(result).toBe("Saturday, June 15, 2024 at 8:00 AM");
82131
});
83132
});
84133

@@ -92,20 +141,17 @@ describe("Timezone utility functions", () => {
92141
expect(result.getTime()).toBeLessThanOrEqual(after.getTime());
93142
});
94143

95-
it("should return current date when date-fns-tz is not installed", () => {
96-
// Suppress console.warn for this test
97-
const warnSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
98-
99-
const before = new Date();
144+
it("should return current date in specified timezone", () => {
100145
const result = nowInTimeZone("America/New_York");
101-
const after = new Date();
102-
103-
// The result should be a Date object within the expected range
104146
expect(result).toBeInstanceOf(Date);
105-
expect(result.getTime()).toBeGreaterThanOrEqual(before.getTime());
106-
expect(result.getTime()).toBeLessThanOrEqual(after.getTime());
147+
// We can't test exact time, but we can verify it's a valid date
148+
expect(result.getTime()).not.toBeNaN();
149+
});
107150

108-
warnSpy.mockRestore();
151+
it("should return current date in UTC", () => {
152+
const result = nowInTimeZone("UTC");
153+
expect(result).toBeInstanceOf(Date);
154+
expect(result.getTime()).not.toBeNaN();
109155
});
110156
});
111157
});
@@ -130,4 +176,88 @@ describe("Timezone utility functions - edge cases", () => {
130176
expect(result).toBe(date);
131177
});
132178
});
179+
180+
it("should handle DST transitions", () => {
181+
// Test a date during DST (summer)
182+
const summerDate = new Date("2024-07-15T12:00:00Z");
183+
const summerResult = formatInTimeZone(
184+
summerDate,
185+
"HH:mm",
186+
"America/New_York",
187+
);
188+
expect(summerResult).toBe("08:00"); // EDT (UTC-4)
189+
190+
// Test a date outside DST (winter)
191+
const winterDate = new Date("2024-01-15T12:00:00Z");
192+
const winterResult = formatInTimeZone(
193+
winterDate,
194+
"HH:mm",
195+
"America/New_York",
196+
);
197+
expect(winterResult).toBe("07:00"); // EST (UTC-5)
198+
});
199+
200+
it("should handle dates at midnight", () => {
201+
const midnightUtc = new Date("2024-06-15T00:00:00Z");
202+
const result = formatInTimeZone(
203+
midnightUtc,
204+
"yyyy-MM-dd HH:mm",
205+
"America/New_York",
206+
);
207+
// Midnight UTC is 8 PM previous day in New York (EDT)
208+
expect(result).toBe("2024-06-14 20:00");
209+
});
210+
211+
it("should handle dates at end of day", () => {
212+
const endOfDayUtc = new Date("2024-06-15T23:59:59Z");
213+
const result = formatInTimeZone(
214+
endOfDayUtc,
215+
"yyyy-MM-dd HH:mm",
216+
"Asia/Tokyo",
217+
);
218+
// 23:59 UTC is 08:59 next day in Tokyo (JST, UTC+9)
219+
expect(result).toBe("2024-06-16 08:59");
220+
});
221+
});
222+
223+
describe("Timezone utility functions - integration", () => {
224+
it("should correctly round-trip dates through timezone conversions", () => {
225+
const originalDate = new Date("2024-06-15T15:30:00Z");
226+
const timezones = [
227+
"America/New_York",
228+
"America/Los_Angeles",
229+
"Europe/London",
230+
"Europe/Paris",
231+
"Asia/Tokyo",
232+
"Australia/Sydney",
233+
"UTC",
234+
];
235+
236+
timezones.forEach((tz) => {
237+
const zoned = toZonedTime(originalDate, tz);
238+
const backToUtc = fromZonedTime(zoned, tz);
239+
expect(backToUtc.getTime()).toBe(originalDate.getTime());
240+
});
241+
});
242+
243+
it("should format consistently across different timezones", () => {
244+
const utcDate = new Date("2024-06-15T00:00:00Z");
245+
246+
// All these should represent the same moment in time
247+
const utcFormatted = formatInTimeZone(utcDate, "yyyy-MM-dd HH:mm", "UTC");
248+
const nyFormatted = formatInTimeZone(
249+
utcDate,
250+
"yyyy-MM-dd HH:mm",
251+
"America/New_York",
252+
);
253+
const tokyoFormatted = formatInTimeZone(
254+
utcDate,
255+
"yyyy-MM-dd HH:mm",
256+
"Asia/Tokyo",
257+
);
258+
259+
expect(utcFormatted).toBe("2024-06-15 00:00");
260+
expect(nyFormatted).toBe("2024-06-14 20:00"); // Previous day in NY
261+
expect(tokyoFormatted).toBe("2024-06-15 09:00"); // Same day, later in Tokyo
262+
});
133263
});

0 commit comments

Comments
 (0)