日期和时间函数
以下为GaussDB数据库MySQL兼容性MySQL模式中日期时间函数的公共说明,与MySQL行为一致。
- 函数入参为时间类型表达式的情况:
时间类型表达式主要包括text、datetime、date或time,但所有可以隐式转换为时间表达式的类型都可以作为入参,比如数字类型可以通过先隐式转化为text,再作为时间类型表达式生效。
但是,不同函数的具体生效情况会有所不同。例如:datediff函数仅计算日期之间的差值,因此时间表达式会被解析为日期;而timestampdiff函数在计算时间差值时,会根据unit参数来决定将时间表达式解析为date、time或 datetime。
- 函数入参为无效日期的情况:
一般而言,日期时间函数支持date、datetime的范围和MySQL保持一致。date支持的范围为'0000-01-01'到'9999-12-31',datetime支持的范围为'0000-01-01 00:00:00'到'9999-12-31 23:59:59'。虽然GaussDB支持的date、datetime范围大于MySQL,但是越界仍然算无效日期。
大部分时间函数对于入参为无效时间时,会告警并返回NULL,只有能通过cast正常转换的日期,才是正常合理的日期。
- 函数入参的分隔符场景:
对于时间函数,处理入参时会将所有非数字字符视作分隔符,然后根据数字所处的位置进行计算,推荐使用标准写法,年月日之间使用-分隔符,时分秒之间使用:分隔符,毫秒之前通过.来进行分隔。
易错场景:在MySQL兼容性MySQL模式数据库中执行“SELECT timestampdiff(hour, '2020-03-01 00:00:00', '2020-02-28 00:00:00+08');”时,时间函数不会自动计算时区,所以此处+08并未识别为时区,而是+作为分隔符当作秒来进行计算。
GaussDB的日期时间函数的大部分功能场景与MySQL一致,但仍有差异,部分差异如下:
- 函数入参为NULL时,函数返回NULL,无warning或error告警。这些函数包括:
from_days、date_format、str_to_date、datediff、timestampdiff、date_add、subtime、month、time_to_sec、to_days、to_seconds、dayname、monthname、convert_tz、sec_to_time、addtime、adddate、date_sub、timediff、last_day、weekday、from_unixtime、unix_timestamp、subdate、day、year、weekofyear、dayofmonth、dayofyear、week、yearweek、dayofweek、time_format、hour、minute、second、microsecond、quarter、get_format、extract、makedate、period_add、timestampadd、period_diff、utc_time、utc_timestamp、maketime、curtime
示例:
gaussdb=# SELECT day(null); day ----- (1 row)
- 纯数字入参个别函数与MySQL有差异,不带引号的数字入参统一转成text入参来处理。
gaussdb=# SELECT day(19231221.123141); WARNING: Incorrect datetime value: "19231221.123141" CONTEXT: referenced column: day day ----- (1 row)
- 时间日期运算函数:adddate、subdate、date_add、date_sub。当运算后的结果为日期时,支持的范围为[0000-01-01, 9999-12-31],当运算后的结果为日期时间时,支持的范围为[0000-01-01 00:00:00.000000, 9999-12-31 23:59:59.999999],当运算后的结果超过支持的范围时,在严格模式下报ERROR,在宽松模式下报WARNING。另外,当运算后的日期结果在范围[0000-01-01, 0001-01-01]中时,GaussDB正常返回结果,MySQL返回'0000-00-00'。
gaussdb=# SELECT subdate('0000-01-01', interval 1 hour); ERROR: Datetime function: datetime field overflow CONTEXT: referenced column: subdate gaussdb=# SELECT subdate('0001-01-01', interval 1 day); subdate ------------- 0000-12-31 (1 row)
- 对于日期和时间函数的date或datetime类型入参,含有0月或0日则为非法值,在严格模式下报error;在宽松模式,当输入为字符串或数字时,报warning,输入为date或datetime类型时视为上一年12月或上一月最后一日处理。
对于cast函数,转换为date、datetime时,严格模式下会报error;宽松模式下不会报warning,而是视为上一年12月或上一月最后一日处理,需要注意此区别。MySQL对于包含0年、0月或0日的情况会原样输出。
示例:
gaussdb=# SELECT adddate('2023-01-00', 1);-- 严格模式 ERROR: Incorrect datetime value: "2023-01-00" CONTEXT: referenced column: adddate gaussdb=# SELECT adddate('2023-01-00', 1);-- 宽松模式 WARNING: Incorrect datetime value: "2023-01-00" CONTEXT: referenced column: adddate adddate --------- (1 row) gaussdb=# SELECT adddate(date'2023-00-00', 1);-- 宽松模式 adddate ------------ 2022-12-01 (1 row) gaussdb=# SELECT cast('2023/00/00' AS date);-- 宽松模式 date ------------ 2022-11-30 (1 row) gaussdb=# SELECT cast('0000-00-00' AS datetime);-- 宽松模式 timestamp --------------------- 0000-00-00 00:00:00 (1 row)
- 若函数入参为numeric数据类型,在非法输入的情况下不会产生报错,会把入参当做0值处理。
gaussdb=# SELECT from_unixtime('aa'); from_unixtime --------------------- 1970-01-01 08:00:00 (1 row)
- 最多保留6位小数,不保留后置都为0的小数。
gaussdb=# SELECT from_unixtime('1234567899.00000'); from_unixtime --------------------- 2009-02-14 07:31:39 (1 row)
- 时间函数参数为字符串时,只保证年月日之间使用“-”分隔,时分秒之间使用“:”分隔时结果正确。
gaussdb=# SELECT adddate('20-12-12',interval 1 day); adddate ------------ 2020-12-13 (1 row)
- 在MySQL中,当函数的返回值为varchar时,在GaussDB中,函数对应的返回值为text。
-- GaussDB中函数的返回值。 gaussdb=# SELECT pg_typeof(adddate('2023-01-01', 1)); pg_typeof ----------- text (1 row) -- MySQL中函数的返回值。 mysql> CREATE VIEW v1 AS SELECT adddate('2023-01-01', 1); Query OK, 0 rows affected (0.00 sec) mysql> DESC v1; +--------------------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +--------------------------+-------------+------+-----+---------+-------+ | adddate('2023-01-01', 1) | varchar(29) | YES | | NULL | | +--------------------------+-------------+------+-----+---------+-------+ 1 row in set (0.00 sec)
MySQL数据库 |
GaussDB数据库 |
差异 |
---|---|---|
ADDDATE() |
支持,存在差异 |
此函数的表现会因为interval表达式的差异与MySQL有差异,具体可见INTERVAL差异说明。 |
ADDTIME() |
支持,存在差异 |
|
CONVERT_TZ() |
支持 |
- |
CURDATE() |
支持 |
- |
CURRENT_DATE(), CURRENT_DATE |
支持 |
- |
CURRENT_TIME(), CURRENT_TIME |
支持,存在差异 |
GaussDB的按精度输出的时间值(小数点后的值)是四舍五入的;MySQL是直接截断的。GaussDB按精度输出的时间值(小数点后的值)末尾0都不显示;MySQL会显示。GaussDB只支持输入[0,6]范围内的整型值,作为返回时间的精度,其他均报错;MySQL的精度值有效值是[0,6],但是输入的整型值内部会对256求余(例257,会返回精度1的时间值)。 |
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP |
支持,存在差异 |
GaussDB的按精度输出的时间值(小数点后的值)是四舍五入的;MySQL是直接截断的。GaussDB按精度输出的时间值(小数点后的值)末尾0都不显示;MySQL会显示。GaussDB只支持输入[0,6]范围内的整型值,作为返回时间的精度,超过6的整型值,会告警并按照精度6输出时间值;MySQL的精度值有效值是[0,6],但是输入的整型值内部会对256求余(例257,会返回精度1的时间值)。 |
CURTIME() |
支持,存在差异 |
GaussDB此函数输入字符串或者非整型值,会被隐式转成整型,然后再校验精度,[0,6]范围之外的会报错,范围之内会正常输出时间值;MySQL直接报错。GaussDB的按精度输出的时间值(小数点后的值)是四舍五入的;MySQL是直接截断的。GaussDB按精度输出的时间值(小数点后的值)末尾0都不显示;MySQL会显示。GaussDB只支持输入[0,6]范围内的整型值,作为返回时间的精度,其他均报错;MySQL的精度值有效值是[0,6],但是输入的整型值内部会对256求余(例257,会返回精度1的时间值)。 |
YEARWEEK() |
支持 |
- |
DATE_ADD() |
支持,存在差异 |
此函数的表现会因为interval表达式的差异与MySQL有差异,具体可见INTERVAL差异说明。 |
DATE_FORMAT() |
支持 |
- |
DATE_SUB() |
支持,存在差异 |
此函数的表现会因为interval表达式的差异与MySQL有差异,具体可见INTERVAL差异说明。 |
DATEDIFF() |
支持 |
- |
DAY() |
支持 |
- |
DAYNAME() |
支持 |
- |
DAYOFMONTH() |
支持 |
- |
DAYOFWEEK() |
支持 |
- |
DAYOFYEAR() |
支持 |
- |
EXTRACT() |
支持 |
- |
FROM_DAYS() |
支持 |
- |
FROM_UNIXTIME() |
支持 |
- |
GET_FORMAT() |
支持 |
- |
HOUR() |
支持 |
- |
LAST_DAY |
支持 |
- |
LOCALTIME(), LOCALTIME |
支持,存在差异 |
GaussDB的按精度输出的时间值(小数点后的值)是四舍五入的;MySQL是直接截断的。GaussDB按精度输出的时间值(小数点后的值)末尾0都不显示;MySQL会显示。GaussDB只支持输入[0,6]范围内的整型值,作为返回时间的精度,其他整型值直接报错;MySQL的精度值有效值是[0,6],但是输入的整型值内部会对256求余(例257,会返回精度1的时间值)。 |
LOCALTIMESTAMP, LOCALTIMESTAMP() |
支持,存在差异 |
GaussDB的按精度输出的时间值(小数点后的值)是四舍五入的;MySQL是直接截断的。GaussDB按精度输出的时间值(小数点后的值)末尾0都不显示;MySQL会显示。GaussDB只支持输入[0,6]范围内的整型值,作为返回时间的精度,超过6的整型值,会告警并按照精度6输出时间值;MySQL的精度值有效值是[0,6],但是输入的整型值内部会对256求余(例257,会返回精度1的时间值)。 |
MAKEDATE() |
支持 |
- |
MAKETIME() |
支持,存在差异 |
与MySQL相比, 入参为NULL时,GaussDB不支持maketime函数自嵌套,MySQL支持。 |
MICROSECOND() |
支持 |
- |
MINUTE() |
支持 |
- |
MONTH() |
支持 |
- |
MONTHNAME() |
支持 |
- |
NOW() |
支持,存在差异 |
GaussDB的按精度输出的时间值(小数点后的值)是四舍五入的;MySQL是直接截断的。GaussDB按精度输出的时间值(小数点后的值)末尾0都不显示;MySQL会显示。GaussDB只支持输入[0,6]范围内的整型值,作为返回时间的精度,超过6的整型值,会告警并按照精度6输出时间值;MySQL的精度值有效值是[0,6],但是输入的整型值内部会对256求余(例257,会返回精度1的时间值)。 |
PERIOD_ADD() |
支持,存在差异 |
当入参period或结果小于0时,GaussDB参考MySQL 8.0.x版本的表现,报错处理。MySQL 5.7会发生整数回绕,导致计算结果异常。 |
PERIOD_DIFF() |
支持,存在差异 |
当入参或结果小于0时,GaussDB参考MySQL 8.0.x版本的表现,报错处理。MySQL 5.7会发生整数回绕,导致计算结果异常。 |
QUARTER() |
支持 |
- |
SEC_TO_TIME() |
支持 |
- |
SECOND() |
支持 |
- |
STR_TO_DATE() |
支持,存在差异 |
返回值与MySQL有差异,GaussDB返回的是text,MySQL返回的是datetime、date。 |
SUBDATE() |
支持,存在差异 |
此函数的表现会因为interval表达式的差异与MySQL有差异,具体可见INTERVAL差异说明。 |
SUBTIME() |
支持,存在差异 |
|
SYSDATE() |
支持,存在差异 |
MySQL入参整型值会按照一字节最大值255整数回绕,Gauss不回绕。 |
YEAR() |
支持 |
- |
TIME_FORMAT() |
支持 |
- |
TIME_TO_SEC() |
支持 |
- |
TIMEDIFF() |
支持 |
- |
WEEKOFYEAR() |
支持 |
- |
TIMESTAMPADD() |
支持 |
- |
TIMESTAMPDIFF() |
支持 |
- |
TO_DAYS() |
支持 |
- |
TO_SECONDS() |
支持 |
- |
UNIX_TIMESTAMP() |
支持,存在差异 |
返回值与MySQL有差异,GaussDB返回的是numeric,MySQL返回的是int。 |
UTC_DATE() |
支持,存在差异 |
|
UTC_TIME() |
支持,存在差异 |
|
UTC_TIMESTAMP() |
支持,存在差异 |
|
WEEK() |
支持 |
- |
WEEKDAY() |
支持 |
- |