Skip to content

Instantly share code, notes, and snippets.

@lukeaus
Last active June 14, 2019 01:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukeaus/ce97e52f203231a222944cb0a24d9aeb to your computer and use it in GitHub Desktop.
Save lukeaus/ce97e52f203231a222944cb0a24d9aeb to your computer and use it in GitHub Desktop.
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