|
1 | 1 | // lib/calculate.ts |
2 | 2 | import type { ContributionCalendar, StreakStats, MonthlyStats } from '../types'; |
3 | 3 |
|
| 4 | +/* |
| 5 | +Calculates streak statistics from a GitHub contribution calendar. |
| 6 | +
|
| 7 | +This function computes: |
| 8 | +- Current streak length (with a one-day grace period) |
| 9 | +- Longest streak length across the calendar |
| 10 | +- Total contributions made |
| 11 | +- Effective "today" date used for UI display |
| 12 | +
|
| 13 | +Current Streak Logic: |
| 14 | +The streak remains active if there are no contributions today |
| 15 | +but there were contributions yesterday. This prevents streaks |
| 16 | +from breaking prematurely due to timezone differences. |
| 17 | +
|
| 18 | +Timezone Handling: |
| 19 | +Contribution dates are calendar-based. The provided IANA timezone |
| 20 | +determines what "today" means for the user, ensuring streaks are |
| 21 | +calculated correctly in local time (e.g., "Asia/Kolkata", |
| 22 | +"America/Los_Angeles"). Defaults to "UTC". |
| 23 | +
|
| 24 | +@param {ContributionCalendar} calendar |
| 25 | + GitHub contribution calendar data containing weekly entries. |
| 26 | +
|
| 27 | +@param {string} [timezone='UTC'] |
| 28 | + IANA timezone string used to determine the local date. |
| 29 | +
|
| 30 | +@param {Date} [now=new Date()] |
| 31 | + Current time reference for calculations. Useful for testing |
| 32 | + or overriding the system clock. |
| 33 | +
|
| 34 | +@returns {StreakStats} |
| 35 | + An object with: |
| 36 | + - currentStreak: active streak length |
| 37 | + - longestStreak: longest historical streak |
| 38 | + - totalContributions: total contribution count |
| 39 | + - todayDate: effective date used for streak/UI calculations |
| 40 | +
|
| 41 | +@example |
| 42 | +// Calculate streak stats using a specific timezone |
| 43 | +const stats = calculateStreak(calendar, 'Asia/Kolkata'); |
| 44 | +
|
| 45 | +@example |
| 46 | +// Override both timezone and current time (useful in tests) |
| 47 | +const stats = calculateStreak( |
| 48 | + calendar, |
| 49 | + 'America/Los_Angeles', |
| 50 | + new Date('2026-05-25T10:00:00Z') |
| 51 | +); |
| 52 | +*/ |
| 53 | + |
4 | 54 | export function calculateStreak( |
5 | 55 | calendar: ContributionCalendar, |
6 | 56 | timezone: string = 'UTC', |
@@ -77,6 +127,34 @@ export function calculateStreak( |
77 | 127 | }; |
78 | 128 | } |
79 | 129 |
|
| 130 | +/* |
| 131 | + Calculates monthly contribution statistics from a GitHub contribution calendar. |
| 132 | +
|
| 133 | + Figures out how many contributions were made this month and last month, then compares them. |
| 134 | +
|
| 135 | + @param {ContributionCalendar} calendar |
| 136 | + Weekly GitHub contribution data. |
| 137 | +
|
| 138 | + @param {string} [timezone='UTC'] |
| 139 | + Timezone to decide which month is "current". |
| 140 | + Example: 'Asia/Kolkata' ensures local month is used. |
| 141 | +
|
| 142 | + @param {Date} [now=new Date()] |
| 143 | + Current date/time reference (useful for testing). |
| 144 | +
|
| 145 | + @returns {MonthlyStats} |
| 146 | + - currentMonthTotal: contributions this month |
| 147 | + - previousMonthTotal: contributions last month |
| 148 | + - deltaAbsolute: difference (this − last) |
| 149 | + - deltaPercentage: % change, rounded |
| 150 | + - currentMonthName: name of this month (e.g. "May") |
| 151 | +
|
| 152 | + @example |
| 153 | + const stats = calculateMonthlyStats(calendar, 'Asia/Kolkata'); |
| 154 | + stats.currentMonthName → "May" |
| 155 | + stats.deltaPercentage → 42 |
| 156 | +*/ |
| 157 | + |
80 | 158 | export function calculateMonthlyStats( |
81 | 159 | calendar: ContributionCalendar, |
82 | 160 | timezone: string = 'UTC', |
|
0 commit comments