> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 日期和时间数据类型 - 时间序列

> ClickHouse 中的时间序列数据类型。

要高效管理时间序列数据，离不开一套完善的日期和时间类型，而 ClickHouse 恰好提供了这样的能力。
从紧凑的日期表示，到具备纳秒级精度的高精度时间戳，这些类型在存储效率与不同时间序列应用的实际需求之间实现了良好平衡。

无论你处理的是历史金融数据、IoT 传感器读数，还是未来日期的事件，ClickHouse 的日期和时间类型都能提供应对各种时间数据场景所需的灵活性。
丰富的类型选择使你能够在满足用例所需精度的同时，兼顾存储空间和查询性能的优化。

* 在大多数情况下，[`Date`](/docs/zh/reference/data-types/date) 类型已经足够。该类型存储一个日期需要 2 个字节，取值范围限制为 `[1970-01-01, 2149-06-06]`。

* [`Date32`](/docs/zh/reference/data-types/date32) 支持更大的日期范围。存储一个日期需要 4 个字节，取值范围限制为 `[1900-01-01, 2299-12-31]`

* [`DateTime`](/docs/zh/reference/data-types/datetime) 以秒级精度存储日期时间值，取值范围为 `[1970-01-01 00:00:00, 2106-02-07 06:28:15]`。每个值需要 4 个字节。

* 对于需要更高精度的场景，可以使用 [`DateTime64`](/docs/zh/reference/data-types/datetime64)。它支持存储最高纳秒级精度的时间，取值范围为 `[1900-01-01 00:00:00, 2299-12-31 23:59:59.99999999]`。每个值需要 8 个字节。

下面创建一个用于存储多种日期类型的表：

```sql theme={null}
CREATE TABLE dates
(
    `date` Date,
    `wider_date` Date32,
    `datetime` DateTime,
    `precise_datetime` DateTime64(3),
    `very_precise_datetime` DateTime64(9)
)
ENGINE = MergeTree
ORDER BY tuple();
```

