import assert from 'assert' ; import addMonths from '.' ; import { getDstTransitions } from '../../test/dst/tzOffsetTransitions' ; describe ( 'addMonths' , ( ) => { it ( 'adds the given number of months' , ( ) => { const result = addMonths ( new Date ( 2014 , 8 , 1 ) , 5 ) ; assert . deepStrictEqual ( result , new Date ( 2015 , 1 , 1 ) ) ; } ) ; it ( 'accepts a timestamp' , ( ) => { const result = addMonths ( new Date ( 2014 , 8 , 1 ) . getTime ( ) , 12 ) ; assert . deepStrictEqual ( result , new Date ( 2015 , 8 , 1 ) ) ; } ) ; it ( 'converts a fractional number to an integer' , ( ) => { const result = addMonths ( new Date ( 2014 , 8 , 1 ) , 5.75 ) ; assert . deepStrictEqual ( result , new Date ( 2015 , 1 , 1 ) ) ; } ) ; it ( 'implicitly converts number arguments' , ( ) => { const result = addMonths ( new Date ( 2014 , 8 , 1 ) , '5' ) ; assert . deepStrictEqual ( result , new Date ( 2015 , 1 , 1 ) ) ; } ) ; it ( 'does not mutate the original date' , ( ) => { const date = new Date ( 2014 , 8 , 1 ) ; addMonths ( date , 12 ) ; assert . deepStrictEqual ( date , new Date ( 2014 , 8 , 1 ) ) ; } ) ; it ( 'works well if the desired month has fewer days and the provided date is in the last day of a month' , ( ) => { const date = new Date ( 2014 , 11 , 31 ) ; const result = addMonths ( date , 2 ) ; assert . deepStrictEqual ( result , new Date ( 2015 , 1 , 28 ) ) ; } ) ; it ( 'handles dates before 100 AD' , ( ) => { const initialDate = new Date ( 0 ) ; initialDate . setFullYear ( 0 , 0 , 31 ) ; initialDate . setHours ( 0 , 0 , 0 , 0 ) ; const expectedResult = new Date ( 0 ) ; expectedResult . setFullYear ( 0 , 1 , 29 ) ; expectedResult . setHours ( 0 , 0 , 0 , 0 ) ; const result = addMonths ( initialDate , 1 ) ; assert . deepStrictEqual ( result , expectedResult ) ; } ) ; it ( 'returns `Invalid Date` if the given date is invalid' , ( ) => { const result = addMonths ( new Date ( NaN ) , 5 ) ; assert ( result instanceof Date && isNaN ( result . getTime ( ) ) ) ; } ) ; it ( 'returns `Invalid Date` if the given amount is NaN' , ( ) => { const result = addMonths ( new Date ( 2014 , 8 , 1 ) , NaN ) ; assert ( result instanceof Date && isNaN ( result . getTime ( ) ) ) ; } ) ; it ( 'throws TypeError exception if passed less than 2 arguments' , ( ) => { assert . throws ( addMonths . bind ( null ) , TypeError ) ; assert . throws ( addMonths . bind ( null , 1 ) , TypeError ) ; } ) ; const dstTransitions = getDstTransitions ( 2017 ) ; const dstOnly = dstTransitions . start && dstTransitions . end ? it : it . skip ; const tz = Intl . DateTimeFormat ( ) . resolvedOptions ( ) . timeZone || process . env . tz ; const HOUR = 1000 * 60 * 60 ; const override = ( base , year = base . getFullYear ( ) , month = base . getMonth ( ) , day = base . getDate ( ) , hour = base . getHours ( ) , minute = base . getMinutes ( ) ) => new Date ( year , month , day , hour , minute ) ; dstOnly ( `works at DST-start boundary in local timezone: ${ tz || '(unknown)' }` , ( ) => { const date = dstTransitions . start ; const result = addMonths ( date ! , 2 ) ; assert . deepStrictEqual ( result , override ( date ! , date ! . getFullYear ( ) , date ! . getMonth ( ) + 2 ) ) ; } ) ; dstOnly ( `works at DST-start - 30 mins in local timezone: ${ tz || '(unknown)' }` , ( ) => { const date = new Date ( dstTransitions . start ! . getTime ( ) - 0.5 * HOUR ) ; const result = addMonths ( date , 2 ) ; const expected = override ( date , date . getFullYear ( ) , date . getMonth ( ) + 2 ) ; assert . deepStrictEqual ( result , expected ) ; } ) ; dstOnly ( `works at DST-start - 60 mins in local timezone: ${ tz || '(unknown)' }` , ( ) => { const date = new Date ( dstTransitions . start ! . getTime ( ) - 1 * HOUR ) ; const result = addMonths ( date , 2 ) ; const expected = override ( date , date . getFullYear ( ) , date . getMonth ( ) + 2 ) ; assert . deepStrictEqual ( result , expected ) ; } ) ; dstOnly ( `works at DST-end boundary in local timezone: ${ tz || '(unknown)' }` , ( ) => { const date = dstTransitions . end ; const result = addMonths ( date ! , 2 ) ; assert . deepStrictEqual ( result , override ( date ! , date ! . getFullYear ( ) + ( date ! . getMonth ( ) >= 10 ? 1 : 0 ) , ( date ! . getMonth ( ) + 2 ) % 12 ) ) ; } ) ; dstOnly ( `works at DST-end - 30 mins in local timezone: ${ tz || '(unknown)' }` , ( ) => { const date = new Date ( dstTransitions . end ! . getTime ( ) - 0.5 * HOUR ) ; const result = addMonths ( date , 2 ) ; assert . deepStrictEqual ( result , override ( date , date . getFullYear ( ) + ( date . getMonth ( ) >= 10 ? 1 : 0 ) , ( date . getMonth ( ) + 2 ) % 12 ) ) ; } ) ; dstOnly ( `works at DST-end - 60 mins in local timezone: ${ tz || '(unknown)' }` , ( ) => { const date = new Date ( dstTransitions . end ! . getTime ( ) - 1 * HOUR ) ; const result = addMonths ( date , 2 ) ; assert . deepStrictEqual ( result , override ( date , date . getFullYear ( ) + ( date . getMonth ( ) >= 10 ? 1 : 0 ) , ( date . getMonth ( ) + 2 ) % 12 ) ) ; } ) ; dstOnly ( `doesn't mutate if zero increment is used: ${ tz || '(unknown)' }` , ( ) => { const date = new Date ( dstTransitions . end ! ) ; const result = addMonths ( date , 0 ) ; assert . deepStrictEqual ( result , date ) ; } ) ; } ) ;