Skip to content

使用 Luxon 处理日期和时间#

Luxon 是一个 JavaScript 库,可以简化日期和时间的处理。关于 Luxon 的完整使用说明,请参考 Luxon 官方文档

n8n 在节点之间以字符串形式传递日期,因此您需要解析这些字符串。Luxon 使这一过程更加简便。

Python 支持

Luxon 是一个 JavaScript 库。n8n 创建的两个便捷变量在 Code 节点中使用 Python 时可用,但其功能有限:

  • 您不能对这些变量执行 Luxon 操作。例如,Python 中没有与 $today.minus(...) 等效的功能。
  • 通用的 Luxon 功能,如将日期字符串转换为 Luxon,对 Python 用户不可用。

变量#

n8n 使用 Luxon 提供两个自定义变量:

  • now:包含当前时间戳的 Luxon 对象。等同于 DateTime.now()
  • today:包含当前时间戳的 Luxon 对象,向下取整到天。等同于 DateTime.now().set({ hour: 0, minute: 0, second: 0, millisecond: 0 })

请注意,这些变量在被转换为字符串时可能返回不同的时间格式。这与 Luxon 的 DateTime.now() 行为一致。

1
2
3
4
5
6
{{$now}}
// n8n 显示 ISO 格式的时间戳
// 例如 2022-03-09T14:02:37.065+00:00
{{"今天的日期是 " + $now}}
// n8n 显示 "今天的日期是 <unix 时间戳>"
// 例如 "今天的日期是 1646834498755"
1
2
3
4
5
6
$now
// n8n 显示 <ISO 格式的时间戳>
// 例如 2022-03-09T14:00:25.058+00:00
let rightNow = "今天的日期是 " + $now
// n8n 显示 "今天的日期是 <unix 时间戳>"
// 例如 "今天的日期是 1646834498755"
1
2
3
4
5
6
_now
# n8n 显示 <ISO 格式的时间戳>
# 例如 2022-03-09T14:00:25.058+00:00
rightNow = "今天的日期是 " + str(_now)
# n8n 显示 "今天的日期是 <unix 时间戳>"
# 例如 "今天的日期是 1646834498755"

n8n 提供内置的便捷函数来支持表达式中的日期数据转换。更多信息请参考数据转换函数 | 日期

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 官方文档

将日期字符串转换为 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 对象。例如:

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 的 解析技术格式 指南。

如果您的日期字符串使用了非标准格式:#

使用 Luxon 的 Ad-hoc 解析功能。为此,请使用 fromFormat() 函数,提供字符串和一组描述格式的标记

例如,您有 n8n 的创立日期 2019 年 6 月 23 日,格式为 23-06-2019。您想将其转换为 Luxon 对象:

1
{{DateTime.fromFormat("23-06-2019", "dd-MM-yyyy")}}
1
let newFormat = DateTime.fromFormat("23-06-2019", "dd-MM-yyyy")

使用 Ad-hoc 解析时,请注意 Luxon 关于限制的警告。如果遇到意外结果,请参考其调试指南。

获取距今天 n 天的日期#

获取当前日期之前或之后若干天的日期。

例如,您希望将某个字段始终设置为当前日期前七天的日期。

在表达式编辑器中输入:

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})

如需更详细的信息和示例,请参阅:

创建人类可读的日期#

获取当前日期前 N 天示例中,获取了当前日期前七天的日期,并以 [Object: "yyyy-mm-dd-T00:00:00.000+00:00"](表达式模式下)或 yyyy-mm-dd-T00:00:00.000+00:00(在代码节点中)的形式返回。为了使日期更易读,可以使用 Luxon 的格式化函数。

例如,您希望日期字段格式化为 DD/MM/YYYY,这样在 2019 年 6 月 23 日会返回 23/06/2019

以下表达式获取当前日期前七天,并将其转换为 DD/MM/YYYY 格式:

1
{{$today.minus({days: 7}).toLocaleString()}}
1
let readableSevenDaysAgo = $today.minus({days: 7}).toLocaleString()

您可以修改格式。例如:

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 的 diffs 功能。该方法通过从一个日期减去另一个日期来返回时间间隔。

例如,计算两个日期之间相差的月数:

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,并进行了一些基本的字符串操作。

场景:您需要一个圣诞节倒计时。每天,它应该显示距离圣诞节还有多少天。您不希望每年都更新它——它需要每年都能无缝工作。

1
{{"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!": 另一个字符串,用 + 连接前面的字符串
  • }}: 表示表达式结束
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!": 另一个字符串,用 + 连接前面的字符串