【问题标题】:php mysql UTC timestampphp mysql UTC时间戳
【发布时间】:2016-12-27 15:26:19
【问题描述】:

我正处于构建 mysql 表的早期阶段,该表将保存来自两个时区的数据。我的机器和服务器都在 America/Los_Angeles 时区。时区表没有加载到 mysql 服务器中,但是在这个站点的其他地方,我已经读过这不是必需的,只要 php 处理查询 - php 会将 UTC 偏移量写入 mysql。 Mysql 数据类型是 TIMESTAMP。已使用包含以下语句的 php 脚本插入示例数据:

        if($company == 'HOS_CIN' or $company == 'HOS_FER') {
        date_default_timezone_set("America/New_York");
    }

然后使用两个 php 脚本在浏览器中显示数据。一份包括上述陈述,一份没有。带有语句的显示时间为美国东部标准时间中午,而没有声明的显示时间为太平洋标准时间中午。如果mysql存储了UTC偏移量,显示的时间不应该有三个小时的差异吗?

php版本5.3.3,mysql版本5.0.95

【问题讨论】:

  • 1) 不,如果你不告诉 PHP 将不会打印 UTC 时区(例如,将时区设置为 UTC)2) TIMESTAMP 从/到 MySQL 服务器的时区转换在存储/检索日期时,您似乎并不关心设置一个已知日期。
  • 这不就是date_default_timezone_set的目的吗?
  • 不确定您现在的意思,如果您选择America/New_York,它将使用纽约时间,而不是UTC。 MySQL 是一个不同的程序,有时甚至可以在不同的计算机上运行。它不会关心 PHP 时区。
  • 本网站和其他网站的其他地方,建议不一致。一些建议将时间戳存储为整数,而另一些建议当数据类型设置为时间戳时,mysql 会将在 php 脚本中启动的日期和时间数据转换并存储为 UTC。我在 php 中选择命名时区的原因是为了预测由可恶的夏令时引起的冲突。提到的查询是从 php 中的 mysqli_query 语句发出的。
  • 我并不是说你的方法是好是坏,只是你没有考虑所有信息(例如 Mysql 时区)并且你做出断言(例如“php 将编写UTC 偏移到 mysql") 不受代码支持。

标签: php mysql datetime


【解决方案1】:

关于 PHP 和 MySQL,您必须面对以下限制:

  • MySQL 没有任何列类型允许存储带有时区信息的本地时间。

  • PHP 无法将复杂的数据类型(例如 DateTime 实例)传递给 MySQL,所有内容都需要字符串化,并且 MySQL 没有传递带有时区信息的日期文字的语法。

实际上它并没有看起来那么糟糕,因为您通常不需要插入信息的用户的本地时间:您只需要知道存储日期所指的确切时间和 (可选)必须显示存储日期的时区。基本上有三种明智的方法可以做到这一点:

  1. 使用不受时区影响的格式,例如一个 Unix 时间戳,存储为 INT

  2. 使用具有明确时区信息的日期列类型,例如TIMESTAMP 列(不要与 Unix 时间戳混淆),其中时区始终为 UTC。

  3. 使用带有隐式时区信息的日期列类型,例如DATEDATETIME 列,您已确定所有日期都属于给定时区,可能是 UTC。

#2 和 #3 之间的区别在于 MySQL 是知道时区还是只有你和你的代码知道。

无论您选择哪种方法,都必须向所有预期进行时区转换的程序指示要使用的时区:

  • PHP 需要时区来生成/显示 Unix 时间戳,并转换/转换为用户输入/预期的本地时间和 MySQL 预期/打印的本地时间,例如:

    $user_date = new DateTime('2016-10-03 00:00:00', new DateTimeZone('Europe/Berlin'));
    $user_date->setTimezone(new DateTimeZone('UTC'));
    echo $user_date->format('c');
    
  • 当您使用TIMESTAMP 列时,MySQL 需要时区来转换本地时间,例如:

    mysql> create table foo(
        -> foo int(10) unsigned auto_increment,
        -> my_date timestamp,
        -> primary key (foo)
        -> );
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> set @@time_zone = '+01:00';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into foo (my_date) values ('2016-12-27 18:50:00');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> set @@time_zone = '-07:00';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> insert into foo (my_date) values ('2016-12-27 18:50:00');
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from foo order by 1;
    +-----+---------------------+
    | foo | my_date             |
    +-----+---------------------+
    |   1 | 2016-12-27 10:50:00 |
    |   2 | 2016-12-27 18:50:00 |
    +-----+---------------------+
    2 rows in set (0.00 sec)
    
    mysql> set @@time_zone = '+09:30';
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> select * from foo order by 1;
    +-----+---------------------+
    | foo | my_date             |
    +-----+---------------------+
    |   1 | 2016-12-28 03:20:00 |
    |   2 | 2016-12-28 11:20:00 |
    +-----+---------------------+
    2 rows in set (0.00 sec)
    

【讨论】:

    猜你喜欢
    • 2012-07-24
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多