日期和时间函数¶
这一系列函数可用于构造、转换、提取或修改 DATE/TIME/TIMESTAMP 数据。
本主题内容:
函数列表¶
子类别 |
函数 |
备注 |
---|---|---|
构造 |
||
提取 |
接受所有日期和时间部分(有关详细信息,请参阅下一节)。 |
|
DATE_PART 的替代项。 |
||
DATE_PART 的替代项。 |
||
接受相关日期部分(有关详细信息,请参阅下一节)。 |
||
DATE_PART 的替代项。 |
||
加法/减法 |
||
接受相关的日期和时间部分(有关详细信息,请参阅下一节)。 |
||
接受相关的日期和时间部分(有关详细信息,请参阅下一节)。 |
||
DATEADD 的别名。 |
||
DATEDIFF 的别名。 |
||
DATEADD 的别名。 |
||
DATEDIFF 的别名。 |
||
截断 |
接受相关的日期和时间部分(有关详细信息,请参阅下一节)。 |
|
允许将时间“舍入”到均匀间隔的起点。 |
||
DATE_TRUNC 的替代项。 |
||
转换 |
||
时区 |
||
警报 |
||
支持的日期和时间部分¶
某些函数(及其相应的别名和替代项)接受日期或时间部分作为实参。以下两个表列出了可用于这些函数的部分(不区分大小写)。
日期部分 |
缩写/变体 |
DATEADD |
DATEDIFF |
DATE_PART |
DATE_TRUNC |
LAST_DAY |
---|---|---|---|---|---|---|
|
|
✔ |
✔ |
✔ |
✔ |
✔ |
|
|
✔ |
✔ |
✔ |
✔ |
✔ |
|
|
✔ |
✔ |
✔ |
✔ |
|
|
|
✔ |
||||
|
|
✔ |
||||
|
|
✔ |
||||
|
|
✔ |
✔ |
✔ |
✔ |
✔ |
|
|
✔ |
||||
|
|
✔ |
✔ |
✔ |
✔ |
✔ |
|
✔ |
|||||
|
✔ |
[1] 有关使用详细信息,请参阅下一节,其中介绍了 Snowflake 如何处理日历周和工作日。
[2] 不受 WEEK_START 和 WEEK_OF_YEAR_POLICY 会话参数控制,如下一节所述。
时间部分 |
缩写/变体 |
DATEADD |
DATEDIFF |
DATE_PART |
DATE_TRUNC |
LAST_DAY |
---|---|---|---|---|---|---|
|
|
✔ |
✔ |
✔ |
✔ |
|
|
|
✔ |
✔ |
✔ |
✔ |
|
|
|
✔ |
✔ |
✔ |
✔ |
|
|
|
✔ |
✔ |
✔ |
||
|
|
✔ |
✔ |
✔ |
||
|
|
✔ |
✔ |
✔ |
✔ |
|
|
|
✔ |
||||
|
|
✔ |
||||
|
|
✔ |
||||
|
|
✔ |
||||
|
|
✔ |
||||
|
|
✔ |
日历周和工作日¶
Snowflake 中与周相关的函数的行为由 WEEK_START 和 WEEK_OF_YEAR_POLICY 会话参数控制。了解这些参数如何相互作用的一个重要方面是 ISO 周的概念。
ISO 周¶
根据 `ISO 8601<https://en.wikipedia.org/wiki/ISO_8601>`_ 标准(针对日期和时间格式)的定义,ISO 周总是从星期一开始,并且“属于”包含该周星期四的年份。这意味着一年中的一天可能属于不同年份的一周:
对于 1 月初的几天,WOY (一年中的周数)值可以是 52 或 53(即该天属于上一年的最后一周)。
对于 12 月最后的几天,WOY 值可以是 1(即该天属于下一年的第一周)。
Snowflake 提供了一组特殊的与周相关的日期函数(以及等效的数据部分),其行为与 ISO 周语义一致:DAYOFWEEKISO、WEEKISO、YEAROFWEEKISO。
这些函数(和日期部分)忽略会话参数(即它们始终遵循 ISO 语义)。
有关如何处理所有其他与周相关的日期函数的详细信息,请参阅以下小节(本主题内容)。
一周的第一天¶
大多数与周相关的函数仅由 WEEK_START 会话参数控制。请注意,函数结果因参数的设置方式而异:
函数 |
参数设置为 |
参数设置为 |
---|---|---|
返回 |
返回 |
|
DATE_TRUNC (有 |
截断输入周,从星期一开始。 |
截断输入周,从定义的周起始日开始。 |
LAST_DAY (有 |
返回输入周的星期日。 |
返回相对于所定义周起始日的那一周的最后一天。 |
DATEDIFF (有 |
按照从星期一开始的周数计算。 |
按照从所定义周起始日的周数来计算。 |
小技巧
该参数的默认值为 0
,保留了旧的 Snowflake 行为(ISO 类似语义);但是,我们建议更改此值以显式控制函数的结果行为。根据我们收到的反馈,最常见的方案是将参数设置为 1
。
一年中的第一周/最后一周¶
WEEK_OF_YEAR_POLICY 会话参数控制 WEEK 和 YEAROFWEEK 函数的行为方式。该参数可以有两个值:
0
:受影响的周相关函数使用与 ISO 语义相似的语义,其中如果一周中至少有 4 天在给定年份,则该周属于该年。这意味着所有周都有 7 天,但 1 月的前几天和 12 月的最后几天可能属于不同年份的周。因此,YEAROFWEEK 和 YEAROFWEEKISO 函数都可以提供一周所属的年份。1
:1 月 1 日总是在一年中的第一周,12 月 31 日总是在一年中的最后一周。这意味着一年中的第一周和最后一周可能少于 7 天。
请注意,此行为还受一周的开始日期的影响,由为 WEEK_START 会话参数设置的值控制:
0
、1
:行为等效于 ISO 周语义,周从星期一开始。2
至7
:保留了“4 天”逻辑,但一周的第一天不同。
小技巧
这两个参数的默认值都是 0
,都保留了旧的 Snowflake 行为(ISO 类似语义);但是,我们建议更改这些值以显式控制函数的结果行为。根据我们收到的反馈,最常见的方案是将两个参数都设置为 1
。
示例¶
备注
这些示例查询同一组日期函数,但为 WEEK_OF_YEAR_POLICY 和 WEEK_START 会话参数设置了不同的值,以说明它们如何影响函数的结果。
控制周起始日¶
将 WEEK_START 设置为 0
(旧行为)或 :code:`1`(星期一)没有显著影响,如以下两个示例所示:
ALTER SESSION SET WEEK_START = 0; SELECT d "Date", DAYNAME(d) "Day", DAYOFWEEK(d) "DOW", DATE_TRUNC('week', d) "Trunc Date", DAYNAME("Trunc Date") "Trunc Day", LAST_DAY(d, 'week') "Last DOW Date", DAYNAME("Last DOW Date") "Last DOW Day", DATEDIFF('week', '2017-01-01', d) "Weeks Diff from 2017-01-01 to Date" FROM week_examples; +------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------+ | Date | Day | DOW | Trunc Date | Trunc Day | Last DOW Date | Last DOW Day | Weeks Diff from 2017-01-01 to Date | |------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------| | 2016-12-30 | Fri | 5 | 2016-12-26 | Mon | 2017-01-01 | Sun | 0 | | 2016-12-31 | Sat | 6 | 2016-12-26 | Mon | 2017-01-01 | Sun | 0 | | 2017-01-01 | Sun | 0 | 2016-12-26 | Mon | 2017-01-01 | Sun | 0 | | 2017-01-02 | Mon | 1 | 2017-01-02 | Mon | 2017-01-08 | Sun | 1 | | 2017-01-03 | Tue | 2 | 2017-01-02 | Mon | 2017-01-08 | Sun | 1 | | 2017-01-04 | Wed | 3 | 2017-01-02 | Mon | 2017-01-08 | Sun | 1 | | 2017-01-05 | Thu | 4 | 2017-01-02 | Mon | 2017-01-08 | Sun | 1 | | 2017-12-30 | Sat | 6 | 2017-12-25 | Mon | 2017-12-31 | Sun | 52 | | 2017-12-31 | Sun | 0 | 2017-12-25 | Mon | 2017-12-31 | Sun | 52 | +------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------+ ALTER SESSION SET WEEK_START = 1; SELECT d "Date", DAYNAME(d) "Day", DAYOFWEEK(d) "DOW", DATE_TRUNC('week', d) "Trunc Date", DAYNAME("Trunc Date") "Trunc Day", LAST_DAY(d, 'week') "Last DOW Date", DAYNAME("Last DOW Date") "Last DOW Day", DATEDIFF('week', '2017-01-01', d) "Weeks Diff from 2017-01-01 to Date" FROM week_examples; +------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------+ | Date | Day | DOW | Trunc Date | Trunc Day | Last DOW Date | Last DOW Day | Weeks Diff from 2017-01-01 to Date | |------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------| | 2016-12-30 | Fri | 5 | 2016-12-26 | Mon | 2017-01-01 | Sun | 0 | | 2016-12-31 | Sat | 6 | 2016-12-26 | Mon | 2017-01-01 | Sun | 0 | | 2017-01-01 | Sun | 7 | 2016-12-26 | Mon | 2017-01-01 | Sun | 0 | | 2017-01-02 | Mon | 1 | 2017-01-02 | Mon | 2017-01-08 | Sun | 1 | | 2017-01-03 | Tue | 2 | 2017-01-02 | Mon | 2017-01-08 | Sun | 1 | | 2017-01-04 | Wed | 3 | 2017-01-02 | Mon | 2017-01-08 | Sun | 1 | | 2017-01-05 | Thu | 4 | 2017-01-02 | Mon | 2017-01-08 | Sun | 1 | | 2017-12-30 | Sat | 6 | 2017-12-25 | Mon | 2017-12-31 | Sun | 52 | | 2017-12-31 | Sun | 7 | 2017-12-25 | Mon | 2017-12-31 | Sun | 52 | +------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------+
WEEK_START 设置为
0
时,星期日的 DOW 为0
。WEEK_START 设置为
1
时,星期日的 DOW 为7
。
如果 WEEK_START 设置为星期一以外的任何一天,则结果差异更大。例如,将参数设置为 :code:`3`(星期三)会更改所有与周相关的函数(第 3 列到第 8 列)的结果:
ALTER SESSION SET WEEK_START = 3; SELECT d "Date", DAYNAME(d) "Day", DAYOFWEEK(d) "DOW", DATE_TRUNC('week', d) "Trunc Date", DAYNAME("Trunc Date") "Trunc Day", LAST_DAY(d, 'week') "Last DOW Date", DAYNAME("Last DOW Date") "Last DOW Day", DATEDIFF('week', '2017-01-01', d) "Weeks Diff from 2017-01-01 to Date" FROM week_examples; +------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------+ | Date | Day | DOW | Trunc Date | Trunc Day | Last DOW Date | Last DOW Day | Weeks Diff from 2017-01-01 to Date | |------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------| | 2016-12-30 | Fri | 3 | 2016-12-28 | Wed | 2017-01-03 | Tue | 0 | | 2016-12-31 | Sat | 4 | 2016-12-28 | Wed | 2017-01-03 | Tue | 0 | | 2017-01-01 | Sun | 5 | 2016-12-28 | Wed | 2017-01-03 | Tue | 0 | | 2017-01-02 | Mon | 6 | 2016-12-28 | Wed | 2017-01-03 | Tue | 0 | | 2017-01-03 | Tue | 7 | 2016-12-28 | Wed | 2017-01-03 | Tue | 0 | | 2017-01-04 | Wed | 1 | 2017-01-04 | Wed | 2017-01-10 | Tue | 1 | | 2017-01-05 | Thu | 2 | 2017-01-04 | Wed | 2017-01-10 | Tue | 1 | | 2017-12-30 | Sat | 4 | 2017-12-27 | Wed | 2018-01-02 | Tue | 52 | | 2017-12-31 | Sun | 5 | 2017-12-27 | Wed | 2018-01-02 | Tue | 52 | +------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------+
控制一年中第一周/最后一周的年份和天数¶
以下示例将两个参数都设置为 0
,以遵循 ISO 类似语义(即周从星期一开始,所有周都有 7 天):
ALTER SESSION SET WEEK_OF_YEAR_POLICY=0, WEEK_START=0; SELECT d "Date", DAYNAME(d) "Day", WEEK(d) "WOY", WEEKISO(d) "WOY (ISO)", YEAROFWEEK(d) "YOW", YEAROFWEEKISO(d) "YOW (ISO)" FROM week_examples; +------------+-----+-----+-----------+------+-----------+ | Date | Day | WOY | WOY (ISO) | YOW | YOW (ISO) | |------------+-----+-----+-----------+------+-----------| | 2016-12-30 | Fri | 52 | 52 | 2016 | 2016 | | 2016-12-31 | Sat | 52 | 52 | 2016 | 2016 | | 2017-01-01 | Sun | 52 | 52 | 2016 | 2016 | | 2017-01-02 | Mon | 1 | 1 | 2017 | 2017 | | 2017-01-03 | Tue | 1 | 1 | 2017 | 2017 | | 2017-01-04 | Wed | 1 | 1 | 2017 | 2017 | | 2017-01-05 | Thu | 1 | 1 | 2017 | 2017 | | 2017-12-30 | Sat | 52 | 52 | 2017 | 2017 | | 2017-12-31 | Sun | 52 | 52 | 2017 | 2017 | +------------+-----+-----+-----------+------+-----------+
下一个示例说明了将 WEEK_OF_YEAR_POLICY 设置为 0
,但将 WEEK_START 更改为 :code:`3`(星期三)的效果:
ALTER SESSION SET WEEK_OF_YEAR_POLICY=0, WEEK_START=3; SELECT d "Date", DAYNAME(d) "Day", WEEK(d) "WOY", WEEKISO(d) "WOY (ISO)", YEAROFWEEK(d) "YOW", YEAROFWEEKISO(d) "YOW (ISO)" FROM week_examples; +------------+-----+-----+-----------+------+-----------+ | Date | Day | WOY | WOY (ISO) | YOW | YOW (ISO) | |------------+-----+-----+-----------+------+-----------| | 2016-12-30 | Fri | 53 | 52 | 2016 | 2016 | | 2016-12-31 | Sat | 53 | 52 | 2016 | 2016 | | 2017-01-01 | Sun | 53 | 52 | 2016 | 2016 | | 2017-01-02 | Mon | 53 | 1 | 2016 | 2017 | | 2017-01-03 | Tue | 53 | 1 | 2016 | 2017 | | 2017-01-04 | Wed | 1 | 1 | 2017 | 2017 | | 2017-01-05 | Thu | 1 | 1 | 2017 | 2017 | | 2017-12-30 | Sat | 52 | 52 | 2017 | 2017 | | 2017-12-31 | Sun | 52 | 52 | 2017 | 2017 | +------------+-----+-----+-----------+------+-----------+
2016 年现在有 53 周(而不是 52 周)。
2017 年 1 月 1 日的 WOY 从第 52 周移到第 53 周。
2017 年 1 月 2 日和 3 日的 WOY 从第 1 周移到第 53 周。
2017 年 1 月 2 日和 3 日的 YOW 从 2017 移到 2016。
WOY (ISO) 和 YOW (ISO) 不受参数更改的影响。
最后两个示例将 WEEK_OF_YEAR_POLICY 设置为 1
,并将 WEEK_START 首先设置为 1
(星期一),然后设置为 3
(星期三):
ALTER SESSION SET WEEK_OF_YEAR_POLICY=1, WEEK_START=1; SELECT d "Date", DAYNAME(d) "Day", WEEK(d) "WOY", WEEKISO(d) "WOY (ISO)", YEAROFWEEK(d) "YOW", YEAROFWEEKISO(d) "YOW (ISO)" FROM week_examples; +------------+-----+-----+-----------+------+-----------+ | Date | Day | WOY | WOY (ISO) | YOW | YOW (ISO) | |------------+-----+-----+-----------+------+-----------| | 2016-12-30 | Fri | 53 | 52 | 2016 | 2016 | | 2016-12-31 | Sat | 53 | 52 | 2016 | 2016 | | 2017-01-01 | Sun | 1 | 52 | 2017 | 2016 | | 2017-01-02 | Mon | 2 | 1 | 2017 | 2017 | | 2017-01-03 | Tue | 2 | 1 | 2017 | 2017 | | 2017-01-04 | Wed | 2 | 1 | 2017 | 2017 | | 2017-01-05 | Thu | 2 | 1 | 2017 | 2017 | | 2017-12-30 | Sat | 53 | 52 | 2017 | 2017 | | 2017-12-31 | Sun | 53 | 52 | 2017 | 2017 | +------------+-----+-----+-----------+------+-----------+ alter session set week_of_year_policy=1, week_start=3; SELECT d "Date", DAYNAME(d) "Day", WEEK(d) "WOY", WEEKISO(d) "WOY (ISO)", YEAROFWEEK(d) "YOW", YEAROFWEEKISO(d) "YOW (ISO)" FROM week_examples; +------------+-----+-----+-----------+------+-----------+ | Date | Day | WOY | WOY (ISO) | YOW | YOW (ISO) | |------------+-----+-----+-----------+------+-----------| | 2016-12-30 | Fri | 53 | 52 | 2016 | 2016 | | 2016-12-31 | Sat | 53 | 52 | 2016 | 2016 | | 2017-01-01 | Sun | 1 | 52 | 2017 | 2016 | | 2017-01-02 | Mon | 1 | 1 | 2017 | 2017 | | 2017-01-03 | Tue | 1 | 1 | 2017 | 2017 | | 2017-01-04 | Wed | 2 | 1 | 2017 | 2017 | | 2017-01-05 | Thu | 2 | 1 | 2017 | 2017 | | 2017-12-30 | Sat | 53 | 52 | 2017 | 2017 | | 2017-12-31 | Sun | 53 | 52 | 2017 | 2017 | +------------+-----+-----+-----------+------+-----------+
WEEK_OF_YEAR_POLICY 设置为
1
,WEEK_START 设置为1
(星期一):
2017-01-01
的 WOY 是1
。第 1 周包括 1 天。
第 2 周从
Mon
开始。请注意,根据我们收到的反馈,这是最常见的使用方案。
WEEK_OF_YEAR_POLICY 设置为
1
,WEEK_START 设置为3
(星期三):
2017-01-01 的 WOY 仍然是
1
。第 1 周包括 3 天。
第 2 周从
Wed
开始。在这两个示例中,WOY (ISO) 和 YOW (ISO) 不受参数更改的影响。