我们可以使用 [`now()`](/docs/zh/reference/functions/regular-functions/date-time-functions#now) 函数返回当前时间，并使用 [`now64()`](/docs/zh/reference/functions/regular-functions/date-time-functions#now64) 通过第一个参数按指定精度返回该时间。

```sql theme={null}
INSERT INTO dates 
SELECT now(), 
       now()::Date32 + toIntervalYear(100),
       now(), 
       now64(3), 
       now64(9) + toIntervalYear(200);
```

这会根据列类型为相应的列填入时间值：

```sql theme={null}
SELECT * FROM dates
FORMAT Vertical;
```

```text theme={null}
Row 1:
──────
date:                  2025-03-12
wider_date:            2125-03-12
datetime:              2025-03-12 11:39:07
precise_datetime:      2025-03-12 11:39:07.196
very_precise_datetime: 2025-03-12 11:39:07.196724000
```

<div id="time-series-time-types">
  ## Time 和 Time64 类型
</div>

对于需要存储不包含日期 components 的时刻值的场景，ClickHouse 提供了 [`Time`](/docs/zh/reference/data-types/time) 和 [`Time64`](/docs/zh/reference/data-types/time64) 类型，它们于 25.6 版本中引入。这些类型适合表示重复性计划、每日规律，或其他适合将日期与时间 components 分开处理的场景。

<Note>
  使用 `Time` 和 `Time64` 需要启用以下设置：`SET enable_time_time64_type = 1;`

  这些类型于 25.6 版本引入
</Note>

`Time` 类型以秒级精度存储小时、分钟和秒。它在内部以有符号 32 位整数存储，支持 `[-999:59:59, 999:59:59]` 范围，因此可以表示超过 24 小时的值。这在跟踪耗时或进行结果超出单日范围的算术运算时非常有用。

对于子秒级精度，`Time64` 以有符号 Decimal64 值存储时间，并支持可配置的秒小数部分。它接受一个精度参数 (0-9) 来定义小数位数。常见精度值包括 3 (毫秒) 、6 (微秒) 和 9 (纳秒) 。

`Time` 和 `Time64` 都不支持时区——它们表示的是不带区域上下文的纯时刻值。

让我们创建一个包含时间列的表：

```sql theme={null}
SET enable_time_time64_type = 1;

CREATE TABLE time_examples
(
    `event_id` UInt8,
    `basic_time` Time,
    `precise_time` Time64(3)
)
ENGINE = MergeTree
ORDER BY event_id;
```

可以使用字符串字面量或数值插入时间值。对于 `Time`，数值会被解释为自 00:00:00 起的秒数。对于 `Time64`，数值同样会被解释为自 00:00:00 起的秒数，其中的小数部分则按该列的精度解释：

```sql theme={null}
INSERT INTO time_examples VALUES 
    (1, '14:30:25', '14:30:25.123'),
    (2, 52225, 52225.456),
    (3, '26:11:10', '26:11:10.789');  -- 超过 24 小时的值会被规范化

SELECT * FROM time_examples ORDER BY event_id;
```

```text theme={null}
┌─event_id─┬─basic_time─┬─precise_time─┐
│        1 │ 14:30:25   │ 14:30:25.123 │
│        2 │ 14:30:25   │ 14:30:25.456 │
│        3 │ 26:11:10   │ 26:11:10.789 │
└──────────┴────────────┴──────────────┘
```

可以直接按时间值进行过滤：

```sql theme={null}
SELECT * FROM time_examples WHERE basic_time = '14:30:25';
```

<div id="time-series-timezones">
  ## 时区
</div>

许多使用场景还需要一并存储时区。我们可以将时区设置为 `DateTime` 或 `DateTime64` 类型的最后一个参数：

```sql theme={null}
CREATE TABLE dtz
(
    `id` Int8,
    `dt_1` DateTime('Europe/Berlin'),
    `dt_2` DateTime,
    `dt64_1` DateTime64(9, 'Europe/Berlin'),
    `dt64_2` DateTime64(9)
)
ENGINE = MergeTree
ORDER BY id;
```

在 DDL 中定义时区后，我们现在可以使用不同时区写入时间值：

```sql theme={null}
INSERT INTO dtz 
SELECT 1, 
       toDateTime('2022-12-12 12:13:14', 'America/New_York'),
       toDateTime('2022-12-12 12:13:14', 'America/New_York'),
       toDateTime64('2022-12-12 12:13:14.123456789', 9, 'America/New_York'),
       toDateTime64('2022-12-12 12:13:14.123456789', 9, 'America/New_York')
UNION ALL
SELECT 2, 
       toDateTime('2022-12-12 12:13:15'),
       toDateTime('2022-12-12 12:13:15'),
       toDateTime64('2022-12-12 12:13:15.123456789', 9),
       toDateTime64('2022-12-12 12:13:15.123456789', 9);
```

现在来看看我们的表里有什么：

```sql theme={null}
SELECT dt_1, dt64_1, dt_2, dt64_2
FROM dtz
FORMAT Vertical;
```

```text theme={null}
第 1 行：
──────
dt_1:   2022-12-12 18:13:14
dt64_1: 2022-12-12 18:13:14.123456789
dt_2:   2022-12-12 17:13:14
dt64_2: 2022-12-12 17:13:14.123456789

第 2 行：
──────
dt_1:   2022-12-12 13:13:15
dt64_1: 2022-12-12 13:13:15.123456789
dt_2:   2022-12-12 12:13:15
dt64_2: 2022-12-12 12:13:15.123456789
```

在第一行中，我们使用 `America/New_York` 时区插入了所有值。

* `dt_1` 和 `dt64_1` 会在查询时自动转换为 `Europe/Berlin`。
* `dt_2` 和 `dt64_2` 没有指定时区，因此会使用服务器的本地时区，在本例中为 `Europe/London`。

在第二行中，我们插入所有值时都未指定时区，因此使用了服务器的本地时区。
与第一行一样，`dt_1` 和 `dt64_1` 会转换为 `Europe/Berlin`，而 `dt_2` 和 `dt64_2` 使用服务器的本地时区。

<div id="time-series-date-time-functions">
  ## 日期和时间函数
</div>

ClickHouse 还提供了一组函数，让我们可以在不同的数据类型之间进行转换。

例如，我们可以使用 [`toDate`](/docs/zh/reference/functions/regular-functions/type-conversion-functions#toDate) 将 `DateTime` 值转换为 `Date` 类型：

```sql theme={null}
SELECT
    now() AS current_time,
    toTypeName(current_time),
    toDate(current_time) AS date_only,
    toTypeName(date_only)
FORMAT Vertical;    
```

```text theme={null}
第 1 行：
──────
current_time:             2025-03-12 12:32:54
toTypeName(current_time): DateTime
date_only:                2025-03-12
toTypeName(date_only):    Date
```

我们可以使用 [`toDateTime64`](/docs/zh/reference/functions/regular-functions/type-conversion-functions#toDateTime64) 将 `DateTime` 转为 `DateTime64`：

```sql theme={null}
SELECT
    now() AS current_time,
    toTypeName(current_time),
    toDateTime64(current_time, 3) AS date_only,
    toTypeName(date_only)
FORMAT Vertical;
```

```text theme={null}
Row 1:
──────
current_time:             2025-03-12 12:35:01
toTypeName(current_time): DateTime
date_only:                2025-03-12 12:35:01.000
toTypeName(date_only):    DateTime64(3)
```

我们还可以使用 [`toDateTime`](/docs/zh/reference/functions/regular-functions/type-conversion-functions#toDateTime) 将 `Date` 或 `DateTime64` 转回 `DateTime`：

```sql theme={null}
SELECT
    now64() AS current_time,
    toTypeName(current_time),
    toDateTime(current_time) AS date_time1,
    toTypeName(date_time1),
    today() AS current_date,
    toTypeName(current_date),
    toDateTime(current_date) AS date_time2,
    toTypeName(date_time2)
FORMAT Vertical;
```

```text theme={null}
第 1 行：
──────
current_time:             2025-03-12 12:41:00.598
toTypeName(current_time): DateTime64(3)
date_time1:               2025-03-12 12:41:00
toTypeName(date_time1):   DateTime
current_date:             2025-03-12
toTypeName(current_date): Date
date_time2:               2025-03-12 00:00:00
toTypeName(date_time2):   DateTime
```
