ba-cafe

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

timeUtils.ts (1655B)


      1 import { addHours, isAfter, startOfHour, setHours, addDays } from 'date-fns';
      2 import { toZonedTime, fromZonedTime } from 'date-fns-tz';
      3 
      4 const JST_TZ = 'Asia/Tokyo';
      5 
      6 // カレンダーの移動制限範囲(運用開始月~現在の月)
      7 export const CALENDAR_LIMITS = {
      8   MIN: new Date(2025, 12, 1),
      9   MAX: new Date(),
     10 } as const;
     11 
     12 // 境界線(4時/16時)を求める
     13 export const getNextBoundary = (date: Date): Date => {
     14   const jst = toZonedTime(date, JST_TZ);
     15   const hour = jst.getHours();
     16 
     17   let boundary = startOfHour(jst);
     18   if (hour < 4) {
     19     boundary = setHours(boundary, 4);
     20   } else if (hour < 16) {
     21     boundary = setHours(boundary, 16);
     22   } else {
     23     boundary = setHours(addDays(boundary, 1), 4);
     24   }
     25   return fromZonedTime(boundary, JST_TZ);
     26 };
     27 
     28 // UI表示用の終了時刻計算 (3時間後 or 境界線の早い方)
     29 export const getSessionEndTime = (lastTapTime: Date | null): Date | null => {
     30   if (!lastTapTime) return null;
     31 
     32   const baseTime = new Date(lastTapTime);
     33   baseTime.setMilliseconds(0);
     34 
     35   const standardEnd = addHours(baseTime, 3);
     36   const boundary = getNextBoundary(baseTime);
     37 
     38   return isAfter(standardEnd, boundary) ? boundary : standardEnd;
     39 };
     40 
     41 // 通知を予約すべきか判定
     42 export const shouldScheduleNotification = (tapTime: Date): boolean => {
     43   const jst = toZonedTime(tapTime, JST_TZ);
     44   const h = jst.getHours();
     45   
     46   if ((h >= 1 && h < 4) || (h >= 13 && h < 16)) return false;
     47 
     48   const endTime = getSessionEndTime(tapTime);
     49   if (!endTime) return false;
     50 
     51   const standardEnd = addHours(tapTime, 3);
     52   standardEnd.setMilliseconds(0);
     53 
     54   return endTime.getTime() === standardEnd.getTime();
     55 };