繁体   English   中英

PHP - strtotime,指定时区

[英]PHP - strtotime, specify timezone

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

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

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

我如何获得时间戳?

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

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

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

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

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

如果由于某种原因您使用 <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 的答案。

如果您打算使用时区,我建议您使用 DateTime 类,在这种情况下,DateTime::createFromFormat() 函数将允许您执行以下操作:

$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'));

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

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

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

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

如果您以后可能需要修改时间戳,请包含原始时区 ID,以便您可以确定偏移量是否与记录的原始值相比发生了变化。

在安排未来的事件时,通常首选本地时间而不是 UTC,因为偏移量更改是很常见的。 请参阅答案和博客文章。

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

如果使用 Java,请为 Java 8 使用 java.time,或为 Java 7 或更低版本使用 Joda Time。 如果使用 .NET,请考虑使用 Noda Time。 如果在没有 Noda Time 的情况下使用 .NET,请考虑 DateTimeOffset 通常比 DateTime 更好的选择。 如果使用 Perl,请使用 DateTime。 如果使用 Python,请使用 pytz 或 dateutil。 如果使用 JavaScript,请使用带有 moment-timezone 扩展名的 moment.js。 如果使用 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 文件在它们与世界其他地方之间保持同步。

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

不管前面的要点是什么,服务器端代码,包括网站,永远不应该期望服务器的本地时区是特别的。 见答案。

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

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

在处理重复事件(例如每周电视节目)时,请记住时间会随 DST 发生变化,并且会因时区而异。

始终将日期时间值查询为下限包含,上限不包含 (>=, <)。

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

$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 ( string $time [, int $now = time() ] )

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

还有帮手

/**
 * 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'))
    )
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM