Skip to content

Commit

Permalink
Merge pull request #247 from asennikov/master
Browse files Browse the repository at this point in the history
Improving correctness of the `formatInTimeZone` close to the DST threshold
  • Loading branch information
marnusw authored Mar 9, 2024
2 parents 7f31fd6 + 1295a95 commit f6979d7
Show file tree
Hide file tree
Showing 25 changed files with 83 additions and 2 deletions.
2 changes: 2 additions & 0 deletions docs/OptionsWithTZ.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
* See [toDate]{@link https://date-fns.org/docs/toDate}
* @property {String} [timeZone=''] - used to specify the IANA time zone offset of a date String.
* Used by all functions that take String as Date-like argument.
* @property {Date|Number} [originalDate] - used to pick the correct IANA time zone of a date.
* Used by `format` function.
* @property {Locale} [locale=defaultLocale] - the locale object.
* Used by `formatDistance`, `formatDistanceStrict`, `format` and `parse`.
* See [Locale]{@link https://date-fns.org/docs/Locale}
Expand Down
3 changes: 2 additions & 1 deletion src/format/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ var tzFormattingTokensRegExp = /([xXOz]+)|''|'(''|[^'])+('|$)/g
* - Some of the local week-numbering year tokens (`YY`, `YYYY`) that are confused with the calendar year tokens
* (`yy`, `yyyy`). See: https://git.io/fxCyr
* @param {String} [options.timeZone=''] - used to specify the IANA time zone offset of a date String.
* @param {Date|Number} [options.originalDate] - used to pick the correct IANA time zone of a date.
* @returns {String} the formatted date string
* @throws {TypeError} 2 arguments required
* @throws {RangeError} `options.additionalDigits` must be 0, 1 or 2
Expand Down Expand Up @@ -320,7 +321,7 @@ export default function format(dirtyDate, dirtyFormatStr, dirtyOptions) {

var matches = formatStr.match(tzFormattingTokensRegExp)
if (matches) {
var date = toDate(dirtyDate, options)
var date = toDate(options.originalDate || dirtyDate, options)
// Work through each match and replace the tz token in the format string with the quoted
// formatted time zone so the remaining tokens can be filled in by date-fns#format.
formatStr = matches.reduce(function (result, token) {
Expand Down
1 change: 1 addition & 0 deletions src/format/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
2 changes: 1 addition & 1 deletion src/format/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ describe('format', function () {
assert(format(date, "''h 'o''clock'''") === "'5 o'clock'")
})

it('accepts new line charactor', function () {
it('accepts new line character', function () {
var date = new Date(2014, 3, 4, 5)
assert.equal(format(date, "yyyy-MM-dd'\n'HH:mm:ss"), '2014-04-04\n05:00:00')
})
Expand Down
1 change: 1 addition & 0 deletions src/formatInTimeZone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ import utcToZonedTime from '../utcToZonedTime/index.js'
export default function formatInTimeZone(date, timeZone, formatStr, options) {
var extendedOptions = cloneObject(options)
extendedOptions.timeZone = timeZone
extendedOptions.originalDate = date
return format(utcToZonedTime(date, timeZone), formatStr, extendedOptions)
}
1 change: 1 addition & 0 deletions src/formatInTimeZone/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
57 changes: 57 additions & 0 deletions src/formatInTimeZone/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import assert from 'power-assert'
import enGB from 'date-fns/locale/en-GB'
import formatInTimeZone from './index'

describe('formatInTimeZone', function () {
Expand Down Expand Up @@ -43,6 +44,62 @@ describe('formatInTimeZone', function () {
})
})

describe('populates the timezone name and offset correctly close to DST threshold', function () {
it('during summer time: CEST', function () {
var date = new Date('2021-08-01T00:30:00Z')
var timeZone = 'Europe/Paris'
var format = 'z XXX'
var expected = 'CEST +02:00'
var options = { locale: enGB }
assert(formatInTimeZone(date, timeZone, format, options) === expected)
})

it('during winter time: CET', function () {
var date = '2021-01-01T01:30:00Z'
var timeZone = 'Europe/Paris'
var format = 'z XXX'
var expected = 'CET +01:00'
var options = { locale: enGB }
assert(formatInTimeZone(date, timeZone, format, options) === expected)
})

it('before DST changeover: (CEST to CET)', function () {
var date = '2021-10-31T00:30:00Z'
var timeZone = 'Europe/Paris'
var format = 'z XXX'
var expected = 'CEST +02:00'
var options = { locale: enGB }
assert(formatInTimeZone(date, timeZone, format, options) === expected)
})

it('after DST changeover: (CEST to CET)', function () {
var date = '2021-10-31T01:30:00Z'
var timeZone = 'Europe/Paris'
var format = 'z XXX'
var expected = 'CET +01:00'
var options = { locale: enGB }
assert(formatInTimeZone(date, timeZone, format, options) === expected)
})

it('before DST changeover: (CET to CEST)', function () {
var date = '2021-03-28T00:30:00Z'
var timeZone = 'Europe/Paris'
var format = 'z XXX'
var expected = 'CET +01:00'
var options = { locale: enGB }
assert(formatInTimeZone(date, timeZone, format, options) === expected)
})

it('after DST changeover: (CET to CEST)', function () {
var date = '2021-03-28T01:30:00Z'
var timeZone = 'Europe/Paris'
var format = 'z XXX'
var expected = 'CEST +02:00'
var options = { locale: enGB }
assert(formatInTimeZone(date, timeZone, format, options) === expected)
})
})

it('throws a RangeError on invalid time zones', function () {
var date = '1986-04-04T10:32:55.123Z'
assert.throws(
Expand Down
1 change: 1 addition & 0 deletions src/fp/format/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/formatInTimeZone/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/formatInTimeZoneWithOptions/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/formatWithOptions/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/getTimezoneOffset/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/toDate/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/toDateWithOptions/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/utcToZonedTime/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/utcToZonedTimeWithOptions/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/zonedTimeToUtc/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/fp/zonedTimeToUtcWithOptions/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/getTimezoneOffset/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/toDate/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/utcToZonedTime/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions src/zonedTimeToUtc/index.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type OptionsWithTZ = {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
1 change: 1 addition & 0 deletions typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ declare module 'date-fns-tz' {
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7
additionalDigits?: 0 | 1 | 2
timeZone?: string
originalDate?: Date | number
locale?: Locale
includeSeconds?: boolean
addSuffix?: boolean
Expand Down

0 comments on commit f6979d7

Please sign in to comment.