返回介绍

日期和时间类型

发布于 2020-10-26 07:01:32 字数 9130 浏览 1075 评论 0 收藏 0

TiDB 支持 MySQL 所有的日期和时间类型,包括 、、、 以及 。完整信息可以参考 MySQL 中的时间和日期类型

每种类型都有有效值范围,值为 0 表示无效值。此外,TIMESTAMPDATETIME 类型能自动生成新的时间值。

关于日期和时间值类型,需要注意:

  • 日期部分必须是“年-月-日”的格式(例如 1998-09-04),而不是“月-日-年”或“日-月-年”的格式。

  • 如果日期的年份部分是 2 位数,TiDB 会根据类型定义

    DATE 类型

    DATE 类型只包含日期部分,不包含时间部分。DATE 类型的格式为 YYYY-MM-DD,支持的范围是 1000-01-019999-12-31

    DATE

    TIME 类型

    TIME 类型的格式为 HH:MM:SS[.fraction],支持的范围是 -838:59:59.000000838:59:59.000000TIME 不仅可用于指示一天内的时间,还可用于指两个事件之间的时间间隔。fsp 参数表示秒精度,取值范围为:0 ~ 6,默认值为 0。

    TIME[(fsp)]

    注意:

    注意 TIME 的缩写形式。例如,11:12 表示 11:12:00 而不是 00:11:12。但是,1112 表示 00:11:12。这些差异取决于 : 字符的存在与否。

    DATETIME 类型

    DATETIME 类型是日期和时间的组合,格式为 YYYY-MM-DD HH:MM:SS[.fraction]。支持的范围是 1000-01-01 00:00:00.0000009999-12-31 23:59:59.999999fsp 参数表示秒精度,取值范围为 0~6,默认值为 0。TiDB 支持字符串或数字转换为 DATETIME 类型。

    DATETIME[(fsp)]

    TIMESTAMP 类型

    TIMESTAMP 类型是日期和时间的组合,支持的范围是 UTC 时间从 1970-01-01 00:00:01.0000002038-01-19 03:14:07.999999fsp 参数表示秒精度,取值范围为 0~6,默认值为 0。在 TIMESTAMP 中,不允许零出现在月份部分或日期部分,唯一的例外是零值本身 0000-00-00 00:00:00

    TIMESTAMP[(fsp)]

    时区处理

    当存储 TIMESTAMP 时,TiDB 会将当前时区的 TIMESTAMP 值转换为 UTC 时区。当读取 TIMESTAMP 时,TiDB 将存储的 TIMESTAMP 值从 UTC 时区转换为当前时区(注意:DATETIME 不会这样处理)。每次连接的默认时区是服务器的本地时区,可以通过环境变量 time_zone 进行修改。

    警告:

    和 MySQL 一样,TIMESTAMP 数据类型受 2038 年问题的影响。如果存储的值大于 2038,建议使用 DATETIME 类型。

    YEAR 类型

    YEAR 类型的格式为 YYYY,支持的值范围是 19012155,也支持零值 0000

    YEAR[(4)]

    YEAR 类型遵循以下格式规则:

    • 如果是四位数的数值,支持的范围是 19012155
    • 如果是四位数的字符串,支持的范围是 '1901''2155'
    • 如果是 1~99 之间的一位数或两位数的数字,1~69 换算成 2001~2069,70~99 换算成 1970~1999。
    • 支持 '0''99' 之间的一位数或两位数字符串的范围
    • 将数值 0 转换为 0000,将字符串 '0''00' 转换为 '2000'

    无效的 YEAR 值会自动转换为 0000(如果用户没有使用 NO_ZERO_DATE SQL 模式)。

    自动初始化和更新 TIMESTAMPDATETIME

    带有 TIMESTAMPDATETIME 数据类型的列可以自动初始化为或更新为当前时间。

    对于表中任何带有 TIMESTAMPDATETIME 数据类型的列,你可以设置默认值,或自动更新为当前时间戳。

    在定义列的时候,TIMESTAMPDATETIME 可以通过 DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP 来设置。DEFAULT 也可以设置为一个特定的值,例如 DEFAULT 0DEFAULT '2000-01-01 00:00:00'

    CREATE TABLE t1 (
        ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    );

    除非指定 DATETIME 的值为 NOT NULL,否则默认 DATETIME 的值为 NULL。指定 DATETIME 的值为 NOT NULL 时,如果没有设置默认值,则默认值为 0

    CREATE TABLE t1 (
        dt1 DATETIME ON UPDATE CURRENT_TIMESTAMP,         -- default NULL
        dt2 DATETIME NOT NULL ON UPDATE CURRENT_TIMESTAMP -- default 0
    );

    时间值的小数部分

    DATETIMETIMESTAMP 值最多可以有 6 位小数,精确到毫秒。如果包含小数部分,值的格式为 YYYY-MM-DD HH:MM:SS[.fraction],小数部分的范围为 000000999999。必须使用小数点分隔小数部分与其他部分。

    • 使用 type_name(fsp) 可以定义精确到小数的列,其中 type_name 可以是TIMEDATETIMETIMESTAMP。例如:

      CREATE TABLE t1 (t TIME(3), dt DATETIME(6));

      fsp 范围是 06

      0 表示没有小数部分。如果省略了 fsp ,默认为 0

    • 当插入包含小数部分的 TIMEDATETIMETIMESTAMP 时,如果小数部分的位数过少或过多,可能需要进行四舍五入。例如:

      CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(2), c3 TIMESTAMP(2) );
      Query OK, 0 rows affected (0.33 sec)
      INSERT INTO fractest VALUES
           > ('17:51:04.777', '2014-09-08 17:51:04.777',   '2014-09-08 17:51:04.777');
      Query OK, 1 row affected (0.03 sec)
      SELECT * FROM fractest;
      +-------------|------------------------|------------------------+
      | c1          | c2                     | c3                     |
      +-------------|------------------------|------------------------+
      | 17:51:04.78 | 2014-09-08 17:51:04.78 | 2014-09-08 17:51:04.78 |
      +-------------|------------------------|------------------------+
      1 row in set (0.00 sec)

    日期和时间类型的转换

    在日期和时间类型之间进行转换时,有些转换可能会导致信息丢失。例如,DATEDATETIMETIMESTAMP 都有各自的有效值范围。TIMESTAMP 不能早于 UTC 时间的 1970 年,也不能晚于 UTC 时间的 2038-01-19 03:14:07。根据这个规则,1968-01-01 对于 DATEDATETIME 是有效的,但当 1968-01-01 转换为 TIMESTAMP 时,就会变成 0。

    DATE 的转换:

    • DATE 转换为 DATETIMETIMESTAMP 时,会添加时间部分 00:00:00,因为 DATE 不包含任何时间信息。
    • DATE 转换为 TIME 时,结果是 00:00:00

    DATETIMETIMESTAMP 的转换:

    • DATETIMETIMESTAMP 转换为 DATE 时,时间和小数部分将被舍弃。例如,1999-12-31 23:59:59.499 被转换为 1999-12-31
    • DATETIMETIMESTAMP 转换为 TIME 时,时间部分被舍弃,因为 TIME 不包含任何时间信息。

    如果要将 TIME 转换为其他时间和日期格式,日期部分会自动指定为 CURRENT_DATE()。最终的转换结果是由 TIMECURRENT_DATE() 组成的日期。也就是说,如果 TIME 的值超出了 00:00:0023:59:59 的范围,那么转换后的日期部分并不表示当前的日期。

    TIME 转换为 DATE 时,转换过程类似,时间部分被舍弃。

    使用 CAST() 函数可以显式地将值转换为 DATE 类型。例如:

    date_col = CAST(datetime_col AS DATE)

    TIMEDATETIME 转换为数字格式。例如:

    SELECT CURTIME(), CURTIME()+0, CURTIME(3)+0;
    +-----------|-------------|--------------+
    | CURTIME() | CURTIME()+0 | CURTIME(3)+0 |
    +-----------|-------------|--------------+
    | 09:28:00  |       92800 |    92800.887 |
    +-----------|-------------|--------------+
    SELECT NOW(), NOW()+0, NOW(3)+0;
    +---------------------|----------------|--------------------+
    | NOW()               | NOW()+0        | NOW(3)+0           |
    +---------------------|----------------|--------------------+
    | 2012-08-15 09:28:00 | 20120815092800 | 20120815092800.889 |
    +---------------------|----------------|--------------------+

    年份为两位数

    如果日期中包含年份为两位数,这个年份是有歧义的,并不显式地表示实际年份。

    对于 DATETIMEDATETIMESTAMP 类型,TiDB 使用如下规则来消除歧义。

    • 将 01 至 69 之间的值转换为 2001 至 2069 之间的值。
    • 将 70 至 99 之间的值转化为 1970 至 1999 之间的值。

    上述规则也适用于 YEAR 类型,但有一个例外。将数字 00 插入到 YEAR(4) 中时,结果是 0000 而不是 2000。

    如果想让结果是 2000,需要指定值为 2000

    对于 MIN()MAX() 等函数,年份为两位数时可能会得到错误的计算结果。建议年份为四位数时使用这类函数。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文