5

我一直在寻找很多,我似乎无法找到解决方案。

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

我已经读过使用 UTC 作为基准时间,但即使是这样,我仍然会遇到同样的问题吗?

谢谢一米!

4

1 回答 1

3

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

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

以秒为单位转换偏移量:

$delta_time = -1 * $offset * 3600

然后计算你的触发时间:

$trigger_time = time() + $delta_time;

现在您有时间让您的电子邮件发件人根据用户的时区设置在正确的时刻触发。

例如:

$offset = 1; // summer in Ireland
$server_time = time(); // at the moment 1350509127
$delta_time = -1 * $offset * 3600; // -3600
$trigger_time = $server_time + $delta_time; // 1350505527

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

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

做一些测试,这并不难。

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

更新:

要计算任何两个时区之间的时间差(以秒为单位),您可以使用以下内容:

函数 delta_offset()

  function delta_offset($server_timezone, $user_timezone) {
    $dt = new DateTime('now', new DateTimeZone($server_timezone));
    $offset_server = $dt->getOffset();
    $dt->setTimezone(new DateTimeZone($user_timezone));
    $offset_user = $dt->getOffset();
    return $offset_user - $offset_server;
    }

要在几秒钟内获得偏移量:

  $server_tz = "Europe/London";
  $user_tz = "America/New_York";
  $offset = delta_offset($server_tz, $user_tz);  // offset in sec.

创建一些输出:

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

浏览器中的输出(在写这篇文章的时候):

UTC date/time: Wednesday, October 17th, 22:32:27
London date/time: Wednesday, October 17th, 23:32:27
New York date/time: Wednesday, October 17th, 18:32:27

Time difference between London (UK) and New York (USA) is: -5:00 (-18000 s)

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

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

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

更新 #2 - 示例(理论)

想象一下这种情况。

您当前的服务器时间是X并且它7:00pm目前在爱尔兰。我住在塞尔维亚,我们有相同的 DST 规则,但我比 (UTC+1/UTC+2) 晚一小时。你和我的时间差是+3600 seconds(1 小时)。

10:00pm现在您必须在(it's 9:00pm in Ireland)中向我发送电子邮件。

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

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

current_timestamp >= trigger_timestamp + delta_offset

其中函数的 delta-offsetdelta_offset()必须乘以-1在公式中使用。

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

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

于 2012-10-17T21:36:58.363 回答