日期和时间函数

这一系列函数可用于构造、转换、提取或修改 DATE/TIME/TIMESTAMP 数据。

本主题内容:

函数列表

子类别

函数

备注

构造

DATE_FROM_PARTS

TIME_FROM_PARTS

TIMESTAMP_FROM_PARTS

提取

DATE_PART

接受所有日期和时间部分(有关详细信息,请参阅下一节)。

DAYNAME

EXTRACT

DATE_PART 的替代项。

HOUR / MINUTE / SECOND

DATE_PART 的替代项。

LAST_DAY

接受相关日期部分(有关详细信息,请参阅下一节)。

MONTHNAME

NEXT_DAY

PREVIOUS_DAY

YEAR* / DAY* / WEEK* / MONTH / QUARTER

DATE_PART 的替代项。

加法/减法

ADD_MONTHS

DATEADD

接受相关的日期和时间部分(有关详细信息,请参阅下一节)。

DATEDIFF

接受相关的日期和时间部分(有关详细信息,请参阅下一节)。

MONTHS_BETWEEN

TIMEADD

DATEADD 的别名。

TIMEDIFF

DATEDIFF 的别名。

TIMESTAMPADD

DATEADD 的别名。

TIMESTAMPDIFF

DATEDIFF 的别名。

截断

DATE_TRUNC

接受相关的日期和时间部分(有关详细信息,请参阅下一节)。

TIME_SLICE

允许将时间“舍入”到均匀间隔的起点。

TRUNC

DATE_TRUNC 的替代项。

转换

TO_DATE、DATE

TO_TIME、TIME

TO_TIMESTAMP / TO_TIMESTAMP_*

时区

CONVERT_TIMEZONE

警报

LAST_SUCCESSFUL_SCHEDULED_TIME

SCHEDULED_TIME

支持的日期和时间部分

某些函数(及其相应的别名和替代项)接受日期或时间部分作为实参。以下两个表列出了可用于这些函数的部分(不区分大小写)。

日期部分

缩写/变体

DATEADD

DATEDIFF

DATE_PART

DATE_TRUNC

LAST_DAY

year

yyyyyyyyyyyryearsyrs

month

mmmonmonsmonths

day

ddddaysdayofmonth

dayofweek [1]

weekdaydowdw

dayofweekiso [2]

weekday_isodow_isodw_iso

dayofyear

yeardaydoydy

week [1]

wwkweekofyearwoywy

weekiso [2]

week_isoweekofyearisoweekofyear_iso

quarter

qqtrqtrsquarters

yearofweek [1]

yearofweekiso [2]

[1] 有关使用详细信息,请参阅下一节,其中介绍了 Snowflake 如何处理日历周和工作日。

[2] 不受 WEEK_START 和 WEEK_OF_YEAR_POLICY 会话参数控制,如下一节所述。

时间部分

缩写/变体

DATEADD

DATEDIFF

DATE_PART

DATE_TRUNC

LAST_DAY

hour

hhhhrhourshrs

minute

mmiminminutesmins

second

ssecsecondssecs

millisecond

msmsecmilliseconds

microsecond

ususecmicroseconds

nanosecond

nsnsecnanosecnsecondnanosecondsnanosecsnseconds

epoch_second

epochepoch_seconds

epoch_millisecond

epoch_milliseconds

epoch_microsecond

epoch_microseconds

epoch_nanosecond

epoch_nanoseconds

timezone_hour

tzh

timezone_minute

tzm

日历周和工作日

Snowflake 中与周相关的函数的行为由 WEEK_STARTWEEK_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 会话参数控制。请注意,函数结果因参数的设置方式而异:

函数

参数设置为 0 (默认/旧行为)

参数设置为 1 - 7 (星期一至星期日)

DAYOFWEEK

返回 0 (星期日)至 6 (星期六)。

返回 1 (定义的周起始日)至 7 (相对于所定义起始日那一周的最后一天)。

DATE_TRUNC (有 WEEK 部分)

截断输入周,从星期一开始。

截断输入周,从定义的周起始日开始。

LAST_DAY (有 WEEK 部分)

返回输入周的星期日。

返回相对于所定义周起始日的那一周的最后一天。

DATEDIFF (有 WEEK 部分)

按照从星期一开始的周数计算。

按照从所定义周起始日的周数来计算。

小技巧

该参数的默认值为 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 会话参数设置的值控制:

  • 01:行为等效于 ISO 周语义,周从星期一开始。

  • 27:保留了“4 天”逻辑,但一周的第一天不同。

小技巧

这两个参数的默认值都是 0,都保留了旧的 Snowflake 行为(ISO 类似语义);但是,我们建议更改这些值以显式控制函数的结果行为。根据我们收到的反馈,最常见的方案是将两个参数都设置为 1

示例

备注

这些示例查询同一组日期函数,但为 WEEK_OF_YEAR_POLICYWEEK_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 |
+------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------+
Copy
  1. WEEK_START 设置为 0 时,星期日的 DOW 为 0

  2. 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 |
+------------+-----+-----+------------+-----------+---------------+--------------+------------------------------------+
Copy

控制一年中第一周/最后一周的年份和天数

以下示例将两个参数都设置为 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 |
+------------+-----+-----+-----------+------+-----------+
Copy

下一个示例说明了将 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 |
+------------+-----+-----+-----------+------+-----------+
Copy
  • 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 |
+------------+-----+-----+-----------+------+-----------+
Copy
  1. WEEK_OF_YEAR_POLICY 设置为 1,WEEK_START 设置为 1 (星期一):

    • 2017-01-01 的 WOY 是 1

    • 第 1 周包括 1 天。

    • 第 2 周从 Mon 开始。

    请注意,根据我们收到的反馈,这是最常见的使用方案。

  2. WEEK_OF_YEAR_POLICY 设置为 1,WEEK_START 设置为 3 (星期三):

    • 2017-01-01 的 WOY 仍然是 1

    • 第 1 周包括 3 天。

    • 第 2 周从 Wed 开始。

在这两个示例中,WOY (ISO) 和 YOW (ISO) 不受参数更改的影响。

语言: 中文