PHP - strtotime,指定时区
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3569014/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP - strtotime, specify timezone
提问by Andy Hin
I have a date string, say '2008-09-11
'. I want to get a timestamp out of this, but I need to specify a timezone dynamically (rather then PHP default).
我有一个日期字符串,比如' 2008-09-11
'。我想从中获得一个时间戳,但我需要动态指定一个时区(而不是 PHP 默认)。
So to recap, I have two strings:
所以回顾一下,我有两个字符串:
$dateStr = '2008-09-11';
$timezone = 'Americas/New_York';
How do I get the timestamp for this?
我如何获得时间戳?
EDIT: The time of day will be the midnight of that day.... $dateStr = '2008-09-11 00:00:00';
编辑:一天中的时间将是那天的午夜.... $dateStr = '2008-09-11 00:00:00';
回答by salathe
$date = new DateTime($dateStr, new DateTimeZone($timezone));
$timestamp = $date->format('U');
$timestamp = $date->format('U');
回答by krowe
The accepted answer is great if you're running PHP > 5.2 (I think that's the version they added the DateTime class). If you want to support an older version, you don't want to type as much, or if you just prefer the functional approach there is another way which also does not modify global settings:
如果您运行的是 PHP > 5.2(我认为这是他们添加了 DateTime 类的版本),那么接受的答案是很好的。如果你想支持旧版本,你不想输入那么多,或者如果你只是喜欢函数式方法,还有另一种方法也不会修改全局设置:
$dateStr = '2008-09-11 00:00:00';
$timezone = 'America/New_York';
$dtUtcDate = strtotime($dateStr. ' '. $timezone);
回答by Jonah
This will work if for some reason you're using <5.2 (Heaven forbid).
如果由于某种原因您使用 <5.2(天堂禁止),这将起作用。
$reset = date_default_timezone_get();
date_default_timezone_set('America/New_York');
$stamp = strtotime($dateStr);
date_default_timezone_set($reset);
But anything 5.2 and above, I'd strongly recommend you opt for @salathe's answer.
但是对于 5.2 及更高版本,我强烈建议您选择 @salathe 的答案。
回答by Philippe Gilbert
If you're going to use Timezones, I propose you use the DateTime class, and in this case the DateTime::createFromFormat() function which will allow you to do semothing like this:
如果您要使用时区,我建议您使用 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);
When you put $tz in the DateTime::createFromFormat function, you tell it what time zone the date you gave is in, so that when you need to convert it to another timezone, all you have to do is something like this:
当您将 $tz 放入 DateTime::createFromFormat 函数时,您会告诉它您提供的日期所在的时区,以便当您需要将其转换为另一个时区时,您所要做的就是这样:
$start = $dt->setTimeZone(new DateTimeZone('UTC'));
回答by Charu
Whenever you are referring to an exact moment in time, persist the time according to a unified standard that is not affected by daylight savings. (GMT and UTC are equivalent with this regard, but it is preferred to use the term UTC. Notice that UTC is also known as Zulu or Z time.)
每当您指的是某个确切时刻时,请根据不受夏令时影响的统一标准来保留时间。(在这方面,GMT 和 UTC 是等效的,但最好使用术语 UTC。请注意,UTC 也称为 Zulu 或 Z 时间。)
If instead you choose to persist a time using a local time value, include the local time offset from UTC, such that the timestamp can later be interpreted unambiguously.
相反,如果您选择使用本地时间值保留时间,请包含与 UTC 的本地时间偏移量,以便稍后可以明确解释时间戳。
In some cases, you may need to store both the UTC time and the equivalent local time. Often this is done with two separate fields, but some platforms support a datetimeoffset type that can store both in a single field.
在某些情况下,您可能需要同时存储 UTC 时间和等效的本地时间。通常这是通过两个单独的字段完成的,但一些平台支持日期时间偏移类型,可以将两者存储在单个字段中。
When storing timestamps as a numeric value, use Unix time - which is the number of whole seconds since 1970-01-01T00:00:00Z (excluding leap seconds). If you require higher precision, use milliseconds instead. This value should always be based on UTC, without any time zone adjustment.
将时间戳存储为数值时,请使用 Unix 时间 - 这是自 1970-01-01T00:00:00Z 以来的整秒数(不包括闰秒)。如果您需要更高的精度,请改用毫秒。此值应始终基于 UTC,无需任何时区调整。
If you might later need to modify the timestamp, include the original time zone ID so you can determine if the offset may have changed from the original value recorded.
如果您以后可能需要修改时间戳,请包含原始时区 ID,以便您可以确定偏移量是否与记录的原始值相比发生了变化。
When scheduling future events, usually local time is preferred instead of UTC, as it is common for the offset to change. See answer, and blog post.
在安排未来的事件时,通常首选本地时间而不是 UTC,因为偏移量更改是很常见的。请参阅答案和博客文章。
Remember that time zone offsets are not always an integer number of hours (for example, Indian Standard Time is UTC+05:30, and Nepal uses UTC+05:45).
请记住,时区偏移量并不总是整数小时(例如,印度标准时间是 UTC+05:30,而尼泊尔使用 UTC+05:45)。
If using Java, use java.time for Java 8, or use Joda Time for Java 7 or lower. If using .NET, consider using Noda Time. If using .NET without Noda Time, consider that DateTimeOffset is often a better choice than DateTime. If using Perl, use DateTime. If using Python, use pytz or dateutil. If using JavaScript, use moment.js with the moment-timezone extension. If using PHP > 5.2, use the native time zones conversions provided by DateTime, and DateTimeZone classes. Be careful when using.
如果使用 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() - see answer. To keep PHP with up to date Olson data, install periodically the timezonedb PECL package; see answer.
DateTimeZone::listAbbreviations() - 见答案。为了使 PHP 保持最新的 Olson 数据,请定期安装 timezonedb PECL 包;见答案。
If using C++, be sure to use a library that uses the properly implements the IANA timezone database. These include cctz, ICU, and Howard Hinnant's "tz" library.
如果使用 C++,请确保使用正确实现 IANA 时区数据库的库。其中包括 cctz、ICU 和 Howard Hinnant 的“tz”库。
Do not use Boost for time zone conversions. While its API claims to support standard IANA (aka "zoneinfo") identifiers, it crudely maps them to fixed offsets without considering the rich history of changes each zone may have had.
不要使用 Boost 进行时区转换。虽然其 API 声称支持标准 IANA(又名“zoneinfo”)标识符,但它粗略地将它们映射到固定偏移量,而没有考虑每个区域可能具有的丰富更改历史。
(Also, the file has fallen out of maintenance.)
(此外,该文件已停止维护。)
Most business rules use civil time, rather than UTC or GMT. Therefore, plan to convert UTC timestamps to a local time zone before applying application logic.
大多数业务规则使用民用时间,而不是 UTC 或 GMT。因此,在应用应用程序逻辑之前,计划将 UTC 时间戳转换为本地时区。
Remember that time zones and offsets are not fixed and may change. For instance, historically US and UK used the same dates to 'spring forward' and 'fall back'.
请记住,时区和偏移量不是固定的,可能会发生变化。例如,从历史上看,美国和英国使用相同的日期来“前进”和“后退”。
However, in 2007 the US changed the dates that the clocks get changed on. This now means that for 48 weeks of the year the difference between London time and New York time is 5 hours and for 4 weeks (3 in the spring, 1 in the autumn) it is 4 hours. Be aware of items like this in any calculations that involve multiple zones.
然而,在 2007 年,美国更改了时钟更改的日期。这意味着一年中有 48 周,伦敦时间和纽约时间之间的时差为 5 小时,4 周(春季 3 周,秋季 1 周)时差为 4 小时。请注意任何涉及多个区域的计算中的此类项目。
Consider the type of time (actual event time, broadcast time, relative time, historical time, recurring time) what elements (timestamp, time zone offset and time zone name) you need to store for correct retrieval - see "Types of Time" in answer.
考虑时间类型(实际事件时间、广播时间、相对时间、历史时间、重复时间)您需要存储哪些元素(时间戳、时区偏移和时区名称)以进行正确检索 - 请参阅“时间类型”回答。
Keep your OS, database and application tzdata files in sync, between themselves and the rest of the world.
使您的操作系统、数据库和应用程序 tzdata 文件在它们与世界其他地方之间保持同步。
On servers, set hardware clocks and OS clocks to UTC rather than a local time zone.
在服务器上,将硬件时钟和操作系统时钟设置为 UTC 而不是本地时区。
Regardless of the previous bullet point, server-side code, including web sites, should never expect the local time zone of the server to be anything in particular. see answer.
不管前面的要点是什么,服务器端代码,包括网站,永远不应该期望服务器的本地时区是特别的。见答案。
Use NTP services on all servers.
在所有服务器上使用 NTP 服务。
If using FAT32, remember that timestamps are stored in local time, not UTC.
如果使用 FAT32,请记住时间戳存储在本地时间,而不是 UTC。
When dealing with recurring events (weekly TV show, for example), remember that the time changes with DST and will be different across time zones.
在处理重复事件(例如每周电视节目)时,请记住时间会随 DST 发生变化,并且会因时区而异。
Always query date-time values as lower-bound inclusive, upper-bound exclusive (>=, <).
始终将日期时间值查询为下限包含,上限不包含 (>=, <)。
回答by hpaknia
Laconic Answer (no need to change default timezone)
简洁的答案(无需更改默认时区)
$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'
);
Loquacious Answer
滔滔不绝的回答
Use strtotime
's second option which changes the frame of reference of the function. By the way I prefer not to update the default time zone of the script:
使用strtotime
的第二个选项来改变函数的参考系。顺便说一句,我不想更新脚本的默认时区:
http://php.net/manual/en/function.strtotime.php
int strtotime ( string $time [, int $now = time() ] )
The function expects to be given a string containing an English date format and will try to parse that format into a Unix timestamp (the number of seconds since January 1 1970 00:00:00 UTC), relative to the timestampgiven in now, or the current time if now is not supplied.
http://php.net/manual/en/function.strtotime.php
int strtotime ( string $time [, int $now = time() ] )
该函数期望得到一个包含英文日期格式的字符串,并将尝试将该格式解析为 Unix 时间戳(自 1970 年 1 月 1 日 00:00:00 UTC 以来的秒数),相对于now 给出的时间戳,或如果现在没有提供当前时间。
And a Helper
还有帮手
/**
* 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')
)
);
Maybe not the most performant approach, but works well when you know the default timezone and the offset. For example if the default timezone is UTC
and the offset is -8
hours:
也许不是最高效的方法,但当您知道默认时区和偏移量时效果很好。例如,如果默认时区是UTC
并且偏移量是-8
小时:
var_dump(
date(
'Y-m-d',
strtotime('this tuesday', strtotime(-8 . ' hours'))
)
);