Skip to content

Commit 89c6c76

Browse files
committed
feat: timezone name for opts.timezoneOffset and date argument, fixes #553
1 parent b7ab357 commit 89c6c76

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

src/filters/date.ts

+14-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { toValue, stringify, isString, isNumber, TimezoneDate, LiquidDate, strftime } from '../util'
22
import { FilterImpl } from '../template'
33

4-
export function date (this: FilterImpl, v: string | Date, format: string, timeZoneOffset?: number) {
4+
export function date (this: FilterImpl, v: string | Date, format: string, timezoneOffset?: number | string) {
55
const opts = this.context.opts
66
let date: LiquidDate
77
v = toValue(v)
@@ -22,14 +22,24 @@ export function date (this: FilterImpl, v: string | Date, format: string, timeZo
2222
date = v
2323
}
2424
if (!isValidDate(date)) return v
25-
if (timeZoneOffset !== undefined) {
26-
date = new TimezoneDate(date, timeZoneOffset)
25+
if (timezoneOffset !== undefined) {
26+
date = new TimezoneDate(date, parseTimezoneOffset(date, timezoneOffset))
2727
} else if (opts.timezoneOffset !== undefined) {
28-
date = new TimezoneDate(date, opts.timezoneOffset!)
28+
date = new TimezoneDate(date, parseTimezoneOffset(date, opts.timezoneOffset))
2929
}
3030
return strftime(date, format)
3131
}
3232

3333
function isValidDate (date: any): date is Date {
3434
return (date instanceof Date || date instanceof TimezoneDate) && !isNaN(date.getTime())
3535
}
36+
37+
/**
38+
* need pass in a `date` because offset is dependent on whether DST is active
39+
*/
40+
function parseTimezoneOffset (date: Date, timeZone: string | number) {
41+
if (isNumber(timeZone)) return timeZone
42+
const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }))
43+
const tzDate = new Date(date.toLocaleString('en-US', { timeZone }))
44+
return (utcDate.getTime() - tzDate.getTime()) / 6e4
45+
}

src/liquid-options.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ export interface LiquidOptions {
3535
ownPropertyOnly?: boolean;
3636
/** Modifies the behavior of `strictVariables`. If set, a single undefined variable will *not* cause an exception in the context of the `if`/`elsif`/`unless` tag and the `default` filter. Instead, it will evaluate to `false` and `null`, respectively. Irrelevant if `strictVariables` is not set. Defaults to `false`. **/
3737
lenientIf?: boolean;
38-
/** JavaScript timezoneOffset for `date` filter, default to local time. That means if you're in Australia (UTC+10), it'll default to -600 */
39-
timezoneOffset?: number;
38+
/** JavaScript timezone name or timezoneOffset for `date` filter, default to local time. That means if you're in Australia (UTC+10), it'll default to `-600` or `Australia/Lindeman` */
39+
timezoneOffset?: number | string;
4040
/** Strip blank characters (including ` `, `\t`, and `\r`) from the right of tags (`{% %}`) until `\n` (inclusive). Defaults to `false`. */
4141
trimTagRight?: boolean;
4242
/** Similar to `trimTagRight`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */

test/integration/filters/date.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,29 @@ describe('filters/date', function () {
6464
it('should support timezone offset argument', function () {
6565
return test('{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", 360}}', '1990-12-31T17:00:00')
6666
})
67+
it('should support timezone name argument', function () {
68+
return test('{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", "Asia/Colombo" }}', '1991-01-01T04:30:00')
69+
})
70+
it('should support timezone name argument when DST is not active', function () {
71+
return test('{{ "2021-01-01T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", "America/New_York" }}', '2021-01-01T18:00:00')
72+
})
73+
it('should support timezone name argument when DST is active', function () {
74+
return test('{{ "2021-06-01T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", "America/New_York" }}', '2021-06-01T19:00:00')
75+
})
6776
it('should offset date literal with timezone 00:00 specified', function () {
6877
return test('{{ "1990-12-31T23:00:00+00:00" | date: "%Y-%m-%dT%H:%M:%S"}}', '1990-12-31T17:00:00', undefined, opts)
6978
})
7079
it('should offset date literal with timezone -01:00 specified', function () {
7180
return test('{{ "1990-12-31T23:00:00-01:00" | date: "%Y-%m-%dT%H:%M:%S"}}', '1990-12-31T18:00:00', undefined, opts)
7281
})
73-
it('should offset date from scope', function () {
82+
it('should offset date from scope (timezone offset)', function () {
7483
const scope = { date: new Date('1990-12-31T23:00:00Z') }
7584
return test('{{ date | date: "%Y-%m-%dT%H:%M:%S"}}', scope, '1990-12-31T17:00:00', opts)
7685
})
86+
it('should offset date from scope (timezone name)', function () {
87+
const scope = { date: new Date('1990-12-31T23:00:00Z') }
88+
return test('{{ date | date: "%Y-%m-%dT%H:%M:%S"}}', scope, '1990-12-31T17:00:00', { timezoneOffset: 'America/Merida' })
89+
})
7790
it('should reflect timezoneOffset', function () {
7891
const scope = { date: new Date('1990-12-31T23:00:00Z') }
7992
return test('{{ date | date: "%z"}}', scope, '-0600', opts)

0 commit comments

Comments
 (0)