import { ParsedOptions } from '../types' ; import dateutil from '../dateutil' ; import { empty , repeat , pymod , includes } from '../helpers' ; import { M365MASK , MDAY365MASK , NMDAY365MASK , WDAYMASK , M365RANGE , M366MASK , MDAY366MASK , NMDAY366MASK , M366RANGE } from '../masks' ; export interface YearInfo { yearlen : 365 | 366 ; nextyearlen : 365 | 366 ; yearordinal : number ; yearweekday : number ; mmask : number [ ] ; mrange : number [ ] ; mdaymask : number [ ] ; nmdaymask : number [ ] ; wdaymask : number [ ] ; wnomask : number [ ] | null ; } export function rebuildYear ( year , options ) { const firstyday = new Date ( Date . UTC ( year , 0 , 1 ) ) ; const yearlen = dateutil . isLeapYear ( year ) ? 366 : 365 ; const nextyearlen = dateutil . isLeapYear ( year + 1 ) ? 366 : 365 ; const yearordinal = dateutil . toOrdinal ( firstyday ) ; const yearweekday = dateutil . getWeekday ( firstyday ) ; const result = { yearlen , nextyearlen , yearordinal , yearweekday , ... baseYearMasks ( year ) , wnomask : null } ; if ( empty ( options . byweekno ) ) { return result ; } result . wnomask = repeat ( 0 , yearlen + 7 ) as number [ ] ; let firstwkst ; let wyearlen ; let no1wkst = firstwkst = pymod ( 7 - yearweekday + options . wkst , 7 ) ; if ( no1wkst >= 4 ) { no1wkst = 0 ; wyearlen = result . yearlen + pymod ( yearweekday - options . wkst , 7 ) ; } else { wyearlen = yearlen - no1wkst ; } const div = Math . floor ( wyearlen / 7 ) ; const mod = pymod ( wyearlen , 7 ) ; const numweeks = Math . floor ( div + mod / 4 ) ; for ( let j = 0 ; j < options . byweekno . length ; j ++ ) { let n = options . byweekno [ j ] ; if ( n < 0 ) { n += numweeks + 1 ; } if ( ! ( n > 0 && n <= numweeks ) ) { continue ; } let i ; if ( n > 1 ) { i = no1wkst + ( n - 1 ) * 7 ; if ( no1wkst !== firstwkst ) { i -= 7 - firstwkst ; } } else { i = no1wkst ; } for ( let k = 0 ; k < 7 ; k ++ ) { result . wnomask [ i ] = 1 ; i ++ ; if ( result . wdaymask [ i ] === options . wkst ) break ; } } if ( includes ( options . byweekno , 1 ) ) { let i = no1wkst + numweeks * 7 ; if ( no1wkst !== firstwkst ) i -= 7 - firstwkst ; if ( i < yearlen ) { for ( let j = 0 ; j < 7 ; j ++ ) { result . wnomask [ i ] = 1 ; i += 1 ; if ( result . wdaymask [ i ] === options . wkst ) break ; } } } if ( no1wkst ) { let lnumweeks ; if ( ! includes ( options . byweekno , - 1 ) ) { const lyearweekday = dateutil . getWeekday ( new Date ( Date . UTC ( year - 1 , 0 , 1 ) ) ) ; let lno1wkst = pymod ( 7 - lyearweekday . valueOf ( ) + options . wkst , 7 ) ; const lyearlen = dateutil . isLeapYear ( year - 1 ) ? 366 : 365 ; let weekst ; if ( lno1wkst >= 4 ) { lno1wkst = 0 ; weekst = lyearlen + pymod ( lyearweekday - options . wkst , 7 ) ; } else { weekst = yearlen - no1wkst ; } lnumweeks = Math . floor ( 52 + pymod ( weekst , 7 ) / 4 ) ; } else { lnumweeks = - 1 ; } if ( includes ( options . byweekno , lnumweeks ) ) { for ( let i = 0 ; i < no1wkst ; i ++ ) result . wnomask [ i ] = 1 ; } } return result ; } function baseYearMasks ( year ) { const yearlen = dateutil . isLeapYear ( year ) ? 366 : 365 ; const firstyday = new Date ( Date . UTC ( year , 0 , 1 ) ) ; const wday = dateutil . getWeekday ( firstyday ) ; if ( yearlen === 365 ) { return { mmask : M365MASK as number [ ] , mdaymask : MDAY365MASK , nmdaymask : NMDAY365MASK , wdaymask : WDAYMASK . slice ( wday ) , mrange : M365RANGE } ; } return { mmask : M366MASK as number [ ] , mdaymask : MDAY366MASK , nmdaymask : NMDAY366MASK , wdaymask : WDAYMASK . slice ( wday ) , mrange : M366RANGE } ; }