Skip to content

Commit

Permalink
feat: LiquidOptions.dateFormat to override default date format (#587)
Browse files Browse the repository at this point in the history
doc: updates related to LiquidOptions.dateFormat
doc: revamped the date filter doc for easier reference
  • Loading branch information
prassie authored Feb 22, 2023
1 parent d9cac4e commit 3fb6646
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 56 deletions.
99 changes: 44 additions & 55 deletions docs/source/filters/date.md
Original file line number Diff line number Diff line change
@@ -1,77 +1,66 @@
---
title: date
---

{% since %}v1.9.1{% endsince %}

Converts a timestamp into another date format. LiquidJS tries to be conformant with Shopify/Liquid which is using Ruby's core [Time#strftime(string)](http://www.ruby-doc.org/core/Time.html#method-i-strftime). The input is firstly converted to `Date` object via [new Date()][newDate].

Input
# Format
* Converts a timestamp into another date format
* LiquidJS tries to be conformant with Shopify/Liquid which is using Ruby's core [Time#strftime(string)](http://www.ruby-doc.org/core/Time.html#method-i-strftime)
* Refer [format flags](https://ruby-doc.org/core/strftime_formatting_rdoc.html)
* Not all options are supported though - refer [differences here](/tutorials/differences.html#Differences)
* The input is firstly converted to `Date` object via [new Date()][jsDate]
* Date format can be provided individually as a filter option
* If not provided, then `%A, %B %-e, %Y at %-l:%M %P %z` format will be used as default format
* Override this using [`dateFormat`](/api/interfaces/liquid_options_.liquidoptions.html#Optional-dateFormat) LiquidJS option, to set your preferred default format for all date filters

### Examples
```liquid
{{ article.published_at | date: "%a, %b %d, %y" }}
```
{{ article.published_at | date: '%a, %b %d, %y' }} => Fri, Jul 17, 15
{{ "now" | date: "%Y-%m-%d %H:%M" }} => 2020-03-25 15:57
Output
```text
Fri, Jul 17, 15
// equivalent to setting options.dateFormat = %d%q of %b %Y at %I:%M %P %Z
{{ '1990-12-31T23:30:28Z' | date: '%d%q of %b %Y at %I:%M %P %Z', -330 }} => 01st of Jan 1991 at 05:00 am +0530;
```

{% note info TimeZone %}
Date will be converted to local time before output. To avoid that, you can set `timezoneOffset` LiquidJS option to `0`, its default value is your local timezone offset which can be obtained by `new Date().getTimezoneOffset()`.
{% endnote %}

And you can set a timezone for each individual `date` filter via the second parameter:

Input
# TimeZone
* By default, dates will be converted to local timezone before output
* You can override that by,
* setting a timezone for each individual `date` filter via the second parameter
* using the [`timezoneOffset`](/api/interfaces/liquid_options_.liquidoptions.html#Optional-timezoneOffset) LiquidJS option
* Its default value is your local timezone offset which can be obtained by `new Date().getTimezoneOffset()`
* Offset can be set as,
* minutes: `-360` means `'+06:00'` and `360` means `'-06:00'`
* timeZone ID: `Asia/Colombo` or `America/New_York`
* Use minutes for better performance with repeated processing of templates with many dates like, converting template for each email recipient
* Refer [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for TZ database values

### Examples
```liquid
{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", 360}} // equivalent to setting `options.timezoneOffset` to `360`.
{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", "Asia/Colombo" }}
// equivalent to setting `options.timezoneOffset` to `360`
{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", 360 }} => 1990-12-31T17:00:00
{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", "Asia/Colombo" }} => 1991-01-01T04:30:00
```

Output
```liquid
1990-12-31T17:00:00
1991-01-01T04:30:00
```

Input
```liquid
{{ article.published_at | date: "%Y" }}
```
# Input
* `date` works on strings if they contain well-formatted dates
* Note that LiquidJS is using [JavaScript Date][jsDate] to parse the input string, that means [IETF-compliant RFC 2822 timestamps](https://datatracker.ietf.org/doc/html/rfc2822#page-14) and strings in [a version of ISO8601](https://www.ecma-international.org/ecma-262/11.0/#sec-date.parse) are supported.

Output
```text
2015
```

`date` works on strings if they contain well-formatted dates:

Input
### Examples
```liquid
{{ "March 14, 2016" | date: "%b %d, %y" }}
```

Output
```text
Mar 14, 16
{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S", 360 }} => 1990-12-31T17:00:00
{{ "March 14, 2016" | date: "%b %d, %y" }} => Mar 14, 16
```

{% note info Timestamp Strings %}
Note that LiquidJS is using JavaScript [Date][newDate] to parse the input string, that means [IETF-compliant RFC 2822 timestamps](https://datatracker.ietf.org/doc/html/rfc2822#page-14) and strings in [a version of ISO8601](https://www.ecma-international.org/ecma-262/11.0/#sec-date.parse) are supported.
{% endnote %}

To get the current time, pass the special word `"now"` (or `"today"`) to `date`:
# Current Date
* To get the current time, pass the special word `"now"` or `"today"` as input
* Note that the value will be the current time of when the page was last generated from the template, not when the page is presented to a user if caching or static site generation is involved

Input
### Example
```liquid
This page was last updated at {{ "now" | date: "%Y-%m-%d %H:%M" }}.
```

Output
```text
This page was last updated at 2020-03-25 15:57.
Last updated on: {{ "now" | date: "%Y-%m-%d %H:%M" }} => Last updated on: 2020-03-25 15:57
Last updated on: {{ "today" | date: "%Y-%m-%d %H:%M" }} => Last updated on: 2020-03-25 15:57
```

{% note info now %}Note that the value will be the current time of when the page was last generated from the template, not when the page is presented to a user if caching or static site generation is involved.{% endnote %}

[newDate]: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date
[jsDate]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
2 changes: 2 additions & 0 deletions docs/source/tutorials/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ it defaults to false. For example, when set to true, a blank string would evalu

**preserveTimezones** is a boolean effects only literal timestamps. When set to `true`, all literal timestamps will remain the same when output. This is a parser option, so Date objects passed to LiquidJS as data will not be affected. Note that `preserveTimezones` has a higher priority than `timezoneOffset`.

**dateFormat** is used to specify a default format to output dates. `%A, %B %-e, %Y at %-l:%M %P %z` will be used if not specified. For example, set `dateFormat: %Y-%m-%dT%H:%M:%S:%LZ` to output all dates in [JavaScript Date.toJson()][https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON] format.

## Trimming

**greedy**, **trimOutputLeft**, **trimOutputRight**, **trimTagLeft**, **trimTagRight** options are used to eliminate extra newlines and indents in templates around Liquid Constructs. See [Whitespace Control][wc] for details.
Expand Down
1 change: 1 addition & 0 deletions docs/source/zh-cn/tutorials/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ LiquidJS 把这个选项默认值设为 <code>true</code> 以兼容于 shopify/l

**preserveTimezones** 是一个布尔值,只影响时间戳字面量。当设置为 `true` 时,所有字面量的时间戳字符串会在输出时保持原状,即不论输入时采取怎样的时区,输出时仍然采用那一时区(和 Shopify Liquid 的行为一致)。注意这是一个解析器参数,渲染时传入的数据中的日期的输出不会受此参数影响。注意 `preserveTimezones``timezoneOffset` 的优先级更高。

**dateFormat** 用于指定输出日期的默认格式. `%A, %B %-e, %Y at %-l:%M %P %z` 如果未指定,将使用. 例如,设置 `dateFormat: %Y-%m-%dT%H:%M:%S:%LZ` 以输出 [JavaSrcipt Date.toJson()][https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON] 格式.

## 换行和缩进

Expand Down
2 changes: 1 addition & 1 deletion src/filters/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export function date (this: FilterImpl, v: string | Date, format?: string, timez
let date: LiquidDate
v = toValue(v)
format = toValue(format)
if (isNil(format)) format = DEFAULT_FMT
if (isNil(format)) format = opts.dateFormat ?? DEFAULT_FMT
else format = stringify(format)
if (v === 'now' || v === 'today') {
date = new Date()
Expand Down
2 changes: 2 additions & 0 deletions src/liquid-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export interface LiquidOptions {
lenientIf?: boolean;
/** 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` */
timezoneOffset?: number | string;
/** Default date format to use if the date filter doesn't include a format. Defaults to `%A, %B %-e, %Y at %-l:%M %P %z`. */
dateFormat?: string;
/** Strip blank characters (including ` `, `\t`, and `\r`) from the right of tags (`{% %}`) until `\n` (inclusive). Defaults to `false`. */
trimTagRight?: boolean;
/** Similar to `trimTagRight`, whereas the `\n` is exclusive. Defaults to `false`. See Whitespace Control for details. */
Expand Down
18 changes: 18 additions & 0 deletions test/integration/filters/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,22 @@ describe('filters/date', function () {
return test('{{ "1990-12-31T23:00:00+02:30" | date: "%Y-%m-%dT%H:%M:%S"}}', '1990-12-31T23:00:00', undefined, opts)
})
})
describe('dateFormat', function () {
const optsWithoutDateFormat: LiquidOptions = { timezoneOffset: 360 } // -06:00
// date.DEFAULT_FMT: '%A, %B %-e, %Y at %-l:%M %P %z'
it('should use default format for date filters without format argument', function () {
return test('{{ "2022-12-08T03:22:18.000Z" | date }}', 'Wednesday, December 7, 2022 at 9:22 pm -0600', undefined, optsWithoutDateFormat)
})
it('should use given date filter format argument and NOT default format', function () {
return test('{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S" }}', '1990-12-31T17:00:00', undefined, optsWithoutDateFormat)
})

const optsWithDateFormat: LiquidOptions = { timezoneOffset: -330, dateFormat: '%d%q of %b %Y at %I:%M %P' } // -06:00, 31st of Dec 1990 at 11:00 pm
it('should use configured `options.dateFormat` for date filters without format argument', function () {
return test('{{ "2022-12-08T13:30:18.000Z" | date }}', '08th of Dec 2022 at 07:00 pm', undefined, optsWithDateFormat)
})
it('should use given date filter format argument and NOT `options.dateFormat`', function () {
return test('{{ "1990-12-31T23:00:00Z" | date: "%Y-%m-%dT%H:%M:%S" }}', '1991-01-01T04:30:00', undefined, optsWithDateFormat)
})
})
})

0 comments on commit 3fb6646

Please sign in to comment.