mysqltimedstconvert-tz

why SELECT in (IDENTIC: [version MySQL + SESSION.sql_mode + system_time_zone]) return NULL in CentOs 7 but GOAL + WARNING on W10?


I know the warning is by DST, but why different results with the QUERY:

SELECT CONVERT_TZ('2002-10-23T15:57:03Z', 'SYSTEM', 'America/Bogota')

when I run the QUERY in CentOs 7 with:

[VERSION()] => 5.7.33
[@@SESSION.sql_mode] => ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
[@@session.time_zone] => GMT

from MySQL I get

NULL

when I run the QUERY in Windows 10 with:

[VERSION()] => 5.7.33
[@@SESSION.sql_mode] => ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
[@@session.time_zone] => GMT

from MySQL I get

[CONVERT_TZ('2002-10-23T15:57:03Z', 'GMT', 'America/Bogota')] => 2002-10-23 10:57:03
WARNING (
    [Level] => Warning
    [Code] => 1292
    [Message] => Truncated incorrect datetime value: '2002-10-23T15:57:03Z'
)

if BOTH servers have SAME ambient, why the result is different?

in Windows I don't have my.ini this is the file my.ini in CentOs 7:

# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html

[mysqld]
performance-schema=0
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
innodb_buffer_pool_size=53477376
max_allowed_packet=268435456
open_files_limit=40000
innodb_file_per_table=1

default_storage_engine=MyIsam
default_tmp_storage_engine=MyIsam
character_set_server=utf8mb4
collation_server=utf8mb4_general_ci

Solution

  • MySQL is a bit lame when it comes to timezones.

    The trailing Z is not recognized, but I think you only get a warning.

    Do you have the timezone table loaded? (I don't know if that is a separate step on your installation. See https://dev.mysql.com/downloads/timezones.html )

    This works better, but requires knowing the adjustment factor:

    mysql> SELECT CONVERT_TZ('2002-10-23T15:57:03', 'SYSTEM', '-05:00');
    +-------------------------------------------------------+
    | CONVERT_TZ('2002-10-23T15:57:03', 'SYSTEM', '-05:00') |
    +-------------------------------------------------------+
    | 2002-10-23 17:57:03                                   |
    +-------------------------------------------------------+
    

    TIMESTAMP

    TIMESTAMP is nothing more than a number -- the number of seconds from the beginning of 1970. However, when storing/fetching, the timezone info based on some settings converts from the system time to/from UTC:

    mysql> SHOW VARIABLES LIKE '%zone%';
    +------------------+--------+
    | Variable_name    | Value  |
    +------------------+--------+
    | system_time_zone | PDT    |
    | time_zone        | SYSTEM |
    +------------------+--------+
    2 rows in set (0.01 sec)
    

    The SYSTEM is based on the OS setting.

    DATETIME

    DATETIME (and the date-only DATE) are essentially a picture of the clock on your wall. That is, there no information stored in it other than what you can see here:

    mysql> SELECT NOW();
    +---------------------+
    | NOW()               |
    +---------------------+
    | 2021-04-19 09:35:23 |
    +---------------------+
    1 row in set (0.00 sec)
    

    No timezone information is stored. Nor is any TZ info honored in a string:

    mysql> SELECT HOUR('2021-04-19 09:35:23 -07:00');
    +------------------------------------+
    | HOUR('2021-04-19 09:35:23 -07:00') |
    +------------------------------------+
    |                                  9 |
    +------------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> show warnings;
    +---------+------+--------------------------------------------------------------+
    | Level   | Code | Message                                                      |
    +---------+------+--------------------------------------------------------------+
    | Warning | 1292 | Truncated incorrect time value: '2021-04-19 09:35:23 -07:00' |
    +---------+------+--------------------------------------------------------------+
    1 row in set (0.00 sec)
    

    Sub-second Milliseconds example. (Up to 6 can be used)

    mysql> SELECT NOW(3), CURRENT_TIMESTAMP(3);
    +-------------------------+-------------------------+
    | NOW(3)                  | CURRENT_TIMESTAMP(3)    |
    +-------------------------+-------------------------+
    | 2021-04-19 09:49:55.292 | 2021-04-19 09:49:55.292 |
    +-------------------------+-------------------------+
    1 row in set (0.00 sec)
    

    Reference

    As of MySQL 8.0.19, you can specify a time zone offset when inserting TIMESTAMP and DATETIME values into a table. The offset is appended to the time part of a datetime literal, with no intravening spaces, and uses the same format used for setting the time_zone system variable, with the following exceptions:

    For hour values less than than 10, a leading zero is required.

    The value '-00:00' is rejected.

    Time zone names such as 'EET' and 'Asia/Shanghai' cannot be used; 'SYSTEM' also cannot be used in this context.

    The value inserted must not have a zero for the month part, the day part, or both parts. This is enforced beginning with MySQL 8.0.22, regardless of the server SQL mode setting.

    That came from https://dev.mysql.com/doc/refman/8.0/en/datetime.html , which may have more information of interest.

    That also shows 8.0.22 having:

    CAST(col AT TIME ZONE INTERVAL '+00:00' AS DATETIME)
    

    which might help you.