使用预选时区的 PHP 计划电子邮件警报

use*_*182 5 php timezone dst

我一直在搜索,但似乎找不到解决方案。

我有一个 PHP 网页,我可以在其中安排特定时间的电子邮件警报。我选择发送警报的日期和时间。这以 UNIX 格式存储在 MySQL 表中。我有一项每 15 分钟执行一次的工作,如果日期+时间是过去,则发送电子邮件 - 这一切都完美无缺,除非我需要为我的美国同事扩展它。我在爱尔兰,所以我需要管理整个美国的不同时区。我计划添加一个时区选择列表,用户一旦注册就必须选择这些时区……至少这是一个开始。管理时区很好,因为我认为我需要做的就是减去与服务器时间不同的时间,然后以 unix 格式保存日期时间。DST 是一个不同的问题 - 有没有人对如何克服这个问题有任何想法?

我读过使用 UTC 作为基准时间,但即使是这种情况,我也不会遇到同样的问题吗?

感谢一百万!

Wh1*_*Ck5 3

您的时间已经采用 UNIX 时间戳格式,因此您所需要做的就是计算用户的时间差(偏移量)。例如,爱尔兰位于UTC/UTC+1时区。因此,您所需要做的就是像james_t在他的评论中提到的那样进行数学计算。如果您需要来自爱尔兰的用户接收电子邮件,9:00pm UTC+1您必须将其发送到8:00pm UTC。那么什么是想法呢?

\n\n

允许用户选择时区,这意味着他们选择相对于 UTC 的偏移量。将其保存在数据库中的某个位置(您的用户表或其他表,无关紧要)。

\n\n

以秒为单位转换偏移量:

\n\n
$delta_time = -1 * $offset * 3600\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后计算你的触发时间:

\n\n
$trigger_time = time() + $delta_time;\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在,您的电子邮件发送器可以根据用户的时区设置在正确的时刻触发。

\n\n

例如:

\n\n
$offset = 1; // summer in Ireland\n$server_time = time(); // at the moment 1350509127\n$delta_time = -1 * $offset * 3600; // -3600\n$trigger_time = $server_time + $delta_time; // 1350505527\n
Run Code Online (Sandbox Code Playgroud)\n\n

您所需要的只是与数据库中的 UNIX 时间戳进行比较$trigger_time,然后决定发送(或不发送)电子邮件。

\n\n

Ofc,使用PHP 时区而不是纯粹的 +/- 偏移量并在 DST 更改应用于某些位置时保持更新并不是一个坏主意。

\n\n

做一些测试,这并不难。

\n\n

这只是一个一般想法,而不是完整的工作解决方案。

\n\n

更新:

\n\n

要计算任意两个时区之间的时差(以秒为单位),您可以使用如下方法:

\n\n

函数 delta_offset()

\n\n
  function delta_offset($server_timezone, $user_timezone) {\n    $dt = new DateTime(\'now\', new DateTimeZone($server_timezone));\n    $offset_server = $dt->getOffset();\n    $dt->setTimezone(new DateTimeZone($user_timezone));\n    $offset_user = $dt->getOffset();\n    return $offset_user - $offset_server;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

要获得以秒为单位的偏移量:

\n\n
  $server_tz = "Europe/London";\n  $user_tz = "America/New_York";\n  $offset = delta_offset($server_tz, $user_tz);  // offset in sec.\n
Run Code Online (Sandbox Code Playgroud)\n\n

创建一些输出:

\n\n
  $dt = new DateTime(\'now\', new DateTimeZone(\'UTC\'));\n  echo "<pre>UTC date/time: " . $dt->format(\'l, F jS, <b>H:i:s</b>\') . "\\n";\n  $dt = new DateTime(\'now\', new DateTimeZone($server_tz));\n  echo "London date/time: " . $dt->format(\'l, F jS, <b>H:i:s</b>\') . "\\n";\n  $dt = new DateTime(\'now\', new DateTimeZone($user_tz));\n  echo "New York date/time: " . $dt->format(\'l, F jS, <b>H:i:s</b>\') . "\\n\\n";\n  echo "Time difference between London (UK) and New York (USA) is: <b>$offset_h</b> ($offset s)</pre>";  \n
Run Code Online (Sandbox Code Playgroud)\n\n

浏览器中的输出(在撰写本文时):

\n\n
UTC date/time: Wednesday, October 17th, 22:32:27\nLondon date/time: Wednesday, October 17th, 23:32:27\nNew York date/time: Wednesday, October 17th, 18:32:27\n\nTime difference between London (UK) and New York (USA) is: -5:00 (-18000 s)\n
Run Code Online (Sandbox Code Playgroud)\n\n

在本例中,偏移量为 -5 小时(-18000 秒),但如果 DST 规则针对作为函数参数给出的任何时区发生更改,它会自动更改。

\n\n

Delta-offset提供了您必须提前或推迟多少时间向不同时区的用户发送电子邮件的信息,您现在所需要做的就是+/- delta-offset使用电子邮件发送者的调度程序进行简单操作。

\n\n

希望这可以帮助您找到解决问题的正确方法。

\n\n

更新 #2 - 示例(理论)

\n\n

想象一下这种情况。

\n\n

您当前的服务器时间是X爱尔兰7:00pm。我住在塞尔维亚,我们有相同的夏令时规则,但我\xe2\x80\x99m 一小时后(UTC+1/UTC+2)。你和我的时间差是+3600 seconds(1小时)。

\n\n

10:00pm现在您必须在(it\xe2\x80\x99s )中向我发送电子邮件9:00pm in Ireland

\n\n
    \n
  • 当前时间是X
  • \n
  • Delta-offset 是-1 * +3600 = -3600(delta-offset 乘以-1)。
  • \n
  • 您所在位置的发送时间为晚上 10:00 X + 10800(3 小时后)。
  • \n
  • 我所在地的发送时间是晚上10点X + 10800 + delta-offset = X + 7200(2小时后)。
  • \n
\n\n

检查实际时间是否等于或大于触发时间(发送时间)的公式为:

\n\n
current_timestamp >= trigger_timestamp + delta_offset\n
Run Code Online (Sandbox Code Playgroud)\n\n

其中函数的增量偏移量delta_offset()必须乘以才能-1在公式中使用。

\n\n

现在,您可以在需要时发送电子邮件,并确保将使用用户的本地时间(ofc,如果用户时区设置正确)发送电子邮件。

\n\n

注意:与此示例(塞尔维亚 - 爱尔兰 = +1 小时)的差异在 DST 更改期间有所不同,这意味着每年 1 小时我们处于同一时区 ( 0 delta-offset),并且我们有 1 小时+2 hours delta-offset。这是可能的,因为 DST 更改在塞尔维亚提前 1 小时应用,因此当我们的时间更改 +1 时,您必须等待 60 分钟才能将相同的更改应用到爱尔兰时间 *然后我们 +2),当我们带来相同的情况时将时钟拨回到正常时间(0 差异)。

\n