# 13.9 TIME

在本教程中，我们将向您介绍MySQL `TIME`数据类型，并显示有用的时间函数来有效地处理时间数据。

## MySQL TIME数据类型简介

MySQL使用`HH:MM:SS`格式来查询和显示代表一天中的时间值(在`24`小时内)。要表示两个事件之间的时间[间隔](http://www.yiibai.com/mysql/interval.html)，MySQL使用大于`24`小时的`HHH:MM:SS`格式。

要定义`TIME`数据类型的列，请使用以下语法：

```sql
column_name TIME;
```

例如，以下代码片段定义了一个名为`start_at`的列，其中包含`TIME`数据类型。

```sql
start_at TIME;
```

`TIME`值范围为`-838:59:59`至`838:59:59`。 此外，`TIME`值可以具有高达微秒精度(`6`位数)的小数秒部分。 要使用小数秒精度部分定义数据类型为`TIME`的列，请使用以下语法：

```sql
column_name TIME(N);
```

*N*是表示小数部分的[整数值](http://www.yiibai.com/mysql/int.html)，最多`6`位数。

以下代码片段定义了`TIME`数据类型的列，其中包含`3`位数的小数秒。

```sql
begin_at TIME(3);
```

`TIME`值需要`3`个字节进行存储。如果`TIME`值包括分数秒精度，则会根据小数秒精度的位数获取额外的字节。下表说明了小数秒精度所需的存储空间。

| 分数秒精度 | 存储(字节) |
| ----- | ------ |
| 0     | 0      |
| 1，2   | 1      |
| 3，4   | 2      |
| 5，6   | 3      |

例如，`TIME`和`TIME(0)`需要`3`个字节。 `TIME(1)`和`TIME(2)`需要`4`个字节(`3 + 1`); `TIME(3)`和`TIME(6)`分别需要`5`和`6`个字节。

## MySQL TIME数据类型示例

让我们来看一下在表中对列使用`TIME`数据类型的例子。

**首先**，创建一个名为`tests`的新表，其中包含四个列：`id`，`name`，`start_at`和`end_at`。 `start_at`和`end_at`列的数据类型为`TIME`。

```sql
USE testdb;

CREATE TABLE tests (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    start_at TIME,
    end_at TIME
);
```

**第二步**，在`tests`表中[插入](http://www.yiibai.com/mysql/insert-statement.html)一行。

```sql
INSERT INTO tests(name,start_at,end_at)
VALUES('Test 1', '08:00:00','10:00:00');
```

**第三步**，从`tests`表[查询数据](http://www.yiibai.com/mysql/select-statement-query-data.html)，如下语句：

```sql
SELECT 
    name, start_at, end_at
FROM
    tests;
```

执行上面查询语句，得到以下结果 -

```
```

请注意，我们使用“`HH:MM:SS`”作为[INSERT](http://www.yiibai.com/mysql/insert-statement.html)语句中的文字时间值。下面来看看MySQL可以识别的所有有效的时间文字。

## MySQL TIME文字

除了我们之前提到的“`HH:MM:SS`”格式之外，MySQL还可以识别各种时间格式。

MySQL允许使用“`HHMMSS`”格式，而不使用分隔符(`:`)表示时间值。 例如’`08:30:00`‘和’`10:15:00`‘可以重写为’`083000`‘和’`101500`‘。

```sql
INSERT INTO tests(name,start_at,end_at)
VALUES('Test 2','083000','101500');
```

但是，`108000`不是有效的时间值，因为`80`不代表正确的分钟。 在这种情况下，如果您尝试在表中插入无效的时间值，MySQL会引发错误。

```sql
INSERT INTO tests(name,start_at,end_at)
VALUES('Test invalid','083000','108000');
```

执行上述语句后，MySQL发出以下错误消息。

```sql
Error Code: 1292. Incorrect time value: '108000' for column 'end_at' at row 1
```

除了字符串格式之外，MySQL接受`HHMMSS`作为代表时间值的数字。也可以使用`SS`，`MMSS`。 例如，可以使用`082000`，而不是使用`'082000'`，如下所示：

```sql
INSERT INTO tests(name,start_at,end_at)
VALUES('Test 3',082000,102000);
```

对于时间间隔，您可以使用`'D HH:MM:SS'`格式，其中`D`代表天数从`0`到`34`的范围。更灵活的语法是`'HH:MM'`，`'D HH:MM'`，`'D HH'`或`'SS'`。

如果使用分隔符`:`，可以使用`1`位数字表示小时，分钟或秒。 例如，可以使用`9:5:0`而不是`'09:05:00'`。

```sql
INSERT INTO tests(name,start_at,end_at)
VALUES('Test 4','9:5:0',100500);
```

## MySQL TIME函数

MySQL提供了几个有用的时间函数来处理`TIME`数据。

**获取当前时间**

要获取数据库服务器的当前时间，请使用`CURRENT_TIME`函数。根据使用该函数的上下文，`CURRENT_TIME`函数以字符串(`'HH:MM:SS'`)或数值(`HHMMSS`)返回当前时间值。

以下语句说明了字符串和数字上下文中的`CURRENT_TIME`函数：

```sql
SELECT 
    CURRENT_TIME() AS string_now,
    CURRENT_TIME() + 0 AS numeric_now;
```

执行上面查询语句，得到以下结果 -

```sql
+------------+-------------+
| string_now | numeric_now |
+------------+-------------+
| 23:04:53   |      230453 |
+------------+-------------+
1 row in set
```

**从TIME值添加和减去时间**

要将`TIME`值添加到另一个`TIME`值，请使用`ADDTIME`函数。要从另一个`TIME`值中减去`TIME`值，可以使用`SUBTIME`函数。

以下语句从当前时间起减去`2`小时`30`分钟。

```sql
SELECT 
    CURRENT_TIME(),
    ADDTIME(CURRENT_TIME(), 023000), 
    SUBTIME(CURRENT_TIME(), 023000);
```

执行上面查询语句，得到以下结果 -

```sql
+----------------+---------------------------------+---------------------------------+
| CURRENT_TIME() | ADDTIME(CURRENT_TIME(), 023000) | SUBTIME(CURRENT_TIME(), 023000) |
+----------------+---------------------------------+---------------------------------+
| 23:05:03       | 25:35:03                        | 20:35:03                        |
+----------------+---------------------------------+---------------------------------+
1 row in set
```

此外，可以使用`TIMEDIFF()`函数来获取两个`TIME`值之间的差异。

```sql
SELECT 
    TIMEDIFF(end_at, start_at)
FROM
    tests;
```

执行上面查询语句，得到以下结果 -

```sql
mysql> SELECT 
    TIMEDIFF(end_at, start_at)
FROM
    tests;
+----------------------------+
| TIMEDIFF(end_at, start_at) |
+----------------------------+
| 02:00:00                   |
| 01:45:00                   |
| 02:00:00                   |
| 01:00:00                   |
+----------------------------+
4 rows in set
```

**格式化MySQL TIME值**

虽然MySQL在检索和显示`TIME`值时使用“`HH:MM:SS`”，但可以使用`TIME_FORMAT`函数以推荐的方式显示`TIME`值。

`TIME_FORMAT`函数类似于[DATE\_FORMAT](http://www.yiibai.com/mysql/date_format.html)函数，除了`TIME_FORMAT`函数仅用于格式化`TIME`值其它均差不多。

请参见以下一个示例 -

```sql
SELECT 
    name,
    TIME_FORMAT(start_at, '%h:%i %p') start_at,
    TIME_FORMAT(end_at, '%h:%i %p') end_at
FROM
    tests;
```

执行上面查询语句，得到以下结果 -

```sql
+--------+----------+----------+
| name   | start_at | end_at   |
+--------+----------+----------+
| Test 1 | 08:00 AM | 10:00 AM |
| Test 2 | 08:30 AM | 10:15 AM |
| Test 3 | 08:20 AM | 10:20 AM |
| Test 4 | 09:05 AM | 10:05 AM |
+--------+----------+----------+
4 rows in set
```

在上面的时间格式字符串中：

* `％h`表示从`0`到`12`的两位数小时数值。
* `％i`表示从`0`到`60`的两位数分钟数值。
* `％p`表示`AM`或`PM`，也就是表示上午或下午。

**从TIME值提取小时，分钟和秒**

要从`TIME`值中提取小时，分和秒，可以使用`HOUR`，`MINUTE`和`SECOND`函数，如下所示：

![img](/files/-LyNuzAL_hLo8dqDLYiO)

**获取UTC时间值**

要获取`UTC`时间，请使用`UTC_TIME`函数，如下所示：

```sql
SELECT 
   CURRENT_TIME(), 
   UTC_TIME();
```

执行上面查询语句，得到以下结果 -

```sql
+----------------+------------+
| CURRENT_TIME() | UTC_TIME() |
+----------------+------------+
| 23:05:41       | 15:05:41   |
+----------------+------------+
1 row in set
```

在本教程中，我们已经介绍了有关MySQL `TIME`数据类型和一些常用的时间函数来处理`TIME`值。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://hezhiqiang-book.gitbook.io/mysql/di-yi-zhang/index-12/time.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
