PHP - strtotime,指定时区

时间:2010-08-25 18:21:03

标签: php date timezone

我有一个日期字符串,比如'2008-09-11'。我想从中获取时间戳,但我需要动态指定时区(而不是PHP默认值)。

所以回顾一下,我有两个字符串:

$dateStr = '2008-09-11';
$timezone = 'Americas/New_York';

如何获取此时间戳?

编辑:当天的时间将是当天的午夜.... $ dateStr ='2008-09-11 00:00:00';

6 个答案:

答案 0 :(得分:69)

$date = new DateTime($dateStr, new DateTimeZone($timezone));

$timestamp = $date->format('U');

答案 1 :(得分:23)

如果你正在运行PHP>那么接受的答案是很好的。 5.2(我认为这是他们添加DateTime类的版本)。如果你想支持旧版本,你不想输入那么多,或者如果你只是喜欢功能方法,还有另一种方法也不能修改全局设置:

$dateStr = '2008-09-11 00:00:00';
$timezone = 'America/New_York';
$dtUtcDate = strtotime($dateStr. ' '. $timezone);

答案 2 :(得分:16)

如果由于某种原因你使用< 5.2(天堂禁止),这将有效。

$reset = date_default_timezone_get();
date_default_timezone_set('America/New_York');
$stamp = strtotime($dateStr);
date_default_timezone_set($reset);

但是5.2及以上,我强烈建议你选择@ salathe的答案。

答案 3 :(得分:4)

如果您要使用时区,我建议您使用DateTime类,在这种情况下,DateTime :: createFromFormat()函数将允许您做这样的semothing:

$start = "2015-01-14 11:59:43";
$timezone = "America/Montreal";

$tz = new DateTimeZone($timezone);
$dt = DateTime::createFromFormat('Y-m-d H:i:s', $start, $tz);

当你将$ tz放在DateTime :: createFromFormat函数中时,你告诉它你所提供的日期是什么时区,这样当你需要将它转换为另一个时区时,所有你需要做的就是这样:

$start = $dt->setTimeZone(new DateTimeZone('UTC'));

答案 4 :(得分:2)

每当您提及确切的时刻时,请根据不受夏令时影响的统一标准保持时间。 (GMT和UTC在这方面是相同的,但最好使用术语UTC。请注意,UTC也称为Zulu或Z时间。)

如果您选择使用本地时间值保留时间,请包括UTC的本地时间偏移量,以便稍后可以明确地解释时间戳。

在某些情况下,您可能需要同时存储UTC时间和等效的本地时间。通常这是通过两个单独的字段完成的,但是某些平台支持datetimeoffset类型,它可以存储在单个字段中。

将时间戳存储为数值时,请使用Unix时间 - 这是自1970-01-01T00:00:00Z(不包括闰秒)以来的整秒数。如果需要更高的精度,请使用毫秒。此值应始终基于UTC,不进行任何时区调整。

如果以后可能需要修改时间戳,请包含原始时区ID,以便确定偏移量是否与记录的原始值有所不同。

在安排未来事件时,通常优先选择本地时间而不是UTC,因为更改偏移是很常见的。见答案和博文。

请记住,时区偏移量并不总是整数小时数(例如,印度标准时间为UTC + 05:30,而尼泊尔使用UTC + 05:45)。

如果使用Java,请使用java.time for Java 8,或使用Joda Time for Java 7或更低版​​本。 如果使用.NET,请考虑使用Noda Time。 如果使用没有Noda Time的.NET,请考虑DateTimeOffset通常是比DateTime更好的选择。 如果使用Perl,请使用DateTime。 如果使用Python,请使用pytz或dateutil。 如果使用JavaScript,请将moment.js与moment-timezone扩展名一起使用。 如果使用PHP> 5.2,使用DateTime和DateTimeZone类提供的本机时区转换。使用时要小心。

DateTimeZone :: listAbbreviations() - 请参阅答案。为了使PHP保持最新的Olson数据,请定期安装timezonedb PECL包;见答案。

如果使用C ++,请务必使用正确实施IANA时区数据库的库。这些包括cctz,ICU和Howard Hinnant的“tz”库。

不要将Boost用于时区转换。虽然其API声称支持标准IANA(又名“zoneinfo”)标识符,但它粗略地将它们映射到固定偏移量,而不考虑每个区域可能具有的丰富变更历史。

(此外,该文件已停止维护。)

大多数商业规则使用民用时间,而不是UTC或GMT。因此,计划在应用应用程序逻辑之前将UTC时间戳转换为本地时区。

请记住,时区和偏移不是固定的,可能会发生变化。例如,历史上美国和英国使用相同的日期来“前进”和“后退”。

然而,在2007年,美国改变了时钟变换的日期。这意味着一年中的48周,伦敦时间和纽约时间之间的差异是5小时和4周(春季3个,秋季1个),这是4个小时。在涉及多个区域的任何计算中都要注意这样的项目。

考虑时间类型(实际事件时间,广播时间,相对时间,历史时间,重复时间)您需要存储哪些元素(时间戳,时区偏移和时区名称)以便正确检索 - 请参阅“时间“回答。

让您的操作系统,数据库和应用程序tzdata文件在他们自己和世界其他地方保持同步。

在服务器上,将硬件时钟和OS时钟设置为UTC而不是本地时区。

无论前一个要点如何,服务器端代码(包括网站)都不应该期望服务器的本地时区特别适合。见答案。

在所有服务器上使用NTP服务。

如果使用FAT32,请记住时间戳存储在本地时间,而不是UTC。

在处理定期事件(例如每周电视节目)时,请记住时间随着夏令时的变化而变化,并且在不同时区会有所不同。

始终将日期时间值视为下限包含,上限独占(> =,<)。

答案 5 :(得分:0)

简明答案(无需更改默认时区)

$dateStr = '2008-09-11';
$timezone = 'America/New_York';
$time = strtotime(
    $dateStr, 
    // convert timezone to offset seconds
    (new \DateTimeZone($timezone))->getOffset(new \DateTime) - (new \DateTimeZone(date_default_timezone_get()))->getOffset(new \DateTime) . ' seconds'
);

仁慈的答案

使用strtotime的第二个选项来更改函数的参考框架。顺便说一下,我不想更新脚本的默认时区:

  

http://php.net/manual/en/function.strtotime.php

     

int strtotime(字符串$ time [,int $ now = time()])

     

功能   期望得到一个包含英文日期格式的字符串,并且   将尝试将该格式解析为Unix时间戳(   自1970年1月1日UTC以来的秒数),相对于时间戳记   现在提供,如果没有提供,则提供当前时间。

还有一个助手

/**
 * Returns the timestamp of the provided time string using a specific timezone as the reference
 * 
 * @param string $str
 * @param string $timezone
 * @return int number of the seconds
 */
function strtotimetz($str, $timezone)
{
    return strtotime(
        $str, strtotime(
            // convert timezone to offset seconds
            (new \DateTimeZone($timezone))->getOffset(new \DateTime) - (new \DateTimeZone(date_default_timezone_get()))->getOffset(new \DateTime) . ' seconds'
        )
    );
}

var_export(
    date(
        'Y-m-d', 
        strtotimetz('this monday', 'America/New_York')
    )
);

也许不是最高效的方法,但是当您知道默认时区和偏移量时,效果很好。例如,如果默认时区为UTC,而偏移量为-8小时:

var_dump(
    date(
        'Y-m-d', 
        strtotime('this tuesday', strtotime(-8 . ' hours'))
    )
);