1. 程式人生 > >MySql 時間類型 & JDBC時間類型

MySql 時間類型 & JDBC時間類型

adb 結果 () 方法 lec rim pin table 種類型

MySql時間類型:DATETIME & TIMESTAMP

  • 長度

    • DATETIME類型包含DATE和TIME,範圍1000-01-01 00:00:00 ~ 9999-12-31 23:59:59。DATETIME還能包含毫秒,例如2018-03-11 14::13:22.999
    • TIMESTAMP也能存儲日期和時間,但是範圍只有1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC
  • 時區

    • DATETIME存儲的時間不包含時區

    • TIMESTAMP存儲的UTC時間

      例如:

      1. create table

        CREATE TABLE timestamp_n_datetime (
        id INT AUTO_INCREMENT PRIMARY KEY,
        ts TIMESTAMP,
        dt DATETIME
        );
      2. insert now(當前時區為+08)

        insert into timestamp_n_datetime(ts,dt) values (now(), now());
      3. select

        MariaDB [test]> select * from timestamp_n_datetime;
        +----+---------------------+---------------------+
        | id | ts                  | dt                  |
        +----+---------------------+---------------------+
        |  1 | 2018-03-11 14:35:01 | 2018-03-11 14:35:01 |
        +----+---------------------+---------------------+
        1 row in set (0.00 sec)
      4. 修改時區

        MariaDB [test]> set time_zone = ‘+00:00‘;
        Query OK, 0 rows affected (0.02 sec)
      5. 再次查詢

        MariaDB [test]> select * from timestamp_n_datetime
        -> ;
        +----+---------------------+---------------------+
        | id | ts                  | dt                  |
        +----+---------------------+---------------------+
        |  1 | 2018-03-11 06:35:01 | 2018-03-11 14:35:01 |
        +----+---------------------+---------------------+
        1 row in set (0.00 sec)

        TIMESTAMP存儲的時間調整到了新時區,而DATETIME存儲的時間不變。剛接觸java的時候寫代碼的就出現過時區問題,mybatis mysql,表字段類型為DATETIME,java類型為java.util.Date。通過查看java connector源碼com.mysql.cj.mysqla.MysqlaSession.java的configureTimezone方法,

        this.getServerVariable("system_time_zone")

        調試這裏發現從系統裏面讀出來的時區設置是CST。於是去查找數據庫服務器的原因

        MariaDB [(none)]> show variables like ‘%time_zone%‘;
        +------------------+--------+
        | Variable_name    | Value  |
        +------------------+--------+
        | system_time_zone | CST    |
        | time_zone        | SYSTEM |
        +------------------+--------+
        2 rows in set (0.01 sec)

        解決方法:

        • 修改配置文件 /etc/my.cnf.d/server.cnf (centos 7),需要重啟mysql

          # this is only for the mysqld standalone daemon
          [mysqld]
          default-time-zone=‘+08:00‘ # 將這行加到mysqld節點下
        • 修改數據庫服務變量(未驗證,如果不方便修改配置文件或重啟數據庫。重啟數據庫之後失效??)

          set time_zone=‘+08:00‘;
          set global time_zone=‘+08:00‘;
          flush privileges;

        如果是直接使用jdbc而不是mybatis,則通過

        java.util.Date now = new java.util.Date();
        java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp(now.getTime());
        PreparedStatement.setTimestamp(1, sqlTimestamp, Calendar.getInstance(Locale.CHINA)); 

        即指定第三個參數。如果沒有指定第三個參數,則又使用了CST時間(setTimestamp源碼中)

JDBC表示時間的類型

這一節的資料有點老(https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/guide/jdbc/getstart/mapping.doc.html)

這三種類型都繼承自java.util.Date,因為java.util.Date沒法匹配三種JDBC時間類型。

  • DATE表示只包含了年月日的時間類型 java.sql.Date for SQL DATE(這裏的SQL說的是SQL-92標準)。 父類的hour, minute, second, millisecond字段被設置為0。

  • TIME表示只包含了時分秒的時間類型 java.sql.Time for SQL TIME information. 父類的year, month, day字段被設置為1970, 1月, 1號. 這個時間是java裏面的“零紀元”

  • TIMESTAMP包含了DATE+TIME再加上一個納秒(nanosecond)字段 java.sql.Timestamp for SQL TIMESTAMP information. 這個類型為java.util.Date擴展了額外的nanosecond字段。

其他命令

get current time_zone
SELECT @@global.time_zone, @@session.time_zone;
如果查詢結果是SYSTEM,表示mysql服務器使用了系統時區 date -R命令能查看系統時區。

MySql 時間類型 & JDBC時間類型