fix: allow %Z for TimezoneDate, update docs accordingly #684

This commit is contained in:
Yang Jun
2024-04-21 15:57:43 +08:00
committed by Jun Yang
parent d48ac56824
commit e09657c52b
10 changed files with 79 additions and 42 deletions
+1
View File
@@ -14,6 +14,7 @@ export interface LiquidDate {
getMonth(): number;
getFullYear(): number;
getTimezoneOffset(): number;
getTimezoneName?(): string;
toLocaleTimeString(): string;
toLocaleDateString(): string;
}
+15 -8
View File
@@ -105,6 +105,15 @@ const padChars = {
p: ' ',
P: ' '
}
function getTimezoneOffset (d: LiquidDate, opts: FormatOptions) {
const nOffset = Math.abs(d.getTimezoneOffset())
const h = Math.floor(nOffset / 60)
const m = nOffset % 60
return (d.getTimezoneOffset() > 0 ? '-' : '+') +
padStart(h, 2, '0') +
(opts.flags[':'] ? ':' : '') +
padStart(m, 2, '0')
}
const formatCodes = {
a: (d: LiquidDate) => dayNamesShort[d.getDay()],
A: (d: LiquidDate) => dayNames[d.getDay()],
@@ -140,14 +149,12 @@ const formatCodes = {
X: (d: LiquidDate) => d.toLocaleTimeString(),
y: (d: LiquidDate) => d.getFullYear().toString().slice(2, 4),
Y: (d: LiquidDate) => d.getFullYear(),
z: (d: LiquidDate, opts: FormatOptions) => {
const nOffset = Math.abs(d.getTimezoneOffset())
const h = Math.floor(nOffset / 60)
const m = nOffset % 60
return (d.getTimezoneOffset() > 0 ? '-' : '+') +
padStart(h, 2, '0') +
(opts.flags[':'] ? ':' : '') +
padStart(m, 2, '0')
z: getTimezoneOffset,
Z: (d: LiquidDate, opts: FormatOptions) => {
if (d.getTimezoneName) {
return d.getTimezoneName() || getTimezoneOffset(d, opts)
}
return (typeof Intl !== 'undefined' ? Intl.DateTimeFormat().resolvedOptions().timeZone : '')
},
't': () => '\t',
'n': () => '\n',
+16 -2
View File
@@ -1,4 +1,5 @@
import { LiquidDate } from './liquid-date'
import { isString } from './underscore'
// one minute in milliseconds
const OneMinute = 60000
@@ -13,13 +14,15 @@ const ISO8601_TIMEZONE_PATTERN = /([zZ]|([+-])(\d{2}):(\d{2}))$/
*/
export class TimezoneDate implements LiquidDate {
private timezoneOffset: number
private timezoneName: string
private date: Date
private displayDate: Date
constructor (init: string | number | Date | TimezoneDate, timezoneOffset: number) {
constructor (init: string | number | Date | TimezoneDate, timezone: number | string) {
this.date = init instanceof TimezoneDate
? init.date
: new Date(init)
this.timezoneOffset = timezoneOffset
this.timezoneOffset = isString(timezone) ? TimezoneDate.getTimezoneOffset(timezone, this.date) : timezone
this.timezoneName = isString(timezone) ? timezone : ''
const diff = (this.date.getTimezoneOffset() - this.timezoneOffset) * OneMinute
const time = this.date.getTime() + diff
@@ -69,6 +72,9 @@ export class TimezoneDate implements LiquidDate {
getTimezoneOffset () {
return this.timezoneOffset!
}
getTimezoneName () {
return this.timezoneName
}
/**
* Create a Date object fixed to it's declared Timezone. Both
@@ -97,4 +103,12 @@ export class TimezoneDate implements LiquidDate {
}
return new Date(dateString)
}
private static getTimezoneOffset (timezoneName: string, date = new Date()) {
const localDateString = date.toLocaleString('en-US', { timeZone: timezoneName })
const utcDateString = date.toLocaleString('en-US', { timeZone: 'UTC' })
const localDate = new Date(localDateString)
const utcDate = new Date(utcDateString)
return (+utcDate - +localDate) / (60 * 1000)
}
}