Skip to content

Commit

Permalink
Merge branch 'master' into update-to-v3
Browse files Browse the repository at this point in the history
  • Loading branch information
marnusw committed Mar 9, 2024
2 parents e69ecc7 + 61e6ea9 commit cd08c4b
Show file tree
Hide file tree
Showing 36 changed files with 4,183 additions and 3,558 deletions.
363 changes: 0 additions & 363 deletions .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs

This file was deleted.

893 changes: 893 additions & 0 deletions .yarn/releases/yarn-4.1.1.cjs

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
compressionLevel: mixed

enableGlobalCache: false

nodeLinker: node-modules

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"
- path: .yarn/plugins/@yarnpkg/plugin-outdated.cjs
spec: "https://github.com/mskelton/yarn-plugin-outdated/raw/v2.1.1/bundles/@yarnpkg/plugin-outdated.js"

yarnPath: .yarn/releases/yarn-3.6.4.cjs
yarnPath: .yarn/releases/yarn-4.1.1.cjs
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
### v2.0.1 (9 March 2024)

- [DOCS] Fix incorrect output comment (#270)
- [DEPS] Limit to date-fns 2.x (#262, #267)
- [REFACTOR] `tzTokenizeDate`: Remove weird unneeded regex (#254)
- [BUGFIX] Improving correctness of the `formatInTimeZone` close to the DST threshold (#247)
- [ENHANCEMENT] Use hourCycle for browsers that support hour cycle formatting (#231)
- [BUGFIX] Fix tzParseTimezone to parse 00:30 timezones properly (#229)

### v2.0.0 (30 January 2023)

- [BREAKING CHANGE] Optimize configuration for ESM exports (entry points for cjs / esm / typescript) (#212)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ const date = new Date('2014-10-25T10:46:20Z')

formatInTimeZone(date, 'America/New_York', 'yyyy-MM-dd HH:mm:ssXXX') // 2014-10-25 06:46:20-04:00
formatInTimeZone(date, 'America/New_York', 'yyyy-MM-dd HH:mm:ss zzz') // 2014-10-25 06:46:20 EST
formatInTimeZone(date, 'Europe/Paris', 'yyyy-MM-dd HH:mm:ss zzz') // 2014-10-25 10:46:20 GMT+2
formatInTimeZone(date, 'Europe/Paris', 'yyyy-MM-dd HH:mm:ss zzz') // 2014-10-25 12:46:20 GMT+2

// The time zone name is generated by the Intl API which works best when a locale is also provided
import enGB from 'date-fns/locale/en-GB'
Expand Down
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
2 changes: 1 addition & 1 deletion scripts/build/package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ set -e
root="$(pwd)/$(dirname "$0")/../.."
cd "$root" || exit 1

PATH="$(npm bin):$PATH"
#PATH="$(npm bin):$PATH"
# XXX: $PACKAGE_OUTPUT_PATH must be an absolute path!
dir=${PACKAGE_OUTPUT_PATH:-"$root/tmp/package"}

Expand Down
8 changes: 4 additions & 4 deletions src/_lib/tzParseTimezone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var patterns = {
timezone: /([Z+-].*)$/,
timezoneZ: /^(Z)$/,
timezoneHH: /^([+-]\d{2})$/,
timezoneHHMM: /^([+-]\d{2}):?(\d{2})$/,
timezoneHHMM: /^([+-])(\d{2}):?(\d{2})$/,
}

// Parse various time zone offset formats to an offset in milliseconds
Expand Down Expand Up @@ -44,15 +44,15 @@ export default function tzParseTimezone(timezoneString, date, isUtcDate) {
// ±hh:mm or ±hhmm
token = patterns.timezoneHHMM.exec(timezoneString)
if (token) {
hours = parseInt(token[1], 10)
var minutes = parseInt(token[2], 10)
hours = parseInt(token[2], 10)
var minutes = parseInt(token[3], 10)

if (!validateTimezone(hours, minutes)) {
return NaN
}

absoluteOffset = Math.abs(hours) * MILLISECONDS_IN_HOUR + minutes * MILLISECONDS_IN_MINUTE
return hours > 0 ? -absoluteOffset : absoluteOffset
return token[1] === '+' ? -absoluteOffset : absoluteOffset
}

// IANA time zone
Expand Down
4 changes: 4 additions & 0 deletions src/_lib/tzParseTimezone/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,22 @@ describe('tzParseTimezone', function () {

it('±hhmm time zone format', function () {
assert.equal(tzParseTimezone('-0430'), 270 * 60 * 1000)
assert.equal(tzParseTimezone('-0030'), 30 * 60 * 1000)
assert.equal(tzParseTimezone('+0230'), -150 * 60 * 1000)
assert.equal(tzParseTimezone('+0030'), -30 * 60 * 1000)
})

it('±hh:mm time zone format', function () {
assert.equal(tzParseTimezone('-23:59'), 1439 * 60 * 1000)
assert.equal(tzParseTimezone('-12:00'), 720 * 60 * 1000)
assert.equal(tzParseTimezone('-11:30'), 690 * 60 * 1000)
assert.equal(tzParseTimezone('-05:00'), 300 * 60 * 1000)
assert.equal(tzParseTimezone('-00:30'), 30 * 60 * 1000)
assert.equal(tzParseTimezone('+03:00'), -180 * 60 * 1000)
assert.equal(tzParseTimezone('+11:30'), -690 * 60 * 1000)
assert.equal(tzParseTimezone('+12:00'), -720 * 60 * 1000)
assert.equal(tzParseTimezone('+23:59'), -1439 * 60 * 1000)
assert.equal(tzParseTimezone('+00:30'), -30 * 60 * 1000)
})

it('IANA time zone', function () {
Expand Down
10 changes: 5 additions & 5 deletions src/_lib/tzTokenizeDate/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function partsOffset(dtf, date) {
}

function hackyOffset(dtf, date) {
var formatted = dtf.format(date).replace(/\u200E/g, '')
var formatted = dtf.format(date)
var parsed = /(\d+)\/(\d+)\/(\d+),? (\d+):(\d+):(\d+)/.exec(formatted)
// var [, fMonth, fDay, fYear, fHour, fMinute, fSecond] = parsed
// return [fYear, fMonth, fDay, fHour, fMinute, fSecond]
Expand All @@ -52,10 +52,10 @@ function getDateTimeFormat(timeZone) {
if (!dtfCache[timeZone]) {
// New browsers use `hourCycle`, IE and Chrome <73 does not support it and uses `hour12`
var testDateFormatted = new Intl.DateTimeFormat('en-US', {
hour12: false,
hourCycle: 'h23',
timeZone: 'America/New_York',
year: 'numeric',
month: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
Expand All @@ -67,7 +67,7 @@ function getDateTimeFormat(timeZone) {

dtfCache[timeZone] = hourCycleSupported
? new Intl.DateTimeFormat('en-US', {
hour12: false,
hourCycle: 'h23',
timeZone: timeZone,
year: 'numeric',
month: 'numeric',
Expand All @@ -77,7 +77,7 @@ function getDateTimeFormat(timeZone) {
second: '2-digit',
})
: new Intl.DateTimeFormat('en-US', {
hourCycle: 'h23',
hour12: false,
timeZone: timeZone,
year: 'numeric',
month: 'numeric',
Expand Down
18 changes: 8 additions & 10 deletions src/format/formatters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ var MILLISECONDS_IN_MINUTE = 60 * 1000
var formatters = {
// Timezone (ISO-8601. If offset is 0, output is always `'Z'`)
X: function (date, token, localize, options) {
var timezoneOffset = getTimeZoneOffset(options.timeZone, options._originalDate || date)
var timezoneOffset = getTimeZoneOffset(options.timeZone, date)

if (timezoneOffset === 0) {
return 'Z'
Expand Down Expand Up @@ -36,7 +36,7 @@ var formatters = {

// Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)
x: function (date, token, localize, options) {
var timezoneOffset = getTimeZoneOffset(options.timeZone, options._originalDate || date)
var timezoneOffset = getTimeZoneOffset(options.timeZone, date)

switch (token) {
// Hours and optional minutes
Expand All @@ -62,7 +62,7 @@ var formatters = {

// Timezone (GMT)
O: function (date, token, localize, options) {
var timezoneOffset = getTimeZoneOffset(options.timeZone, options._originalDate || date)
var timezoneOffset = getTimeZoneOffset(options.timeZone, date)

switch (token) {
// Short
Expand All @@ -79,18 +79,16 @@ var formatters = {

// Timezone (specific non-location)
z: function (date, token, localize, options) {
var originalDate = options._originalDate || date

switch (token) {
// Short
case 'z':
case 'zz':
case 'zzz':
return tzIntlTimeZoneName('short', originalDate, options)
return tzIntlTimeZoneName('short', date, options)
// Long
case 'zzzz':
default:
return tzIntlTimeZoneName('long', originalDate, options)
return tzIntlTimeZoneName('long', date, options)
}
},
}
Expand Down Expand Up @@ -131,16 +129,16 @@ function formatTimezoneWithOptionalMinutes(offset, dirtyDelimeter) {
return formatTimezone(offset, dirtyDelimeter)
}

function formatTimezoneShort(offset, dirtyDelimeter) {
function formatTimezoneShort(offset, dirtyDelimiter) {
var sign = offset > 0 ? '-' : '+'
var absOffset = Math.abs(offset)
var hours = Math.floor(absOffset / 60)
var minutes = absOffset % 60
if (minutes === 0) {
return sign + String(hours)
}
var delimeter = dirtyDelimeter || ''
return sign + String(hours) + delimeter + addLeadingZeros(minutes, 2)
var delimiter = dirtyDelimiter || ''
return sign + String(hours) + delimiter + addLeadingZeros(minutes, 2)
}

export default formatters
4 changes: 3 additions & 1 deletion src/format/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ 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] - can be used to pass the original unmodified date to `format` to
* improve correctness of the replaced timezone token close to the DST threshold.
* @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 +322,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?: FirstWeekContainsDate,
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 cloneDeep from 'lodash.clonedeep'
export default function formatInTimeZone(date, timeZone, formatStr, options) {
var extendedOptions = cloneDeep(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?: FirstWeekContainsDate,
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?: FirstWeekContainsDate,
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?: FirstWeekContainsDate,
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?: FirstWeekContainsDate,
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?: FirstWeekContainsDate,
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?: FirstWeekContainsDate,
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?: FirstWeekContainsDate,
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?: FirstWeekContainsDate,
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?: FirstWeekContainsDate,
additionalDigits?: 0 | 1 | 2,
timeZone?: string,
originalDate?: Date | number,
locale?: Locale,
includeSeconds?: boolean,
addSuffix?: boolean,
Expand Down
Loading

0 comments on commit cd08c4b

Please sign in to comment.