Skip to content

Commit 12f3064

Browse files
authored
fix: prevent current streak overstatement when today's data is missing (JhaSourav07#2062)
## Description Fixes JhaSourav07#2053 This PR fixes an edge case in streak calculation that could overstate the current streak when today's date is missing from the returned calendar data. ### Changes * Updated `findTodayIndex()` to return `-1` when today's date is not present in the calendar. * Modified `calculateStreak()` to fall back to the last available day **only when the local date is strictly after the calendar's last date** (indicating stale data). * Removed the previous behavior that always used the last available day whenever today could not be found. ### Why Previously, when today's date was missing from the returned calendar, the streak calculation would automatically use the last available day. This could incorrectly report an active streak for partial or stale calendar responses. The new logic ensures that: * Missing today's date does not automatically imply an active streak. * Fallback behavior is only used for genuinely stale calendar data. * Current streak values are not overstated. **Modified file:** `calculate.ts` ## Pillar - [ ] 🎨 Pillar 1 — New Theme Design - [ ] 📐 Pillar 2 — Geometric SVG Improvement - [ ] 🕐 Pillar 3 — Timezone Logic Optimization - [x] 🛠️ Other (Bug fix, refactoring, docs) ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise). - [x] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`). - [ ] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have started the repo. - [x] I have made sure that i have only one commit to merge in this PR. - [x] The SVG output matches the CommitPulse "premium quality" aesthetic standard (no raw elements, smooth animations, correct fonts). - [ ] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents d9d73ef + 5be59ab commit 12f3064

1 file changed

Lines changed: 37 additions & 8 deletions

File tree

lib/calculate.ts

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ export function findTodayIndex(days: ContributionDay[], timezone: string, now: D
1919

2020
const localTodayIndex = days.findIndex((d) => d.date === localTodayStr);
2121

22-
return localTodayIndex !== -1 ? localTodayIndex : days.length - 1;
22+
// If today's date isn't present in the calendar, return -1 so callers can
23+
// decide whether falling back to the last available day is appropriate.
24+
// Previously we always returned the last index which could cause an
25+
// overstated current streak when the calendar is partial or stale.
26+
return localTodayIndex !== -1 ? localTodayIndex : -1;
2327
}
2428

2529
export function calculateStreak(
@@ -47,15 +51,40 @@ export function calculateStreak(
4751

4852
// 2. Calculate Current Streak (Backwards loop with Grace Period)
4953
const localTodayStr = new Intl.DateTimeFormat('en-CA', { timeZone: timezone }).format(now);
50-
const todayIndex = findTodayIndex(days, timezone, now);
54+
let todayIndex = findTodayIndex(days, timezone, now);
5155

56+
// If the calendar doesn't contain today's date, only fall back to the
57+
// last available day when the local date is after the calendar's last
58+
// reported date (i.e. the calendar is stale). Otherwise, avoid guessing
59+
// and treat today's data as missing to prevent overstating the streak.
5260
if (todayIndex < 0) {
53-
return {
54-
currentStreak: 0,
55-
longestStreak: 0,
56-
totalContributions: calendar.totalContributions,
57-
todayDate: localTodayStr,
58-
};
61+
const lastIndex = days.length - 1;
62+
if (lastIndex < 0) {
63+
return {
64+
currentStreak: 0,
65+
longestStreak: 0,
66+
totalContributions: calendar.totalContributions,
67+
todayDate: localTodayStr,
68+
};
69+
}
70+
71+
const lastDateStr = days[lastIndex].date;
72+
73+
// Compare YYYY-MM-DD strings lexicographically — this works for ISO dates.
74+
if (localTodayStr > lastDateStr) {
75+
// Local date is after the last reported date → calendar is stale.
76+
todayIndex = lastIndex;
77+
} else {
78+
// Calendar contains dates after (or unrelated to) local today, or
79+
// today is simply missing from a partial range — don't assume the
80+
// streak is alive based on the last day.
81+
return {
82+
currentStreak: 0,
83+
longestStreak,
84+
totalContributions: calendar.totalContributions,
85+
todayDate: localTodayStr,
86+
};
87+
}
5988
}
6089

6190
let isStreakAlive = false;

0 commit comments

Comments
 (0)