加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

php – 如何独立于时区获取所有相同的日期和时间

发布时间:2020-12-13 22:33:40 所属栏目:PHP教程 来源:网络整理
导读:我应该如何在PostgreSQL数据库中存储我的“日期时间”? 这就是我想要实现的目标: 如何在世界任何地方(例如)当地时间2012年1月1日00:00:00之前发生所有条目? 根据UTC时间显示按日期排序的所有条目. (2012年纽约新年前夜比伦敦新年更近). 我该如何存储我的
我应该如何在PostgreSQL数据库中存储我的“日期时间”?

这就是我想要实现的目标:

>如何在世界任何地方(例如)当地时间2012年1月1日00:00:00之前发生所有条目?
>根据UTC时间显示按日期排序的所有条目. (2012年纽约新年前夜比伦敦新年更近).

我该如何存储我的数据?我已经读过PostgreSQL内部存储所有时间(PostgreSQL documentation),所以我的用户时区实际上已经丢失了.

我想我应该使用一个类型为“timestamp without timezone”的列:

>第1点很容易.
>使用另一个类型为“String”的列,我将存储时区字符串(例如:America / New_York)
但是,第2点看起来仍然很难……

我希望我很清楚.

编辑新想法:我认为存储两个时间戳:一个没有时区(1. ok),一个带时区(2. ok)

解决方法

是的,PostgreSQL在内部将所有时间戳存储为UTC.对于具有时区的时间戳,时区偏移仅用于调整UTC的时间,但不会显式存储.

我不会存储时区字符串或更少的时区缩写(那些不精确).这可以在以后需要昂贵的计算,因为你必须考虑夏令时和国际时间制度的其他奇怪之处.

您可以将时区偏移量存储为间隔(占用12个字节)或数值秒数(占4个字节作为整数),就像我在此related answer中演示的那样.

或者,就像您已经提出的那样:除了UTC时间戳之外还存储本地时间戳(需要8个字节).这将使您的任务变得简单.考虑以下演示::

-- DROP TABLE tbl;
CREATE TEMP TABLE tbl (id int,ts_tz timestamp with time zone,ts timestamp);
INSERT INTO tbl VALUES
 (1,'2012-1-1 00:00+01','2012-1-1 00:00+01'),(2,'2012-1-1 00:00+02','2012-1-1 00:00+02'),(3,'2012-1-1 00:01+03','2012-1-1 00:01+03'),(4,'2012-1-1 00:02+04','2012-1-1 00:02+04');

查询问题1:

SELECT *
FROM   tbl
WHERE  ts = '2012-1-1 00:00'::timestamp;

 id |         ts_tz          |         ts
----+------------------------+---------------------
  1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00
  2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00

查询问题2:

SELECT *
FROM   tbl
ORDER  BY ts_tz;

 id |         ts_tz          |         ts
----+------------------------+---------------------
  4 | 2011-12-31 21:02:00+01 | 2012-01-01 00:02:00
  3 | 2011-12-31 22:01:00+01 | 2012-01-01 00:01:00
  2 | 2011-12-31 23:00:00+01 | 2012-01-01 00:00:00
  1 | 2012-01-01 00:00:00+01 | 2012-01-01 00:00:00

此解决方案的棘手部分可能是输入本地时间戳.只要在本地输入所有数据,这很容易.但是,如果你输入洛杉矶纽约的数据,就需要考虑.使用AT TIME ZONE construct:

SELECT ('2012-1-1 00:00+00' AT TIME ZONE 'America/New_York')::timestamp,('2012-1-1 00:00+00' AT TIME ZONE 'America/Los_Angeles')::timestamp

      timezone       |      timezone
---------------------+---------------------
 2011-12-31 19:00:00 | 2011-12-31 16:00:00

请注意我如何使用带时区的时间戳作为输入. AT TIME ZONE为带或不带时区的时间戳提供不同的结果.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读