AgentSkillsCN

ramadan-calendar-and-fasting-logic

TryRamadan 中的斋月日历(起始与结束日期、当日序号、年份分界线)、禁食状态(已完成/跳过/中断)、连续禁食天数以及“今日覆盖”功能。适用于编辑 src/lib/ramadan.ts 文件、调整禁食状态的转换逻辑、计算连续禁食天数,或更新斋月日期标签时使用。

SKILL.md
--- frontmatter
name: ramadan-calendar-and-fasting-logic
description: Ramadan calendar (start/end, day number, year boundary), fasting states (completed/skipped/broken), streak and todayOverride in TryRamadan. Use when editing src/lib/ramadan.ts, fasting state transitions, streak calculation, or Ramadan day labels.

Ramadan Calendar and Fasting Logic (TryRamadan)

Use this skill when working on Ramadan dates, fasting state (completed/skipped/broken), streak, or "today" vs timezone so behavior stays consistent with the documented model.


1. Ramadan calendar (src/lib/ramadan.ts)

  • Start/end: RAMADAN_START_BY_YEAR (Gregorian); getRamadanStartForYear, getRamadanEndForYear. Cross-year Ramadan (e.g. 2030-12-26 → 2031-01-23) is handled in isRamadanDay and getRamadanDayNumber.
  • Missing year: Code falls back to ~11 days earlier from a reference year; add a test for missing year and consider logging or in-app note when using fallback.
  • Tests: src/test/ramadan.test.ts. See docs/QA-RAMADAN-LOGIC-AND-TEST-CASES.md and docs/EDGE-CASE-TEST-SCENARIOS.md (calendar & Ramadan boundaries).

2. Fasting states (per day)

  • Data: progress.completedDays, progress.skippedDays, progress.fastingLog (entries with status: 'in_progress' | 'completed' | 'broken', optional brokenReason).
  • Transitions: startFastingToday → in_progress; completeFastingToday → completed + add to completedDays; breakFastingToday → broken (remove from completedDays, store reason); setDaySkipped → skipped (remove from completedDays, clear log for that date); uncompleteFastingToday / setDayCompleted(..., false) → remove from completedDays.
  • Excused: brokenReason in ['illness','travel','menstruation','medical'] = excused; stats and streak treat excused as streak-preserving (see streaks-stats-gamification skill).
  • State-transition table and invalid transitions: docs/STATE-TRANSITION-TESTING-FASTING.md. When changing transitions, ensure UI blocks or warns on invalid transitions.

3. "Today" and todayOverride

  • Display timezone: When displayTimezone is set, "today" = location's date (getTodayStringInTimezone(displayTimezone)). Pass this as todayOverride into: getTodayFastingLog(progress, todayOverride), isFastingToday(progress, todayOverride), startFastingToday(..., todayOverride), completeFastingToday(..., todayOverride), breakFastingToday(..., todayOverride), getStreakDays(progress, todayOverride), calculateStreak(progress, todayOverride).
  • Dashboard, Today, Progress, Settings, Achievements: All use todayStr from display timezone when set and pass it into streak and fasting helpers so streak and day label stay in sync.
  • Bug risk: If streak or "today" uses device-local date while the rest of the app uses display timezone, streak can show 0 or wrong day. Always pass the same "today" used for the UI.

4. Ramadan calendar override (user-defined Ramadan days)

  • Doc: docs/RAMADAN-CALENDAR-ROBUSTNESS-AND-OVERRIDE.md. Covers app vs community start/end difference, manual override of "Ramadan days," and edge cases (logging before/after app’s Ramadan, voluntary fasts still labeled Ramadan). Implement override and labeling so the experience stays coherent with user control.

5. Tests

  • Ramadan dates: src/test/ramadan.test.ts.
  • Fasting / streak / todayOverride: src/test/loggingAndTracking.test.ts (including Regression: BUG-STRK-001).
  • When changing Ramadan or fasting logic, add or update tests and check STATE-TRANSITION-TESTING-FASTING and EDGE-CASE-TEST-SCENARIOS for coverage.