Skip to content

Commit

Permalink
Fix issue spencermountain#182: wrong offset within 1hr of DST start
Browse files Browse the repository at this point in the history
Solved to Chicken and Egg Problem described in summerTime.js: "we can't get the date, without knowing the timezone, and vice-versa".
In order to eliminate the time zone offset effect the given UTC time is compared to the DST change boundaries converted to UTC.
  • Loading branch information
bsvetlik committed Oct 28, 2020
1 parent 14fd1ef commit a9f2acd
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/timezone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const timezone = s => {
if (result.hasDst === false) {
result.current.offset = summer
result.current.isDST = false
} else if (inSummerTime(s.epoch, result.change.start, result.change.back, summer) === true) {
} else if (inSummerTime(s.epoch, result.change.start, result.change.back, summer, winter) === true) {
result.current.offset = summer
result.current.isDST = result.hemisphere === 'North' //dst 'on' in winter in north
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/timezone/quick.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const quickOffset = s => {
dec = jul - 1
}
let split = obj.dst.split('->')
let inSummer = isSummer(s.epoch, split[0], split[1], jul)
let inSummer = isSummer(s.epoch, split[0], split[1], jul, dec)
if (inSummer === true) {
return jul
}
Expand Down
36 changes: 12 additions & 24 deletions src/timezone/summerTime.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
const zeroPad = require('../fns').zeroPad
const MSEC_IN_HOUR = 60 * 60 * 1000;

const serialize = d =>
zeroPad(d.getMonth() + 1) + '/' + zeroPad(d.getDate()) + ':' + zeroPad(d.getHours())
const toUtc = (dstChange, offset, year) => {
const [month, rest] = dstChange.split('/');
const [day, hour] = rest.split(':');
return Date.UTC(year, month - 1, day, hour) - offset * MSEC_IN_HOUR;
};

// a timezone will begin with a specific offset in january
// then some will switch to something else between november-march
const shouldChange = (epoch, start, end, defaultOffset) => {
//note: this has a cray order-of-operations issue
//we can't get the date, without knowing the timezone, and vice-versa
//it's possible that we can miss a dst-change by a few hours.
let d = new Date(epoch)
//(try to mediate this a little?)
let bias = d.getTimezoneOffset() || 0
let shift = bias + defaultOffset * 60 //in minutes
shift = shift * 60 * 1000 //in ms
d = new Date(epoch + shift)
const shouldChange = (epoch, start, end, summerOffset, winterOffset) => {
const year = new Date(epoch).getUTCFullYear();
const startUtc = toUtc(start, winterOffset, year);
const endUtc = toUtc(end, summerOffset, year);

let current = serialize(d)
//eg. is it after ~november?
if (current >= start) {
//eg. is it before ~march~ too?
if (current < end) {
return true
}
}
return false
return epoch >= startUtc && epoch < endUtc;
}

module.exports = shouldChange

0 comments on commit a9f2acd

Please sign in to comment.