使用 Luxon 处理日期和时间#
Luxon 是一个 JavaScript 库,用于简化日期和时间的操作。有关如何使用 Luxon 的完整说明,请参考 Luxon 官方文档。 n8n 在节点之间传递日期时以字符串形式传输,因此你需要对其进行解析。Luxon 让这一过程更加简便。
Python 支持
Luxon 是一个 JavaScript 库。在代码节点(Code node)中使用 Python 时,n8n 提供的两个便捷 变量 可用,但其功能有限:
- 你无法在这两个变量上执行 Luxon 操作。例如,Python 中没有与
$today.minus(...)对应的等效方法。 - 通用的 Luxon 功能(如 将日期字符串转换为 Luxon 对象)对 Python 用户不可用。
n8n 中的日期和时间行为#
请注意以下几点:
- 在工作流中,n8n 会在节点之间将日期和时间转换为字符串。当你对来自其他节点的日期和时间进行算术运算时,请牢记这一点。
- 使用原生 JavaScript,你可以通过
new Date('2019-06-23')将字符串转换为日期。而在 Luxon 中,你必须显式使用指定格式的函数,例如DateTime.fromISO('2019-06-23')或DateTime.fromFormat("23-06-2019", "dd-MM-yyyy")。
在 n8n 中设置时区#
Luxon 使用 n8n 的时区设置。该值可能为以下之一:
- 默认值:
America/New_York - 通过环境变量
GENERIC_TIMEZONE为你的 n8n 实例设置的自定义时区。 - 在工作流设置中为单个工作流配置的自定义时区。
常见任务#
本节提供了一些常见操作的示例。更多示例和详细指导,请参阅 Luxon 官方文档。
获取当前日期或时间#
使用 $now 和 $today Luxon 对象 来获取当前时间或日期:
now:包含当前时间戳的 Luxon 对象。等同于DateTime.now()。today:包含当前时间戳的 Luxon 对象,但已向下取整到当日零点。等同于DateTime.now().set({ hour: 0, minute: 0, second: 0, millisecond: 0 })。
请注意,当这些变量被转换为字符串时,可能会返回不同的时间格式: 表达式(JavaScript)代码节点(JavaScript)代码节点(Python)
1
2
3
4
5
6| ``` {{$now}} // n8n 显示 ISO 格式的时间戳 // 例如:2022-03-09T14:02:37.065+00:00 {{"Today's date is "+$now}} // n8n 显示 "Today's date is " // 例如:"Today's date is 1646834498755"
---|---1 2 3 4 5 6
| ```
$now
// n8n 显示 <ISO 格式的时间戳>
// 例如:2022-03-09T14:00:25.058+00:00
letrightNow="Today's date is "+$now
// n8n 显示 "Today's date is <unix timestamp>"
// 例如:"Today's date is 1646834498755"---|---
1
2
3
4
5
6| ``` _now
n8n 显示 <ISO 格式的时间戳>
例如:2022-03-09T14:00:25.058+00:00
rightNow = "Today's date is " + str(_now)
n8n 显示 "Today's date is "
例如:"Today's date is 1646834498755"
---|---
n8n 提供了内置的便捷函数,用于在表达式中对日期进行数据转换。更多信息请参见 数据转换函数 | 日期 (Data transformation functions | Dates)。
### 将 JavaScript 日期转换为 Luxon#
要将原生 JavaScript 日期转换为 Luxon 日期:
* 在表达式中,使用 .toDateTime() 方法。例如:`{{ (new Date()).toDateTime() }}`。
* 在代码节点(Code node)中,使用 `DateTime.fromJSDate()`。例如:`let luxondate = DateTime.fromJSDate(new Date())`。
### 将日期字符串转换为 Luxon#
你可以将日期字符串和其他日期格式转换为 Luxon 的 DateTime 对象。支持标准格式以及任意字符串的转换。
Luxon DateTime 与 JavaScript Date 的区别
在原生 JavaScript 中,你可以通过 `new Date('2019-06-23')` 将字符串转换为日期。而在 Luxon 中,你必须显式指定格式的函数,例如使用 `DateTime.fromISO('2019-06-23')` 或 `DateTime.fromFormat("23-06-2019", "dd-MM-yyyy")`。
#### 如果你的日期是受支持的标准技术格式:#
大多数情况下应使用 `fromISO()`。该方法可以从 ISO 8601 字符串创建一个 Luxon DateTime 对象。例如:
表达式(JavaScript)代码节点(JavaScript)1
| ```
{{DateTime.fromISO('2019-06-23T00:00:00.00')}}
---|---1
| ```
let luxonDateTime = DateTime.fromISO('2019-06-23T00:00:00.00')---|--- Luxon 的 API 文档提供了更多关于 fromISO 的信息。 Luxon 提供了处理多种格式转换的函数。详情请参考 Luxon 的 解析技术格式(Parsing technical formats) 指南。
如果你的日期是一个非标准格式的字符串:#
使用 Luxon 的 临时解析(Ad-hoc parsing)。为此,使用 fromFormat() 函数,并提供该字符串以及描述其格式的一组 令牌(tokens)。
例如,你有 n8n 的成立日期:2019 年 6 月 23 日,格式为 23-06-2019,你想将其转换为一个 Luxon 对象:
表达式(JavaScript)代码节点(JavaScript)
1| ``` {{DateTime.fromFormat("23-06-2019","dd-MM-yyyy")}}
---|---1
| ```
let newFormat = DateTime.fromFormat("23-06-2019", "dd-MM-yyyy")---|--- 使用临时解析时,请注意 Luxon 关于 限制(Limitations) 的警告。如果出现意外结果,建议参考其 调试指南(Debugging)。
获取从今天起的 N 天前或 N 天后日期#
获取相对于今天的若干天前或若干天后的日期。 表达式(JavaScript)代码节点(JavaScript) 例如,你想设置一个字段始终显示当前日期七天前的日期。 在表达式编辑器中输入:
1| ``` {{$today.minus({days:7})}}
---|---
在 2019 年 6 月 23 日执行时,返回 `[Object: "2019-06-16T00:00:00.000+00:00"]`。
此示例为了方便使用了 n8n 的自定义变量 `$today`,它等价于 `DateTime.now().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).minus({days: 7})`。
再比如,你想创建一个变量,包含当前日期七天前的日期。
在代码编辑器中输入:1
| ```
let sevenDaysAgo = $today.minus({days:7})
---|---
在 2019 年 6 月 23 日,返回 `[Object: "2019-06-16T00:00:00.000+00:00"]`。
此示例为方便起见使用了 n8n 的自定义变量 `$today`。其等价于 `DateTime.now().set({ hour: 0, minute: 0, second: 0, millisecond: 0 }).minus({days: 7})`。
如需更详细的信息和示例,请参考:
* Luxon 的 数学运算指南
* 其 API 文档中的 DateTime plus 和 DateTime minus
### 创建人类可读的日期#
在 获取今天之前的 n 天 示例中,获取当前日期前七天的日期,并以 `[Object: "yyyy-mm-dd-T00:00:00.000+00:00"]`(用于表达式)或 `yyyy-mm-dd-T00:00:00.000+00:00`(在 Code 节点中)格式返回。为了提高可读性,你可以使用 Luxon 的格式化功能。
例如,你希望包含日期的字段以 DD/MM/YYYY 格式显示,这样在 2019 年 6 月 23 日时,返回 `23/06/2019`。
以下表达式获取今天之前七天的日期,并将其转换为 DD/MM/YYYY 格式。
表达式 (JavaScript)Code 节点 (JavaScript)1
| ```
{{$today.minus({days:7}).toLocaleString()}}---|---
1| ``` let readableSevenDaysAgo = $today.minus({days:7}).toLocaleString()
---|---
你可以更改格式。例如:
表达式 (JavaScript)Code 节点 (JavaScript)1
| ```
{{$today.minus({days:7}).toLocaleString({month:'long', day:'numeric', year:'numeric'})}}---|--- 在 2019 年 6 月 23 日,此表达式返回 "16 June 2019"。
1| ``` let readableSevenDaysAgo = $today.minus({days:7}).toLocaleString({month:'long', day:'numeric', year:'numeric'})
---|---
在 2019 年 6 月 23 日,此代码返回 "16 June 2019"。
更多信息请参阅 Luxon 关于 toLocaleString(面向人类的字符串) 的指南。
### 获取两个日期之间的时间间隔#
要获取两个日期之间的时间间隔,请使用 Luxon 的 diff 功能。它会从一个日期减去另一个日期,并返回一个持续时间(duration)。
例如,获取两个日期之间的月份数:
表达式 (JavaScript)Code 节点 (JavaScript)1
| ```
{{DateTime.fromISO('2019-06-23').diff(DateTime.fromISO('2019-05-23'), 'months').toObject()}}
---|---
这将返回 `[Object: {"months":1}]`。1
| ```
let monthsBetweenDates = DateTime.fromISO('2019-06-23').diff(DateTime.fromISO('2019-05-23'), 'months').toObject()---|---
这将返回 {"months":1}。
更多信息请参考 Luxon 的 Diffs(差值计算)。
更长的例子:距离圣诞节还有多少天?#
这个例子结合了多个 Luxon 功能,使用了 JMESPath,并进行了一些基础的字符串操作。 场景如下:你想要一个倒计时,指向每年的 12 月 25 日。每天它都会告诉你距离圣诞节还有多少天。你不想每年都手动更新年份——它需要能够无缝适用于每一年。 表达式(JavaScript)代码节点(JavaScript)
1| ``` {{"There are "+$today.diff(DateTime.fromISO($today.year+'-12-25'),'days').toObject().days.toString().substring(1)+" days to Christmas!"}}
---|---
该表达式输出 `"There are <天数> days to Christmas!"`。例如,在 3 月 9 日运行时,输出为 "There are 291 days to Christmas!"。
以下是该表达式的详细解释:
* `{{`:表示表达式的开始。
* `"There are "`:一段普通字符串。
* `+`:用于连接两个字符串。
* `$today.diff()`:类似于 获取两个日期之间的时间间隔 中的例子,但这里使用了 n8n 自定义的 `$today` 变量。
* `DateTime.fromISO($today.year + '-12-25'), 'days'`:这部分通过 `$today.year` 获取当前年份,将其与固定的月份和日期组合成 ISO 格式的字符串,然后将整个字符串转换为 Luxon 的 DateTime 数据结构。同时指定你希望以“天”为单位计算时间间隔。
* `toObject()` 将 `diff()` 的结果转换为更易使用的对象格式。此时表达式的结果是 `[Object: {"days":-<天数>}]`。例如,在 3 月 9 日时,结果为 `[Object: {"days":-291}]`。
* `.days` 使用 JMESPath 语法从对象中提取出“天数”字段的值。关于在 n8n 中使用 JMESPath 的更多信息,请参阅我们的 JMESPath 文档。此时得到的是一个负数,表示距离目标日期还剩多少天。
* `.toString().substring(1)` 将数字转换为字符串,并移除开头的负号 `-`。
* `+ " days to Christmas!"`:另一段字符串,用 `+` 连接到前面的结果上。
* `}}`:表示表达式的结束。1
| ```
let daysToChristmas = "There are " + $today.diff(DateTime.fromISO($today.year + '-12-25'), 'days').toObject().days.toString().substring(1) + " days to Christmas!";
---|---
这将输出 `"距离圣诞节还有 <天数> 天!"`。例如,在 3 月 9 日,它会输出 "距离圣诞节还有 291 天!"。
代码功能的详细说明:
* `"There are "`:一个字符串。
* `+`:用于连接两个字符串。
* `$today.diff()`:类似于 获取两个日期之间的时间 中的例子,但使用了 n8n 自定义的 `$today` 变量。
* `DateTime.fromISO($today.year + '-12-25'), 'days'`:这一部分使用 `$today.year` 获取当前年份,将其与月份和日期组合成 ISO 格式的字符串,然后将整个 ISO 字符串转换为 Luxon 的 DateTime 数据结构。同时告诉 Luxon 你希望以“天”为单位计算时间间隔。
* `toObject()` 将 diff() 的结果转换为更易使用的对象。此时表达式返回 `[Object: {"days":-<天数>}]`。例如,在 3 月 9 日时,返回 `[Object: {"days":-291}]`。
* `.days` 使用 JMESPath 语法从对象中提取出天数。有关在 n8n 中使用 JMESPath 的更多信息,请参考我们的 JMESpath 文档。这会得到一个表示距离圣诞节天数的负数。
* `.toString().substring(1)` 将该数字转换为字符串并移除前面的 `-` 符号。
* `+ " days to Christmas!"`:另一个字符串,使用 `+` 将其与前面的字符串连接起来。