当前位置: 首页 > 面试题库 >

PHP,MySQL和时区

夹谷鸿福
2023-03-14
问题内容

我正在尝试将时区系统集成到我的应用程序中,直到现在为止,我一直在努力避免制作时区感知的应用程序-
但是它是一项强制性要求,因此别无选择。TimeZones只是在我头上。我已经在PHP.net和其他站点(包括但不限于SO)上阅读了多个主题。但是我永远也无法掌握。

因此,我想知道是否有人可以在这里帮助我:(我想要做的是在我的应用程序中使用偏好选项,以允许用户从选择菜单中选择自己的时区,但是该应用程序也应该能够设置/为每个用户相应地选择DST。

请确保这将对仍在努力争取时区的其他人有所帮助,所以即使您认为我是一个完整的小飞象/傻瓜,也请提供尽可能详细的解释。

编辑赏金:

我为这个问题添加了赏金,因为我真的很需要编写PHP /
MySQL应用程序时需要一个有关时区的规范性问题(因此我还要添加MySQL标记)。我已经从很多地方找到了东西,但是最好将它们放在一起。查尔斯的回答很好,但我仍然觉得它缺少一些。这是我想到的一些事情:

  • 如何通过PHP DateTime对象将时间存储在数据库
  • 应该将它们存储在DATETIME还是TIMESTAMP?每个都有什么好处或警告?
  • 我们是否需要担心MySQL的时区DATE
  • 如何使用插入值NOW()。这些是否需要在插入之前或之后以某种方式进行转换?
  • 是否需要设置MySQL使用的时区?如果是这样,怎么办?应该持久执行还是在每个HTTP请求上执行?是否必须将其设置为UTC还是其他?还是服务器的时间足够?
  • 如何从MySQL检索值并将其转换为DateTime对象。直接DateTime::__construct()使用它是否足够?还是需要使用DateTime::createFromFormat()
  • 何时转换为当地时间以及为什么。在将它回显给用户 之前 ,是否有一段时间我们要对其进行转换(例如,与另一个DateTime对象或静态值进行比较)?
  • 我们是否有需要担心夏令时(DST)的时间?为什么或者为什么不?
  • 如果某人先前已插入数据(例如使用NOW()),而不必担心时区以确保一切保持一致,该怎么办?
  • 您想到别人应该注意的其他事情

如果可能,请尝试将其分成逻辑部分,以使将来的用户更容易找到信息。请确保在必要时提供代码示例。


问题答案:

此答案已更新,以适应赏金。原始的未编辑答案在该行下方。

赏金所有者添加的几乎所有问题都与在时区范围内MySQL和PHP日期时间应如何交互有关。

MySQL仍然具有 可怜的 时区支持,这意味着智能必须在PHP端提供。

  • 如上面的链接所述,将您的MySQL 连接时区 设置为UTC。这将导致MySQL处理的所有日期时间(包括NOW())被合理处理。
  • 始终使用DATETIMETIMESTAMP除非明确要求特殊行为,否则不要使用TIMESTAMP。这比以前减轻了痛苦。

    • 这是 确定 的Unix纪元时间存储为一个整数,如果你 到,如用于传统的目的。时代是UTC。
    • MySQL的首选日期时间格式是使用PHP日期格式字符串创建的 Y-m-d H:i:s
    • 所有 PHP日期时间存储在MySQL中时,将 所有 PHP日期时间转换为UTC,这很简单,如下所述
    • 从MySQL返回的日期时间可以安全地传递给PHP DateTime构造函数。请务必同时传递UTC时区!
    • 尽快 在echo上将 PHP DateTime转换为用户的本地时区。值得庆幸的是,DateTime与其他DateTime的比较和数学运算将考虑每个时区的时区。
    • 您仍然可以随PHP提供的DST数据库一时兴起。保持您的PHP和OS修补程序为最新!使MySQL保持UTC的幸福状态,以消除一种潜在的DST烦恼。

这解决了 大多数 问题。

最后一件事是笨拙的:

  • 如果某人先前已插入数据(例如使用NOW()),而不必担心时区以确保一切保持一致,该怎么办?

这真是个烦人。另一个答案指出了MySQL的答案CONVERT_TZ,尽管我个人通过在选择和更新过程中在服务器本地时区和UTC时区之间切换来做到这一点,因为我很顽固。

该应用程序还应该能够为每个用户自行设置/选择DST。

在现代,您不需要也不 应这样 做。

现代版本的PHP具有DateTimeZone类,该类具有列出命名的timezones的功能。命名时区允许用户选择其实际位置,并使系统根据该位置
自动 确定其DST规则。

您可以将DateTimeZone与DateTime结合使用,以获得一些简单但功能强大的功能。默认情况下,您可以简单地在UTC中存储和使用 所有
时间戳,并将它们转换为显示的用户时区。

// UTC default
    date_default_timezone_set('UTC');
// Note the lack of time zone specified with this timestamp.
    $nowish = new DateTime('2011-04-23 21:44:00');
    echo $nowish->format('Y-m-d H:i:s'); // 2011-04-23 21:44:00
// Let's pretend we're on the US west coast.  
// This will be PDT right now, UTC-7
    $la = new DateTimeZone('America/Los_Angeles');
// Update the DateTime's timezone...
    $nowish->setTimeZone($la);
// and show the result
    echo $nowish->format('Y-m-d H:i:s'); // 2011-04-23 14:44:00

通过使用此技术,系统将 自动 为用户选择正确的DST设置,而无需询问用户当前是否在DST中。

您可以使用类似的方法来呈现选择菜单。您可以连续地为单个DateTime对象重新分配时区。例如,此代码此刻将列出区域及其当前时间:

$dt = new DateTime('now', new DateTimeZone('UTC')); 
foreach(DateTimeZone::listIdentifiers() as $tz) {
    $dt->setTimeZone(new DateTimeZone($tz));
    echo $tz, ': ', $dt->format('Y-m-d H:i:s'), "\n";
}

通过使用一些客户端魔术,可以大大简化选择过程。Javascript有一个参差不齐但实用的
Date类,它具有一种标准方法,可以在分钟内获取UTC偏移量。在用户时钟正确的盲目假设下,您可以使用它来帮助缩小可能的时区列表。

让我们将这种方法与自己进行比较。除了推翻他们并不真正在乎的用户之外,您还需要在 每次 操作日期 时间时
实际执行一次日期数学运算。这不仅是次优的,而且是蝙蝠鸟粪的疯狂。强迫用户在需要DST支持时注明需要麻烦和困惑。

此外,如果您想为此使用现代的PHP
DateTime和DateTimeZone框架,则需要使用不建议使用的Etc/GMT...时区字符串而不是命名时区。这些区域名称可能会从将来的PHP版本中删除,因此这样做是不明智的。我说的都是经验。

tl; dr :使用现代工具集,免除日期数学的恐惧。向用户显示 命名 时区的列表。 将您的日期存储在UTC中
,这不会受到DST的任何影响。将datetimes转换为 display上 用户选择的命名时区,而不是更早。

根据要求,这是一个可用时区的循环,以分钟为单位显示其GMT偏移量。我在这里选择分钟来演示一个不幸的事实:并非所有的补偿都在整个小时内!实际上,有些人在夏令时期间提前了半个小时而不是整整一个小时。以分钟为单位的最终偏移量
与Javascript的偏移量匹配Date.getTimezoneOffset

$utc = new DateTimeZone('UTC');
$dt = new DateTime('now', $utc); 
foreach(DateTimeZone::listIdentifiers() as $tz) {
    $local = new DateTimeZone($tz);
    $dt->setTimeZone($local);
    $offset = $local->getOffset($dt); // Yeah, really.
    echo $tz, ': ', 
         $dt->format('Y-m-d H:i:s'),
         ', offset = ',
         ($offset / 60),
         " minutes\n";
}


 类似资料:
  • 问题内容: 我的服务器时间是格林尼治标准时间(GMT),每当有人在线时,我都会执行以下操作。 所以,我的问题是……每当有人执行某项操作时,它都会将日期/时间存储在用户本地时间中……这给我带来了很多麻烦。 我想要的是将所有内容存储在GMT中,但要让用户在其本地时区查看数据并与之交互。 编辑: 这是我更新用户状态的方法: 这是我将日期戳转换为秒的功能。 最后,我如何比较日期: 问题答案: 这里的技巧是

  • 问题内容: 我正在制作一个需要使用PHP 函数将日期存储在MySQL中的应用程序。 这些日期需要在MySQL中使用函数返回以小时为单位的时差进行比较,例如: 但是问题是– PHP date函数使用PHP时区设置,而该函数从MySQL服务器获取MySQL timezome。 我正在尝试解决此问题: 它仅适用于PHP。 它仅适用于PHP。 此返回为空。 这从MySQL的控制台抛出错误。 而且对于MyS

  • 问题内容: 平台: PHP和mySQL 出于实验目的,我在自己的网站上尝试了很少的XSS注入。考虑这种情况,我可以输入表单textarea。由于这是一个文本区域,因此我可以输入文本和各种(英文)字符。这是我的观察结果: 一个)。如果仅在将数据插入数据库之前才应用strip_tags和mysql_real_escape_string并且不对输入使用htmlentities, 则查询将中断 ,由于异常

  • 问题内容: 我有一个MySQL查询 我想分页显示每页10条结果。我该怎么做? 问题答案: 这是一个不错的起点:

  • 本文向大家介绍php mysql localhost,127.0.0.1和ip区别,包括了php mysql localhost,127.0.0.1和ip区别的使用技巧和注意事项,需要的朋友参考一下 一家之言: localhost与127.0.0.1的区别 localhost与127.0.0.1的区别是什么?相信有人会说是本地ip,曾有人说,用127.0.0.1比localhost好,可以减少一次

  • 问题内容: 我正在写一个基本上使用php和mysql查找经纬度25英里半径范围内的地方的地方,并长期使用它。 我想知道这样的事情如何工作? 我会通过一条经纬度较长的经纬度,并让其只提取经纬度25英里以内且距我的位置数据库较长的纬度。 做这个的最好方式是什么? 编辑:我发现此代码用于计算2点之间的距离。 这是在MYSQL中进行此计算的一种方法,因此我只能在Miles = <25时返回吗? 问题答案: