1

我有一个表,其中每一行都有一个时间戳。时间戳是一个unix时间戳。我想使用这些数据做一些报告,这需要我按特定时间段对这些数据进行分组(现在,我们只说天:所以 86400 秒)。这可以通过设置时间戳来实现,即:

mysql> set time_zone='+00:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select NOW(), FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP()/86400)*86400);
+---------------------+----------------------------------------------------+
| NOW()               | FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP()/86400)*86400) |
+---------------------+----------------------------------------------------+
| 2013-01-17 06:06:37 | 2013-01-17 00:00:00                                |
+---------------------+----------------------------------------------------+
1 row in set (0.01 sec)

这使我可以进行以下数据汇总:

select FROM_UNIXTIME(FLOOR(timestamp/86400)*86400) groupts, count(some_id) from table group by groupts order by groupts;

所有这一切都完美无缺,现在我想将数据与其他报告进行比较,其中我只有特定时区的数据,比如说它的 EST。

不幸的是(很明显),地板不再起作用了:

mysql> set time_zone='-05:00';
Query OK, 0 rows affected (0.00 sec)

mysql> select NOW(), FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP()/86400)*86400);
+---------------------+----------------------------------------------------+
| NOW()               | FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP()/86400)*86400) |
+---------------------+----------------------------------------------------+
| 2013-01-17 01:10:38 | 2013-01-16 19:00:00                                |
+---------------------+----------------------------------------------------+
1 row in set (0.00 sec)

这最终让我想到了我的问题:有没有办法根据特定时区来确定时间戳?即,地板将确保该时区 00:00-23:59 的所有值最终都在特定组中?

谢谢!

4

1 回答 1

1

您需要将时区偏移从 UTC 转换为秒;然后,您需要在除法和乘法之前从 Unix 时间戳中添加或减去该偏移量,然后再将其加回。

例如:

我们可以在时区 UTC-05:00(美国/东部,或美国/纽约)中建立日期 2012-01-17 的 UTC 值范围:

$ timestamp -Z -z -05:00 1358398800 1358485200
1358398800 = Thu Jan 17 00:00:00 2013 -05:00
1358485200 = Fri Jan 18 00:00:00 2013 -05:00
$ timestamp -Z -z 00:00 1358398800 1358485200
1358398800 = Thu Jan 17 05:00:00 2013 +00:00
1358485200 = Fri Jan 18 05:00:00 2013 +00:00
$

时区偏移距 UTC (5 * 3,600) 为 -18,000 秒,当然,一天有 86,400 秒。

然后我们可以证明bc计算应该是:

  • ((utc_time + tz_offset) / secs_per_day) * secs_per_day - tz_offset

例如,我们可以使用bc来进行计算:

$ bc
scale=0
a=1358398800
b=a+86400
c=-18000
d=86400
((a+c)/d)*d-c
1358398800
((b-1+c)/d)*d-c
1358398800
((b+c)/d)*d-c
1358485200
b
1358485200
quit
$

如您所见,美国/东部时区 2012-01-17 期间的时间都归入同一组(使用极端时间值演示)。

因此,只要您可以以秒为单位计算时区与 UTC 的偏移量,格林威治子午线以西的时区为负值,其以东的时区为正值,那么您就可以使用显示的计算。

SELECT NOW(), FROM_UNIXTIME(FLOOR((UNIX_TIMESTAMP() + (-18000))/86400)*86400 - (-18000));

概括:

FLOOR((timestamp + (offset_in_seconds))/86400)*86400 - (offset_in_seconds)

其中 offset_in_seconds 可以是正数或负数。

于 2013-01-17T06:50:23.913 回答