Skip to content

Commit b1f76e9

Browse files
authored
Merge branch 'main' into refactor/i18n-usage
2 parents 4a12b7b + 0d28eb4 commit b1f76e9

3 files changed

Lines changed: 536 additions & 50 deletions

File tree

app/composables/useCharts.ts

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -122,36 +122,6 @@ function mergeDailyPoints(
122122
.map(([day, downloads]) => ({ day, downloads }))
123123
}
124124

125-
function getIsoWeekStartDateFromWeekKey(weekKey: string): Date | null {
126-
const match = /^(\d{4})-W(\d{2})$/.exec(weekKey)
127-
if (!match) return null
128-
129-
const year = Number(match[1])
130-
const week = Number(match[2])
131-
132-
const januaryFourth = new Date(Date.UTC(year, 0, 4))
133-
const januaryFourthIsoDay = januaryFourth.getUTCDay() || 7
134-
const weekOneMonday = new Date(Date.UTC(year, 0, 4 - (januaryFourthIsoDay - 1)))
135-
136-
const weekMonday = new Date(weekOneMonday)
137-
weekMonday.setUTCDate(weekOneMonday.getUTCDate() + (week - 1) * 7)
138-
return weekMonday
139-
}
140-
141-
function toIsoWeekKey(isoDay: string): string {
142-
const date = new Date(`${isoDay}T00:00:00.000Z`)
143-
const isoDayOfWeek = date.getUTCDay() || 7
144-
145-
const thursday = new Date(date)
146-
thursday.setUTCDate(date.getUTCDate() + 4 - isoDayOfWeek)
147-
148-
const isoYear = thursday.getUTCFullYear()
149-
const isoYearStart = new Date(Date.UTC(isoYear, 0, 1))
150-
const weekNumber = Math.ceil(((+thursday - +isoYearStart) / 86400000 + 1) / 7)
151-
152-
return `${isoYear}-W${String(weekNumber).padStart(2, '0')}`
153-
}
154-
155125
function buildDailyEvolutionFromDaily(
156126
daily: Array<{ day: string; downloads: number }>,
157127
): DailyDownloadPoint[] {
@@ -161,30 +131,44 @@ function buildDailyEvolutionFromDaily(
161131
.map(item => ({ day: item.day, downloads: item.downloads }))
162132
}
163133

164-
function buildWeeklyEvolutionFromDaily(
134+
function buildRollingWeeklyEvolutionFromDaily(
165135
daily: Array<{ day: string; downloads: number }>,
136+
rangeStartIso: string,
137+
rangeEndIso: string,
166138
): WeeklyDownloadPoint[] {
167139
const sorted = daily.slice().sort((a, b) => a.day.localeCompare(b.day))
168-
const downloadsByWeekKey = new Map<string, number>()
140+
const rangeStartDate = parseIsoDateOnly(rangeStartIso)
141+
const rangeEndDate = parseIsoDateOnly(rangeEndIso)
142+
143+
const groupedByIndex = new Map<number, number>()
169144

170145
for (const item of sorted) {
171-
const weekKey = toIsoWeekKey(item.day)
172-
downloadsByWeekKey.set(weekKey, (downloadsByWeekKey.get(weekKey) ?? 0) + item.downloads)
173-
}
146+
const itemDate = parseIsoDateOnly(item.day)
147+
const dayOffset = Math.floor((itemDate.getTime() - rangeStartDate.getTime()) / 86400000)
148+
if (dayOffset < 0) continue
174149

175-
return Array.from(downloadsByWeekKey.entries())
176-
.sort(([a], [b]) => a.localeCompare(b))
177-
.map(([weekKey, downloads]) => {
178-
const weekStartDate = getIsoWeekStartDateFromWeekKey(weekKey)
179-
if (!weekStartDate) return { weekKey, downloads, weekStart: '-', weekEnd: '-' }
150+
const weekIndex = Math.floor(dayOffset / 7)
151+
groupedByIndex.set(weekIndex, (groupedByIndex.get(weekIndex) ?? 0) + item.downloads)
152+
}
180153

154+
return Array.from(groupedByIndex.entries())
155+
.sort(([a], [b]) => a - b)
156+
.map(([weekIndex, downloads]) => {
157+
const weekStartDate = addDays(rangeStartDate, weekIndex * 7)
181158
const weekEndDate = addDays(weekStartDate, 6)
182159

160+
// Clamp weekEnd to the actual data range end date
161+
const clampedWeekEndDate =
162+
weekEndDate.getTime() > rangeEndDate.getTime() ? rangeEndDate : weekEndDate
163+
164+
const weekStartIso = toIsoDateString(weekStartDate)
165+
const weekEndIso = toIsoDateString(clampedWeekEndDate)
166+
183167
return {
184-
weekKey,
185168
downloads,
186-
weekStart: toIsoDateString(weekStartDate),
187-
weekEnd: toIsoDateString(weekEndDate),
169+
weekKey: `${weekStartIso}_${weekEndIso}`,
170+
weekStart: weekStartIso,
171+
weekEnd: weekEndIso,
188172
}
189173
})
190174
}
@@ -341,6 +325,9 @@ export function useCharts() {
341325
)
342326
} else if (downloadEvolutionOptions.granularity === 'week') {
343327
const weekCount = downloadEvolutionOptions.weeks ?? 52
328+
329+
// Full rolling weeks ending on `end` (yesterday by default)
330+
// Range length is exactly weekCount * 7 days (inclusive)
344331
start = addDays(end, -(weekCount * 7) + 1)
345332
} else {
346333
start = addDays(end, -30 + 1)
@@ -362,14 +349,14 @@ export function useCharts() {
362349

363350
const { start, end } = resolveDateRange(resolvedOptions, resolvedCreatedIso)
364351

365-
const sortedDaily = await fetchDailyRangeChunked(
366-
resolvedPackageName,
367-
toIsoDateString(start),
368-
toIsoDateString(end),
369-
)
352+
const startIso = toIsoDateString(start)
353+
const endIso = toIsoDateString(end)
354+
355+
const sortedDaily = await fetchDailyRangeChunked(resolvedPackageName, startIso, endIso)
370356

371357
if (resolvedOptions.granularity === 'day') return buildDailyEvolutionFromDaily(sortedDaily)
372-
if (resolvedOptions.granularity === 'week') return buildWeeklyEvolutionFromDaily(sortedDaily)
358+
if (resolvedOptions.granularity === 'week')
359+
return buildRollingWeeklyEvolutionFromDaily(sortedDaily, startIso, endIso)
373360
if (resolvedOptions.granularity === 'month') return buildMonthlyEvolutionFromDaily(sortedDaily)
374361
return buildYearlyEvolutionFromDaily(sortedDaily)
375362
}

0 commit comments

Comments
 (0)