@@ -455,12 +455,15 @@ export interface PolicyRequest {
455455 * Handles midnight-spanning windows (e.g. 22:00 → 06:00).
456456 */
457457function isWithinTimeWindow ( timeWindow : TimeWindow , now : Date ) : boolean {
458- // Get the current time in the specified timezone
458+ // Get the current time in the specified timezone.
459+ // Use hourCycle: 'h23' (range 0-23) instead of hour12: false, because
460+ // hour12: false resolves to hourCycle 'h24' (range 1-24) on Node 20's
461+ // ICU, which returns hour "24" for midnight — breaking time comparisons.
459462 const formatter = new Intl . DateTimeFormat ( 'en-US' , {
460463 timeZone : timeWindow . timezone ,
461464 hour : '2-digit' ,
462465 minute : '2-digit' ,
463- hour12 : false ,
466+ hourCycle : 'h23' ,
464467 } ) ;
465468
466469 const parts = formatter . formatToParts ( now ) ;
@@ -476,11 +479,11 @@ function isWithinTimeWindow(timeWindow: TimeWindow, now: Date): boolean {
476479 const endMinutes = endH * 60 + endM ;
477480
478481 if ( startMinutes <= endMinutes ) {
479- // Normal window: e.g. 09:00 → 18:00
480- return currentMinutes >= startMinutes && currentMinutes < endMinutes ;
482+ // Normal window: e.g. 09:00 → 18:00 (both bounds inclusive)
483+ return currentMinutes >= startMinutes && currentMinutes <= endMinutes ;
481484 }
482- // Midnight-spanning window: e.g. 22:00 → 06:00
483- return currentMinutes >= startMinutes || currentMinutes < endMinutes ;
485+ // Midnight-spanning window: e.g. 22:00 → 06:00 (both bounds inclusive)
486+ return currentMinutes >= startMinutes || currentMinutes <= endMinutes ;
484487}
485488
486489/**
0 commit comments