@@ -5,34 +5,7 @@ import type {
55 WeeklyDataPoint ,
66 YearlyDataPoint ,
77} from '~/types/chart'
8-
9- // ---------------------------------------------------------------------------
10- // Date helpers
11- // ---------------------------------------------------------------------------
12-
13- const DAY_MS = 86_400_000
14-
15- function parseIso ( value : string ) : Date {
16- return new Date ( `${ value } T00:00:00.000Z` )
17- }
18-
19- function toIso ( date : Date ) : string {
20- return date . toISOString ( ) . slice ( 0 , 10 )
21- }
22-
23- function addDays ( date : Date , days : number ) : Date {
24- const d = new Date ( date )
25- d . setUTCDate ( d . getUTCDate ( ) + days )
26- return d
27- }
28-
29- function daysInMonth ( year : number , month : number ) : number {
30- return new Date ( Date . UTC ( year , month + 1 , 0 ) ) . getUTCDate ( )
31- }
32-
33- function daysInYear ( year : number ) : number {
34- return year % 4 === 0 && ( year % 100 !== 0 || year % 400 === 0 ) ? 366 : 365
35- }
8+ import { DAY_MS , parseIsoDate , toIsoDate , addDays , daysInMonth , daysInYear } from '~/utils/date'
369
3710// ---------------------------------------------------------------------------
3811// Fill partial bucket
@@ -52,7 +25,11 @@ export function buildDailyEvolution(daily: DailyRawPoint[]): DailyDataPoint[] {
5225 return daily
5326 . slice ( )
5427 . sort ( ( a , b ) => a . day . localeCompare ( b . day ) )
55- . map ( item => ( { day : item . day , value : item . value , timestamp : parseIso ( item . day ) . getTime ( ) } ) )
28+ . map ( item => ( {
29+ day : item . day ,
30+ value : item . value ,
31+ timestamp : parseIsoDate ( item . day ) . getTime ( ) ,
32+ } ) )
5633}
5734
5835export function buildWeeklyEvolution (
@@ -63,18 +40,18 @@ export function buildWeeklyEvolution(
6340 const sorted = daily . slice ( ) . sort ( ( a , b ) => a . day . localeCompare ( b . day ) )
6441 if ( sorted . length === 0 ) return [ ]
6542
66- const rangeStartDate = parseIso ( rangeStartIso )
43+ const rangeStartDate = parseIsoDate ( rangeStartIso )
6744
6845 // Align from last day with actual data (npm has 1-2 day delay, today is incomplete)
6946 const lastNonZero = sorted . findLast ( d => d . value > 0 )
70- const pickerEnd = parseIso ( rangeEndIso )
71- const effectiveEnd = lastNonZero ? parseIso ( lastNonZero . day ) : pickerEnd
47+ const pickerEnd = parseIsoDate ( rangeEndIso )
48+ const effectiveEnd = lastNonZero ? parseIsoDate ( lastNonZero . day ) : pickerEnd
7249 const rangeEndDate = effectiveEnd . getTime ( ) < pickerEnd . getTime ( ) ? effectiveEnd : pickerEnd
7350
7451 // Group into 7-day buckets from END backwards
7552 const buckets = new Map < number , number > ( )
7653 for ( const item of sorted ) {
77- const offset = Math . floor ( ( rangeEndDate . getTime ( ) - parseIso ( item . day ) . getTime ( ) ) / DAY_MS )
54+ const offset = Math . floor ( ( rangeEndDate . getTime ( ) - parseIsoDate ( item . day ) . getTime ( ) ) / DAY_MS )
7855 if ( offset < 0 ) continue
7956 const idx = Math . floor ( offset / 7 )
8057 buckets . set ( idx , ( buckets . get ( idx ) ?? 0 ) + item . value )
@@ -94,8 +71,8 @@ export function buildWeeklyEvolution(
9471 value = fillPartialBucket ( value , actualDays , 7 )
9572 }
9673
97- const weekStartIso = toIso ( weekStartDate )
98- const weekEndIso = toIso ( weekEndDate )
74+ const weekStartIso = toIsoDate ( weekStartDate )
75+ const weekEndIso = toIsoDate ( weekEndDate )
9976 return {
10077 value,
10178 weekKey : `${ weekStartIso } _${ weekEndIso } ` ,
@@ -134,7 +111,7 @@ export function buildMonthlyEvolution(
134111 if ( endDay < total ) value = fillPartialBucket ( value , endDay , total )
135112 }
136113
137- return { month, value, timestamp : parseIso ( `${ month } -01` ) . getTime ( ) }
114+ return { month, value, timestamp : parseIsoDate ( `${ month } -01` ) . getTime ( ) }
138115 } )
139116}
140117
@@ -154,17 +131,17 @@ export function buildYearlyEvolution(
154131
155132 return entries . map ( ( [ year , value ] , i ) => {
156133 const total = daysInYear ( Number ( year ) )
157- const yearStart = parseIso ( `${ year } -01-01` )
134+ const yearStart = parseIsoDate ( `${ year } -01-01` )
158135
159136 if ( i === 0 && rangeStartIso ) {
160137 const dayOfYear = Math . floor (
161- ( parseIso ( rangeStartIso ) . getTime ( ) - yearStart . getTime ( ) ) / DAY_MS ,
138+ ( parseIsoDate ( rangeStartIso ) . getTime ( ) - yearStart . getTime ( ) ) / DAY_MS ,
162139 )
163140 if ( dayOfYear > 0 ) value = fillPartialBucket ( value , total - dayOfYear , total )
164141 }
165142 if ( i === entries . length - 1 && rangeEndIso ) {
166143 const actualDays =
167- Math . floor ( ( parseIso ( rangeEndIso ) . getTime ( ) - yearStart . getTime ( ) ) / DAY_MS ) + 1
144+ Math . floor ( ( parseIsoDate ( rangeEndIso ) . getTime ( ) - yearStart . getTime ( ) ) / DAY_MS ) + 1
168145 if ( actualDays < total ) value = fillPartialBucket ( value , actualDays , total )
169146 }
170147
0 commit comments