Last active
June 14, 2019 01:34
-
-
Save lukeaus/ce97e52f203231a222944cb0a24d9aeb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const _ = require('moment') | |
const MAX_MONTHS_TO_TEST_DST_OFFSET = 12; | |
const convertToMoment = (date) { | |
if (date instanceof moment) return date; | |
return new moment(date); | |
} | |
const wasDSTNowNot = (was, now = new moment()) => { | |
return DateHelper.convertToMoment(was).isDST() && !now.isDST(); | |
} | |
const wasNotDSTNowIs = (was, now = new moment()) => { | |
return !DateHelper.convertToMoment(was).isDST() && now.isDST(); | |
} | |
/** | |
* Returns the duration of daylight savings time (DST) for the moment's timezone | |
* @param {object} m moment | |
* @return {number} a duration in minutes | |
*/ | |
const durationDSTMins = m => { | |
const isDST = m_ => m_.isDST(); | |
const isNotDST = m_ => !m_.isDST(); | |
const utcOffsetOfOpposite = (m, oppositeCond) => { | |
let monthCounter = 1; | |
while (monthCounter <= MAX_MONTHS_TO_TEST_DST_OFFSET) { | |
const mNextMonth = new moment().add(monthCounter, 'month'); | |
if (oppositeCond(mNextMonth)) return mNextMonth.utcOffset(); | |
++monthCounter; | |
} | |
return 0; | |
}; | |
const calcDurationDSTMins = m => { | |
if (isDST(m) && utcOffsetOfOpposite(m, isNotDST)) { | |
return m.utcOffset() - utcOffsetOfOpposite(m, isNotDST); | |
} | |
if (utcOffsetOfOpposite(m, isDST)) { | |
return m.utcOffset() - utcOffsetOfOpposite(m, isDST); | |
} | |
return 0; | |
}; | |
return Math.abs(calcDurationDSTMins(m)); | |
} | |
/* | |
* Work around for sinon.fsinon.useFakeTimers().tick(ms) where new date ticking to crossing over | |
* a date that DST starts or ends. | |
* e.g. At the start of DST. the sinon clock might try and tick forward 7 hours in duration but | |
* it actually only moves 6 relative hours because the clock gets wound back an hour. | |
* So: | |
* if was DST --> now not DST, add DST duration worth of MS; or | |
* if was not DST --> now DST, subtract DST duration worth of MS | |
*/ | |
sinonClockTick = (clock, msToTick) => { | |
const mClockDate = new moment(clock.Date()); | |
const mClockDateToTickTo = new moment(mClockDate).add( | |
msToTick, | |
'milliseconds' | |
); | |
if (wasDSTNowNot(mClockDate, mClockDateToTickTo)) { | |
mClockDateToTickTo.add( | |
durationDSTMins(mClockDateToTickTo), | |
'minutes' | |
); | |
} else if (wasNotDSTNowIs(mClockDate, mClockDateToTickTo)) { | |
mClockDateToTickTo.subtract( | |
durationDSTMins(mClockDateToTickTo), | |
'minutes' | |
); | |
} | |
const msToTickDSTAware = mClockDateToTickTo.diff( | |
mClockDate, | |
'milliseconds' | |
); | |
clock.tick(msToTickDSTAware); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment