@@ -274,4 +274,99 @@ describe("prettyFormatTimeRange", () => {
274
274
} ) ;
275
275
} ) ;
276
276
} ) ;
277
+
278
+ describe ( "Handles time zones correctly" , ( ) => {
279
+ const America_New_York = [
280
+ {
281
+ test : "Non-zero minute, minute grain" ,
282
+ time : "2025-09-04T16:30:30.000Z" ,
283
+ grain : V1TimeGrain . TIME_GRAIN_MINUTE ,
284
+ formattedTime : "Sep 4, 2025 (12:30:30PM)" ,
285
+ } ,
286
+ {
287
+ test : "Same month, days difference, same time at midnight" ,
288
+ start : "2025-09-02T04:00:00.000Z" ,
289
+ end : "2025-09-06T04:00:00.000Z" ,
290
+ grain : V1TimeGrain . TIME_GRAIN_DAY ,
291
+ formattedTime : "Sep 2 – 5, 2025" ,
292
+ } ,
293
+ {
294
+ test : "Full 2024, year grain" ,
295
+ start : "2024-01-01T05:00:00.000Z" ,
296
+ end : "2025-01-01T05:00:00.000Z" ,
297
+ grain : V1TimeGrain . TIME_GRAIN_YEAR ,
298
+ formattedTime : "2024" ,
299
+ } ,
300
+ {
301
+ test : "Two non-zero dates in America/New_York, second grain" ,
302
+ start : "2025-09-18T11:12:03.605-04:00" ,
303
+ end : "2025-09-20T14:24:04.485-04:00" ,
304
+ grain : V1TimeGrain . TIME_GRAIN_SECOND ,
305
+ formattedTime : "Sep 18 – 20, 2025 (11:12:03AM-2:24:04PM)" ,
306
+ } ,
307
+ {
308
+ test : "Two non-zero dates, second grain" ,
309
+ start : "2025-09-18T15:12:03.605Z" ,
310
+ end : "2025-09-20T18:24:04.485Z" ,
311
+ grain : V1TimeGrain . TIME_GRAIN_SECOND ,
312
+ formattedTime : "Sep 18 – 20, 2025 (11:12:03AM-2:24:04PM)" ,
313
+ } ,
314
+ ] ;
315
+
316
+ const Asia_Kathmandu = [
317
+ {
318
+ test : "Point in time at midnight, minute grain" ,
319
+ time : "2025-09-04T18:15:00.000Z" ,
320
+ grain : V1TimeGrain . TIME_GRAIN_MINUTE ,
321
+ formattedTime : "Sep 5, 2025 (12:00AM)" ,
322
+ } ,
323
+ {
324
+ test : "Same month, days difference, same time not at midnight" ,
325
+ start : "2025-09-01T10:15:00.000Z" ,
326
+ end : "2025-09-04T10:15:00.000Z" ,
327
+ grain : V1TimeGrain . TIME_GRAIN_HOUR ,
328
+ formattedTime : "Sep 1 – 4, 2025 (4PM)" ,
329
+ } ,
330
+ {
331
+ test : "Full 2023, year grain" ,
332
+ start : "2022-12-31T18:15:00.000Z" ,
333
+ end : "2023-12-31T18:15:00.000Z" ,
334
+ grain : V1TimeGrain . TIME_GRAIN_YEAR ,
335
+ formattedTime : "2023" ,
336
+ } ,
337
+ {
338
+ test : "Two non-zero dates in Asia/Kathmandu, minute grain" ,
339
+ start : "2021-08-27T02:30:00.000+05:45" ,
340
+ end : "2023-08-29T13:30:00.000+05:45" ,
341
+ grain : V1TimeGrain . TIME_GRAIN_MINUTE ,
342
+ formattedTime : "Aug 27, 2021 – Aug 29, 2023 (2:30AM-1:30PM)" ,
343
+ } ,
344
+ ] ;
345
+
346
+ America_New_York . forEach (
347
+ ( { test, start, end, time, grain, formattedTime } ) => {
348
+ it ( test + " in America/New_York" , ( ) => {
349
+ const interval = Interval . fromDateTimes (
350
+ DateTime . fromISO ( start ?? time ) . setZone ( "America/New_York" ) ,
351
+ DateTime . fromISO ( end ?? time ) . setZone ( "America/New_York" ) ,
352
+ ) ;
353
+ const actualFormattedTime = prettyFormatTimeRange ( interval , grain ) ;
354
+ expect ( actualFormattedTime ) . toEqual ( formattedTime ) ;
355
+ } ) ;
356
+ } ,
357
+ ) ;
358
+
359
+ Asia_Kathmandu . forEach (
360
+ ( { test, time, start, end, grain, formattedTime } ) => {
361
+ it ( test + " in Asia/Kathmandu" , ( ) => {
362
+ const interval = Interval . fromDateTimes (
363
+ DateTime . fromISO ( start ?? time ) . setZone ( "Asia/Kathmandu" ) ,
364
+ DateTime . fromISO ( end ?? time ) . setZone ( "Asia/Kathmandu" ) ,
365
+ ) ;
366
+ const actualFormattedTime = prettyFormatTimeRange ( interval , grain ) ;
367
+ expect ( actualFormattedTime ) . toEqual ( formattedTime ) ;
368
+ } ) ;
369
+ } ,
370
+ ) ;
371
+ } ) ;
277
372
} ) ;
0 commit comments