diff --git a/scripts/test/dst.sh b/scripts/test/dst.sh new file mode 100755 index 0000000000..5256e69ec4 --- /dev/null +++ b/scripts/test/dst.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# The script runs the DST tests. +# +# It's a part of the test process. + +set -ex + +export PATH="$(yarn bin):$PATH" + +env TZ=America/Sao_Paulo babel-node ./test/dst/toDate/basic.js +env TZ=Pacific/Apia babel-node ./test/dst/toDate/samoa.js \ No newline at end of file diff --git a/scripts/test/travis.sh b/scripts/test/travis.sh index b4bcc50160..6f737d625c 100755 --- a/scripts/test/travis.sh +++ b/scripts/test/travis.sh @@ -21,6 +21,8 @@ then yarn test -- --single-run + ./scripts/test/dst.sh + prebuild ./scripts/test/tz.sh diff --git a/src/toDate/index.js b/src/toDate/index.js index 06a443e8ec..0151f3a099 100644 --- a/src/toDate/index.js +++ b/src/toDate/index.js @@ -186,11 +186,20 @@ export default function toDate(argument, dirtyOptions) { return new Date(NaN) } } else { - // get offset accurate to hour in timezones that change offset - offset = getTimezoneOffsetInMilliseconds(new Date(timestamp + time)) - offset = getTimezoneOffsetInMilliseconds( - new Date(timestamp + time + offset) - ) + 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) diff --git a/test/dst/toDate/basic.js b/test/dst/toDate/basic.js new file mode 100644 index 0000000000..058257c6a0 --- /dev/null +++ b/test/dst/toDate/basic.js @@ -0,0 +1,30 @@ +// This is basic DST test for toDate + +import toDate from '../../../src/toDate' +import assert from 'assert' + +if (process.env.TZ !== 'America/Sao_Paulo') + throw new Error('The test must be run with TZ=America/Sao_Paulo') + +if (parseInt(process.version.match(/^v(\d+)\./)[1]) < 10) + throw new Error('The test must be run on Node.js version >= 10') + +// Test DST start edge +assert.equal(toDate('2018-11-03').getDate(), 3) +assert.equal(toDate('2018-11-04').getDate(), 4) // DST start +assert.equal(toDate('2018-11-05').getDate(), 5) + +// Test DST end edge +assert.equal(toDate('2019-02-15').getDate(), 15) +assert.equal(toDate('2019-02-16').getDate(), 16) // DST end +assert.equal(toDate('2019-02-17').getDate(), 17) + +// Test creation of nonexistent time +assert.equal( + toDate('2018-11-04T00:00').toString(), + 'Sun Nov 04 2018 01:00:00 GMT-0200 (Brasilia Summer Time)' +) +assert.equal( + toDate('2018-11-04T00:30').toString(), + 'Sun Nov 04 2018 01:30:00 GMT-0200 (Brasilia Summer Time)' +) diff --git a/test/dst/toDate/samoa.js b/test/dst/toDate/samoa.js new file mode 100644 index 0000000000..5234f70b04 --- /dev/null +++ b/test/dst/toDate/samoa.js @@ -0,0 +1,16 @@ +// This is basic DST test for toDate + +import toDate from '../../../src/toDate' +import assert from 'assert' + +if (process.env.TZ !== 'Pacific/Apia') + throw new Error('The test must be run with TZ=Pacific/Apia') + +if (parseInt(process.version.match(/^v(\d+)\./)[1]) < 10) + throw new Error('The test must be run on Node.js version >= 10') + +assert.equal(toDate('2011-12-30').getDate(), 31) +assert.equal( + toDate('2011-12-30T03:30').toString(), + 'Sat Dec 31 2011 03:30:00 GMT+1400 (Apia Daylight Time)' +)