【问题标题】:How to get Unix timestamp in MySQL from UTC time?如何从 UTC 时间获取 MySQL 中的 Unix 时间戳?
【发布时间】:2012-11-11 00:45:43
【问题描述】:

如果我使用unix_timestamp(some_date),它会在内部将some_date 转换为UTC,而some_date 已经是UTC。有没有办法获取当前的 Unix 时间戳?

编辑:我需要 UTC 时间的 Unix 时间戳。

【问题讨论】:

    标签: mysql datetime


    【解决方案1】:

    您应该能够首先使用CONVERT_TZ 将其从UTC 转换为本地时区:

    UNIX_TIMESTAMP(CONVERT_TZ(some_date, '+00:00', @@global.time_zone))
    

    另见:10.6. MySQL Server Time Zone Support

    【讨论】:

      【解决方案2】:

      您可以从 UTC 日期时间值获取 MySQL 中的 UNIX 时间戳,如下所示:

      SELECT 
      UNIX_TIMESTAMP(CONVERT_TZ("some_date", '+00:00', @@session.time_zone)) 
      FROM `table_name`
      

      我在这里做了一个备忘单:Should MySQL have its timezone set to UTC?

      【讨论】:

        【解决方案3】:

        这对我来说很好用:

        UNIX_TIMESTAMP(CONVERT_TZ("some_date", '+00:00', 'SYSTEM'))
        

        【讨论】:

          【解决方案4】:

          还有其他几种方法:

          SELECT UNIX_TIMESTAMP(myDate)+UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(UTC_TIMESTAMP()) 
          FROM myTable
          

           

          SELECT UNIX_TIMESTAMP(myDate)-TIMESTAMPDIFF(SECOND, NOW(), UTC_TIMESTAMP()) 
          FROM myTable
          

          【讨论】:

            【解决方案5】:

            因为两个原因:

            1. MySQL 的内置函数UNIX_TIMESTAMPFROM_UNIXTIME 采用存储在@@global.time_zone 中的时区,我通常不希望/能够更改,并且
            2. DST 更改时的内置行为(如果全球时区使用 DST)在某些用例中会导致信息丢失,

            我首选的解决方案是编写我自己的函数来转换为 Unix 时间戳并返回:

            DELIMITER $$
            CREATE FUNCTION UnixTimestamp(utcstamp DATETIME) RETURNS BIGINT UNSIGNED DETERMINISTIC
            BEGIN
             DECLARE y INT UNSIGNED;
             SET y = YEAR(utcstamp);
             RETURN (y - 1970)          * 365 * 24 * 60 * 60 -- total seconds in full years since 1970
                  + FLOOR((y - 1969) / 4)     * 24 * 60 * 60 -- add to that total seconds in extra days for each leap year
                  - FLOOR((y - 1901) / 100)   * 24 * 60 * 60 -- subtract seconds for each day in a year that is divisible by 100 because those are not leap years
                  + FLOOR((y - 1601) / 400)   * 24 * 60 * 60 -- but add back each day in a leap year that is divisible by 400 because those are leap years
                  + (DAYOFYEAR(utcstamp) - 1) * 24 * 60 * 60 -- total seconds in full days since beginning of year
                  + HOUR(utcstamp)                 * 60 * 60 -- total seconds for each full hour passed since beginning of day
                  + MINUTE(utcstamp)                    * 60 -- total seconds for each full minute since last full hour
                  + SECOND(utcstamp);                        -- seconds since last full minute
            END$$
            DELIMITER ;
            
            DELIMITER $$
            CREATE FUNCTION FromUnixtime(utcstamp BIGINT UNSIGNED) RETURNS DATETIME DETERMINISTIC
            BEGIN
             DECLARE s INT UNSIGNED;
             DECLARE d INT UNSIGNED;
             DECLARE y INT UNSIGNED;
             IF utcstamp = 0 THEN RETURN '1970-01-01 00:00:00';
             END IF;
             SET s = utcstamp % (24 * 60 * 60);
             SET d = FLOOR(utcstamp / (24 * 60 * 60)) + 365 * 370 + 90;         -- days since 1600-01-01, last full leap year period
             SET y = 1600 + FLOOR(d / (400 * 365 + 97)) * 400;                  -- year is now 1600 + 400 * n, where n >= 0
             SET d = d - (400 * 365 + 97) * FLOOR(d / (400 * 365 + 97));        -- days since 1600 + 400 * n, less than 400 years
             IF d > 0 THEN
              SET y = y + FLOOR((d - 1) / (100 * 365 + 24)) * 100;              -- year is now 1600 + 400 * n + 100 * m, where 4 > m >= 0
              SET d = d - (100 * 365 + 24) * FLOOR((d - 1) / (100 * 365 + 24)); -- days since 1600 + 400 * n + 100 * m, less than 100 years
              SET y = y + FLOOR(d / (4 * 365 + 1)) * 4;                         -- year is now 1600 + 400 * n + 100 * m + 4 * l, where 25 > l >= 0
              SET d = d - (4 * 365 + 1) * FLOOR(d / (4 * 365 + 1));             -- days since 1600 + 400 * n + 100 * m + 4 * l, less than 4 years
              IF d > 0 THEN
               SET y = y + FLOOR(d / 365);                                      -- year is now 1600 + 400 * n + 100 * m + 4 * l + k, where 4 > k >= 0
               SET d = d - 365 * FLOOR(d / 365);                                -- days since 1600 + 400 * n + 100 * m + 4 * l + k, less than a year
               IF (y % 400 = 0 OR (y % 4 = 0 AND y % 100 <> 0)) THEN            -- if it's a leap year
                IF d > 0 THEN                                                   -- and if it's not day 0
                 SET d = d + 1;                                                 -- add a day we dropped in a previous step
                ELSEIF d = 0 THEN                                               -- otherwise if it's day 0
                 SET d = 365;                                                   -- then it's actually New Year's Eve
                 SET y = y - 1;                                                 -- on the year before
                END IF;
               END IF;
              ELSE SET d = d + 1;
              END IF;
             ELSE SET d = d + 1;
             END IF;
             RETURN CONCAT(MAKEDATE(y, d), ' ', LPAD(FLOOR(s / 3600), 2, 0), ':', LPAD(FLOOR((s - FLOOR(s / 3600) * 3600) / 60), 2, 0), ':', LPAD(s % 60, 2, 0));
            END$$
            DELIMITER ;
            

            你可以通过执行来检查这些函数:

            SELECT UTC_TIMESTAMP() AS CurrentTime, FromUnixtime(UnixTimestamp(UTC_TIMESTAMP())) AS Result;
            

            CurrentTimeResult 应该相同。

            【讨论】:

              猜你喜欢
              • 2013-03-20
              • 2017-10-07
              • 2014-11-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-07-20
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多