Skip to content

Commit

Permalink
Backport DST fix from v2 (#1005)
Browse files Browse the repository at this point in the history
See #1003
  • Loading branch information
kossnocorp committed Dec 10, 2018
1 parent 5522f20 commit 92a0f31
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,12 @@ This change log follows the format documented in [Keep a CHANGELOG].

## [Unreleased]

### Fixed

- [Fixed DST issue](https://github.com/date-fns/date-fns/pull/1005). See [#972](https://github.com/date-fns/date-fns/issues/972) and [#992](https://github.com/date-fns/date-fns/issues/992) for more details. This fix was backported from v2.

- Fix a few bugs that appear in timezones with offsets that include seconds (e.g. GMT+00:57:44). See PR [#789](https://github.com/date-fns/date-fns/issues/789). This fix was backported from v2.

## [1.29.0] - 2017-10-11

### Fixed
Expand Down
21 changes: 21 additions & 0 deletions src/_lib/getTimezoneOffsetInMilliseconds/index.js
@@ -0,0 +1,21 @@
var MILLISECONDS_IN_MINUTE = 60000

/**
* Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.
* They usually appear for dates that denote time before the timezones were introduced
* (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891
* and GMT+01:00:00 after that date)
*
* Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,
* which would lead to incorrect calculations.
*
* This function returns the timezone offset in milliseconds that takes seconds in account.
*/
module.exports = function getTimezoneOffsetInMilliseconds (dirtyDate) {
var date = new Date(dirtyDate.getTime())
var baseTimezoneOffset = date.getTimezoneOffset()
date.setSeconds(0, 0)
var millisecondsPartOfTimezoneOffset = date.getTime() % MILLISECONDS_IN_MINUTE

return baseTimezoneOffset * MILLISECONDS_IN_MINUTE + millisecondsPartOfTimezoneOffset
}
22 changes: 17 additions & 5 deletions src/parse/index.js
@@ -1,3 +1,4 @@
var getTimezoneOffsetInMilliseconds = require('../_lib/getTimezoneOffsetInMilliseconds/index.js')
var isDate = require('../is_date/index.js')

var MILLISECONDS_IN_HOUR = 3600000
Expand Down Expand Up @@ -107,14 +108,25 @@ function parse (argument, dirtyOptions) {
}

if (dateStrings.timezone) {
offset = parseTimezone(dateStrings.timezone)
offset = parseTimezone(dateStrings.timezone) * MILLISECONDS_IN_MINUTE
} else {
// get offset accurate to hour in timezones that change offset
offset = new Date(timestamp + time).getTimezoneOffset()
offset = new Date(timestamp + time + offset * MILLISECONDS_IN_MINUTE).getTimezoneOffset()
var fullTime = timestamp + time
var fullTimeDate = new Date(fullTime)

offset = getTimezoneOffsetInMilliseconds(fullTimeDate)

// Adjust time when it's coming from DST
var fullTimeDateNextDay = new Date(fullTime)
fullTimeDateNextDay.setDate(fullTimeDate.getDate() + 1)
var offsetDiff =
getTimezoneOffsetInMilliseconds(fullTimeDateNextDay) -
getTimezoneOffsetInMilliseconds(fullTimeDate)
if (offsetDiff > 0) {
offset += offsetDiff
}
}

return new Date(timestamp + time + offset * MILLISECONDS_IN_MINUTE)
return new Date(timestamp + time + offset)
} else {
return new Date(argument)
}
Expand Down

0 comments on commit 92a0f31

Please sign in to comment.