fix: timezoneOffset ignored in date when preserveTimezones is enabled, fixes #605

This commit is contained in:
Harttle
2023-04-25 01:28:48 +08:00
committed by Jun Yang
parent c2a8365054
commit 21ee27b575
4 changed files with 45 additions and 27 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ export function date (this: FilterImpl, v: string | Date, format?: string, timez
if (!isValidDate(date)) return v if (!isValidDate(date)) return v
if (timezoneOffset !== undefined) { if (timezoneOffset !== undefined) {
date = new TimezoneDate(date, parseTimezoneOffset(date, timezoneOffset)) date = new TimezoneDate(date, parseTimezoneOffset(date, timezoneOffset))
} else if (opts.timezoneOffset !== undefined) { } else if (!(date instanceof TimezoneDate) && opts.timezoneOffset !== undefined) {
date = new TimezoneDate(date, parseTimezoneOffset(date, opts.timezoneOffset)) date = new TimezoneDate(date, parseTimezoneOffset(date, opts.timezoneOffset))
} }
return strftime(date, format) return strftime(date, format)
+2 -2
View File
@@ -14,6 +14,6 @@ export interface LiquidDate {
getMonth(): number; getMonth(): number;
getFullYear(): number; getFullYear(): number;
getTimezoneOffset(): number; getTimezoneOffset(): number;
toLocaleTimeString(): string; toLocaleTimeString(locale?: string, init?: any): string;
toLocaleDateString(): string; toLocaleDateString(locale?: string, init?: any): string;
} }
+35 -23
View File
@@ -15,51 +15,63 @@ const ISO8601_TIMEZONE_PATTERN = /([zZ]|([+-])(\d{2}):(\d{2}))$/
export class TimezoneDate implements LiquidDate { export class TimezoneDate implements LiquidDate {
private timezoneOffset: number private timezoneOffset: number
private date: Date private date: Date
private displayDate: Date
constructor (init: string | number | Date | TimezoneDate, timezoneOffset: number) { constructor (init: string | number | Date | TimezoneDate, timezoneOffset: number) {
if (init instanceof TimezoneDate) { this.date = init instanceof TimezoneDate
this.date = init.date ? init.date
timezoneOffset = init.timezoneOffset : new Date(init)
} else {
const diff = (hostTimezoneOffset - timezoneOffset) * OneMinute
const time = new Date(init).getTime() + diff
this.date = new Date(time)
}
this.timezoneOffset = timezoneOffset this.timezoneOffset = timezoneOffset
const diff = (hostTimezoneOffset - this.timezoneOffset) * OneMinute
const time = this.date.getTime() + diff
this.displayDate = new Date(time)
} }
getTime () { getTime () {
return this.date.getTime() return this.displayDate.getTime()
} }
getMilliseconds () { getMilliseconds () {
return this.date.getMilliseconds() return this.displayDate.getMilliseconds()
} }
getSeconds () { getSeconds () {
return this.date.getSeconds() return this.displayDate.getSeconds()
} }
getMinutes () { getMinutes () {
return this.date.getMinutes() return this.displayDate.getMinutes()
} }
getHours () { getHours () {
return this.date.getHours() return this.displayDate.getHours()
} }
getDay () { getDay () {
return this.date.getDay() return this.displayDate.getDay()
} }
getDate () { getDate () {
return this.date.getDate() return this.displayDate.getDate()
} }
getMonth () { getMonth () {
return this.date.getMonth() return this.displayDate.getMonth()
} }
getFullYear () { getFullYear () {
return this.date.getFullYear() return this.displayDate.getFullYear()
} }
toLocaleTimeString (locale?: string) { toLocaleString (locale?: string, init?: any) {
return this.date.toLocaleTimeString(locale) if (locale === undefined) {
return this.displayDate.toLocaleString(locale)
}
return this.date.toLocaleString(locale, init)
} }
toLocaleDateString (locale?: string) { toLocaleTimeString (locale?: string, init?: any) {
return this.date.toLocaleDateString(locale) if (locale === undefined) {
return this.displayDate.toLocaleTimeString(locale)
}
return this.date.toLocaleTimeString(locale, init)
}
toLocaleDateString (locale?: string, init?: any) {
if (locale === undefined) {
return this.displayDate.toLocaleDateString(locale)
}
return this.date.toLocaleDateString(locale, init)
} }
getTimezoneOffset () { getTimezoneOffset () {
return this.timezoneOffset! return this.timezoneOffset!
@@ -87,8 +99,8 @@ export class TimezoneDate implements LiquidDate {
// has a timezone specified // has a timezone specified
if (m && m[2] && m[3] && m[4]) { if (m && m[2] && m[3] && m[4]) {
const [, , sign, hours, minutes] = m const [, , sign, hours, minutes] = m
const delta = (sign === '+' ? -1 : 1) * (parseInt(hours, 10) * 60 + parseInt(minutes, 10)) const offset = (sign === '+' ? -1 : 1) * (parseInt(hours, 10) * 60 + parseInt(minutes, 10))
return new TimezoneDate(+new Date(dateString), delta) return new TimezoneDate(+new Date(dateString), offset)
} }
return new Date(dateString) return new Date(dateString)
} }
+7 -1
View File
@@ -1,4 +1,5 @@
import { LiquidOptions } from '../../../src/liquid-options' import { LiquidOptions } from '../../../src/liquid-options'
import { Liquid } from '.././../../src/liquid'
import { test } from '../../stub/render' import { test } from '../../stub/render'
describe('filters/date', function () { describe('filters/date', function () {
@@ -98,10 +99,15 @@ describe('filters/date', function () {
const scope = { date: new Date('1990-12-31T23:00:00Z') } const scope = { date: new Date('1990-12-31T23:00:00Z') }
return test('{{ date | date: "%z"}}', scope, '-0600', opts) return test('{{ date | date: "%z"}}', scope, '-0600', opts)
}) })
it('should work with `preserveTimezones`', function () { it('opts.timezoneOffset should work with `preserveTimezones`', function () {
const opts: LiquidOptions = { timezoneOffset: 600, preserveTimezones: true } const opts: LiquidOptions = { timezoneOffset: 600, preserveTimezones: true }
return test('{{ "1990-12-31T23:00:00+02:30" | date: "%Y-%m-%dT%H:%M:%S"}}', '1990-12-31T23:00:00', undefined, opts) return test('{{ "1990-12-31T23:00:00+02:30" | date: "%Y-%m-%dT%H:%M:%S"}}', '1990-12-31T23:00:00', undefined, opts)
}) })
it('timezoneOffset should work with `preserveTimezones`', async () => {
const liquid = new Liquid({ preserveTimezones: true })
const html = liquid.parseAndRenderSync('{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", "Asia/Colombo" }}')
expect(html).toEqual('1991-01-01T04:30:00')
})
}) })
describe('dateFormat', function () { describe('dateFormat', function () {
const optsWithoutDateFormat: LiquidOptions = { timezoneOffset: 360 } // -06:00 const optsWithoutDateFormat: LiquidOptions = { timezoneOffset: 360 } // -06:00