当日期存储为unix时间戳时,如何统计美国东部时间3月9日19日出生的人数?

mpe*_*pen 5 mysql date

假设我的数据库中有人出现在-73440000unix时间.这意味着他出生于04 -Sep-1967 UTC,但是03 -Sep-1967 EDT.我如何计算在美国东部时间每年每天出生的人数?


马上,你会发现这一点

SELECT FROM_UNIXTIME(-73440000)
-- returns NULL
Run Code Online (Sandbox Code Playgroud)

退货NULL.MySQL无法处理负的unix时间戳.

好的,我们可以解决这个问题:

select date_add('1970-01-01', interval -73440000 second)
-- returns 1967-09-04 00:00:00
Run Code Online (Sandbox Code Playgroud)

收益率1967-09-04 00:00:00是他在UTC的生日.

我们可以尝试将其转换为EDT(多伦多时间):

select convert_tz('1967-09-04 00:00:00','UTC','America/Toronto')
-- returns 1967-09-04 00:00:00, but should be 1967-09-03 20:00:00
Run Code Online (Sandbox Code Playgroud)

但事实证明,CONVERT_TZ在1970年之前的日期也不起作用.

(我已经安装了时区,它确实可以在1970年到2038年之间的日期工作)

所以现在我被卡住了.我需要将unix时间戳转换为MySQL DATE,以便我可以GROUP BY它然后COUNT它.我能想到的唯一另一个选择是将数据库中的每条记录作为unix时间戳返回,并使用另一种语言进行转换并计算它们,但如果有数百万条记录,这可能会有点荒谬.

注意:您无法计算EDT和UTC之间的小时偏差,因为这可能会在一年中发生变化(夏令时).

mik*_*n32 3

您可以手动进行转换;如果您已经将区域数据加载到 MySQL 中,那么您已经获得了可追溯到 1918 年的数据。让我们看一下列表:

SET @timezone = "America/Toronto";
SELECT FROM_UNIXTIME(0) + INTERVAL Transition_Time SECOND AS change_time, Offset, Abbreviation
FROM mysql.time_zone_transition t
LEFT JOIN mysql.time_zone_transition_type tt ON (
    t.Time_zone_id = tt.Time_zone_id AND
    t.Transition_type_id = tt.Transition_type_id
)
LEFT JOIN mysql.time_zone_name n ON (
    t.Time_zone_id = n.Time_zone_id
)
WHERE n.Name = @timezone
    AND Transition_time < 0
ORDER BY change_time ASC;
Run Code Online (Sandbox Code Playgroud)

修改您的样本日期,我们可以提取以下内容:

SET @timezone = "America/Toronto";
SET @birthday = -73440000;

SELECT ('1970-01-01 00:00:00' + INTERVAL @birthday SECOND) + INTERVAL Offset SECOND AS offsetDate
FROM mysql.time_zone_transition t
LEFT JOIN mysql.time_zone_transition_type tt ON (
    t.Time_zone_id = tt.Time_zone_id AND
    t.Transition_type_id = tt.Transition_type_id
)
LEFT JOIN mysql.time_zone_name n ON (
    t.Time_zone_id = n.Time_zone_id
)
WHERE n.Name = @timezone
    AND Transition_time < @birthday
ORDER BY Transition_time DESC
LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

由于它选择该日期之前的最近的转换,因此它不会返回第一个转换之前的日期的记录。这应该表明您处于未知领域,并且必须弥补自己的偏移量。

如果您想使用第一个过渡时间作为后备,您可以Transition_time < @birthdayWHERE子句中删除并将其添加到ORDER BY子句中,正如您在评论中建议的那样。