@@ -17,6 +17,9 @@ export interface FreebuffModelOption {
1717 availability : 'always' | 'deployment_hours'
1818}
1919
20+ /** Server-facing fallback copy for APIs and provider errors that can't know
21+ * the caller's local timezone. The CLI should render
22+ * `getFreebuffDeploymentAvailabilityLabel()` instead. */
2023export const FREEBUFF_DEPLOYMENT_HOURS_LABEL = '9am ET-5pm PT'
2124export const FREEBUFF_GLM_MODEL_ID = 'z-ai/glm-5.1'
2225export const FREEBUFF_MINIMAX_MODEL_ID = 'minimax/minimax-m2.7'
@@ -30,7 +33,6 @@ interface ZonedDateParts {
3033 weekday : string
3134 hour : number
3235 minute : number
33- minutes : number
3436}
3537
3638interface LocalTimeFormatOptions {
@@ -113,7 +115,6 @@ function getZonedParts(date: Date, timeZone: string): ZonedDateParts {
113115 weekday : value ( 'weekday' ) ?? '' ,
114116 hour,
115117 minute,
116- minutes : hour * 60 + minute ,
117118 }
118119}
119120
@@ -167,29 +168,34 @@ function getUtcForZonedTime(
167168function isWeekend (
168169 parts : Pick < ZonedDateParts , 'year' | 'month' | 'day' > ,
169170) : boolean {
170- const weekday = new Date (
171- Date . UTC ( parts . year , parts . month - 1 , parts . day ) ,
172- ) . getUTCDay ( )
171+ const weekday = getWeekdayIndex ( parts )
173172 return weekday === 0 || weekday === 6
174173}
175174
175+ function getWeekdayIndex (
176+ parts : Pick < ZonedDateParts , 'year' | 'month' | 'day' > ,
177+ ) : number {
178+ return new Date ( Date . UTC ( parts . year , parts . month - 1 , parts . day ) ) . getUTCDay ( )
179+ }
180+
176181function getNextFreebuffDeploymentStart ( now : Date ) : Date {
177182 const easternNow = getZonedParts ( now , FREEBUFF_EASTERN_TIMEZONE )
183+ const weekday = getWeekdayIndex ( easternNow )
184+ const isBeforeTodayOpen = easternNow . hour < 9
178185
179- for ( let offset = 0 ; offset < 8 ; offset ++ ) {
180- const day = addDaysToYmd (
181- easternNow . year ,
182- easternNow . month ,
183- easternNow . day ,
184- offset ,
185- )
186- if ( isWeekend ( day ) ) continue
187- const candidate = getUtcForZonedTime ( day , FREEBUFF_EASTERN_TIMEZONE , 9 , 0 )
188- if ( candidate . getTime ( ) > now . getTime ( ) ) return candidate
189- }
186+ const offset =
187+ weekday === 6
188+ ? 2
189+ : weekday === 0
190+ ? 1
191+ : isBeforeTodayOpen
192+ ? 0
193+ : weekday === 5
194+ ? 3
195+ : 1
190196
191197 return getUtcForZonedTime (
192- addDaysToYmd ( easternNow . year , easternNow . month , easternNow . day , 8 ) ,
198+ addDaysToYmd ( easternNow . year , easternNow . month , easternNow . day , offset ) ,
193199 FREEBUFF_EASTERN_TIMEZONE ,
194200 9 ,
195201 0 ,
@@ -246,7 +252,10 @@ export function isFreebuffDeploymentHours(now: Date = new Date()): boolean {
246252 const eastern = getZonedParts ( now , FREEBUFF_EASTERN_TIMEZONE )
247253 const pacific = getZonedParts ( now , FREEBUFF_PACIFIC_TIMEZONE )
248254 if ( eastern . weekday === 'Sat' || eastern . weekday === 'Sun' ) return false
249- return eastern . minutes >= 9 * 60 && pacific . minutes < 17 * 60
255+ return (
256+ eastern . hour * 60 + eastern . minute >= 9 * 60 &&
257+ pacific . hour * 60 + pacific . minute < 17 * 60
258+ )
250259}
251260
252261export function isFreebuffModelAvailable (
0 commit comments