2024-02-16 01:21:13 +03:00
import dayjs from 'dayjs' ;
2024-05-05 18:36:53 -07:00
import utc from 'dayjs/plugin/utc.js' ;
2024-07-07 17:32:30 +02:00
import { getCurrentLocale } from '../utils.ts' ;
2024-08-28 18:32:38 +02:00
import type { ConfigType } from 'dayjs' ;
2024-02-16 01:21:13 +03:00
2024-05-05 18:36:53 -07:00
dayjs . extend ( utc ) ;
/ * *
* Returns an array of millisecond - timestamps of start - of - week days ( Sundays )
*
2024-08-28 18:32:38 +02:00
* @param startDate The start date . Can take any type that dayjs accepts .
* @param endDate The end date . Can take any type that dayjs accepts .
2024-05-05 18:36:53 -07:00
* /
2024-08-28 18:32:38 +02:00
export function startDaysBetween ( startDate : ConfigType , endDate : ConfigType ) : number [ ] {
2024-05-05 18:36:53 -07:00
const start = dayjs . utc ( startDate ) ;
const end = dayjs . utc ( endDate ) ;
let current = start ;
2024-02-16 01:21:13 +03:00
// Ensure the start date is a Sunday
2024-05-05 18:36:53 -07:00
while ( current . day ( ) !== 0 ) {
current = current . add ( 1 , 'day' ) ;
2024-02-16 01:21:13 +03:00
}
2024-08-28 18:32:38 +02:00
const startDays : number [ ] = [ ] ;
2024-02-16 01:21:13 +03:00
while ( current . isBefore ( end ) ) {
startDays . push ( current . valueOf ( ) ) ;
2024-05-05 18:36:53 -07:00
current = current . add ( 1 , 'week' ) ;
2024-02-16 01:21:13 +03:00
}
return startDays ;
}
2024-08-28 18:32:38 +02:00
export function firstStartDateAfterDate ( inputDate : Date ) : number {
2024-02-16 01:21:13 +03:00
if ( ! ( inputDate instanceof Date ) ) {
throw new Error ( 'Invalid date' ) ;
}
2024-05-05 18:36:53 -07:00
const dayOfWeek = inputDate . getUTCDay ( ) ;
2024-02-16 01:21:13 +03:00
const daysUntilSunday = 7 - dayOfWeek ;
const resultDate = new Date ( inputDate . getTime ( ) ) ;
2024-05-05 18:36:53 -07:00
resultDate . setUTCDate ( resultDate . getUTCDate ( ) + daysUntilSunday ) ;
2024-02-16 01:21:13 +03:00
return resultDate . valueOf ( ) ;
}
2024-10-28 21:15:05 +01:00
export type DayData = {
2024-08-28 18:32:38 +02:00
week : number ,
additions : number ,
deletions : number ,
commits : number ,
}
2024-12-08 03:58:18 +01:00
export type DayDataObject = {
[ timestamp : string ] : DayData ,
}
export function fillEmptyStartDaysWithZeroes ( startDays : number [ ] , data : DayDataObject ) : DayData [ ] {
2024-02-16 01:21:13 +03:00
const result = { } ;
for ( const startDay of startDays ) {
result [ startDay ] = data [ startDay ] || { 'week' : startDay , 'additions' : 0 , 'deletions' : 0 , 'commits' : 0 } ;
}
return Object . values ( result ) ;
}
2024-03-08 08:57:52 +01:00
2024-08-28 18:32:38 +02:00
let dateFormat : Intl.DateTimeFormat ;
2024-03-08 08:57:52 +01:00
// format a Date object to document's locale, but with 24h format from user's current locale because this
// option is a personal preference of the user, not something that the document's locale should dictate.
2024-08-28 18:32:38 +02:00
export function formatDatetime ( date : Date | number ) : string {
2024-03-08 08:57:52 +01:00
if ( ! dateFormat ) {
// TODO: replace `hour12` with `Intl.Locale.prototype.getHourCycles` once there is broad browser support
dateFormat = new Intl . DateTimeFormat ( getCurrentLocale ( ) , {
day : 'numeric' ,
month : 'short' ,
year : 'numeric' ,
hour : 'numeric' ,
hour12 : ! Number . isInteger ( Number ( new Intl . DateTimeFormat ( [ ] , { hour : 'numeric' } ) . format ( ) ) ) ,
minute : '2-digit' ,
timeZoneName : 'short' ,
} ) ;
}
return dateFormat . format ( date ) ;
}