19

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

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

4

5 回答 5

29

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

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

另见:10.6。MySQL 服务器时区支持

于 2012-11-22T15:33:11.250 回答
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
于 2016-05-09T19:26:54.283 回答
3

这对我来说很好:

UNIX_TIMESTAMP(CONVERT_TZ("some_date", '+00:00', 'SYSTEM'))
于 2014-12-05T17:36:42.770 回答
1

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

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

我在这里做了一个备忘单:MySQL 是否应该将其时区设置为 UTC?

于 2013-09-28T16:50:38.120 回答
0

因为两个原因:

  1. MySQL 的内置函数UNIX_TIMESTAMP并采用我通常不希望/能够更改FROM_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;

CurrentTime并且Result应该是一样的。

于 2021-10-21T18:55:50.027 回答