我只是想对此进行一些澄清。PHP 5.4 消除了 TZ 环境变量和过去的“猜测” date_default_timezone_get
。所以现在在我看来,根本没有办法获得服务器的时区。
所以我的问题是:是否可以在 PHP 5.4 中获取服务器时区?我知道我可以在 php.ini 中手动设置它,但是当有一台完全能够知道现在几点的计算机时,这似乎有点愚蠢。我希望答案是“不”,所以也许有人可以解释为什么编程语言在这种情况下无法确定其时区。
没有可靠的方法来猜测每个系统上的时区。不同的系统使用不同的约定,有时甚至不同的时区定义(例如 Unix 和 Windows),有时有冲突的时区说明符(相同的 3 个字母的区域缩写在不同的地方可能意味着不同的东西)。因此,如果您想拥有可在系统之间移植的代码,唯一可靠的方法就是询问用户。例如,请参阅此线程: http ://marc.info/?t=132356551500002&r=1& w=2 关于它的一些问题(查找来自 Derick Rethans 的电子邮件 - 他是 PHP 日期时间扩展维护者)。
如果您有办法找出您信任的时区 - 例如 TZ 变量 - 那么您总是可以这样做date_default_timezone_set($_SERVER['TZ']);
。但是总的来说,这不是一种可靠的方法,因此必须由您决定是否信任它,PHP 无法为您服务。
如果你看这里,你会看到 PHP 5.3 中的代码,它试图猜测系统时区。没有那么多,但似乎消除猜测的原因主要与 DST 有关,因为这似乎是问题出现的地方。
整个猜测过程的细分如下所示:
TZ
环境变量(根据我的经验很少定义)(第 855-858 行)date.default_timezone
(应该已经定义的特殊情况)(第 860-872 行)time()
区localtime()
。规范似乎说设置时区是可选的,因为此调用的线程版本可能存在问题(第 873-890 行)GetTimeZoneInformation()
并尝试确定系统时区(第 893-928 行)_timezone
值是否已定义(第 929-937 行)我只能推测,但也许他们只是将其删除,因为这是一个猜测,并不总是可靠的。
同样由于 PHP 的流行,它安装在几乎所有基于 Linux 的共享托管计划中,其中客户通常与服务器不在同一时区,因此对于这些人来说,回退到服务器时区并不比默认使用 UTC 更好。然后它只会引起混乱,因为这些客户必须来 SO 询问为什么 PHP 的时间是错误的。
我对 C 和标准不够熟悉,但似乎基于localtime
多线程代码猜测时区有问题,或者在某些情况下不可用。由于在非 Windows 平台上,这是确定时区的最佳方法,如果说一半时间它不返回任何内容或导致多线程 PHP 出现问题,那么这样做是没有意义的。
当然,在时区和偏移量因一年中的时间而异的某些地方存在 DST 问题。
希望有帮助。
不,目前无法在 PC 上检索时区。
我最近从头开始为一个项目构建了几台服务器。由于之前在服务器使用本地时区的其他项目中的经验,我选择强制每台服务器使用“UTC”时区。尽管这导致日志文件关闭 7 小时(UTC - PST),但它确实消除了设置本地时区导致的不一致(来自上一个项目)。
强制一致性在操作系统和应用层被证明是有用的。对于 OS 层,所有日志文件条目都可以从一个集中位置(通过 udp 上的 syslog)查看,而不管它们的物理位置如何。在应用层,将每个时间戳存储为 UTC 更容易,然后在渲染上为指定时区的用户进行转换。这种单向转换比双向转换要简单得多,在双向转换中,您必须在保存时将时间戳从服务器的本地时区转换为 UTC,然后在渲染时将其转换为用户选择的时区。
因此,除非有非常令人信服的理由让您的服务器了解时区,否则我会选择坚持使用 UTC,这是 5.4 之前的默认设置:“如果上述方法均不成功,则 date_default_timezone_get() 将返回 UTC 的默认时区。 "
这只是一个疯狂的猜测。您能否通过以下方式获取时区:
date('H', 0);
或类似的东西?我的意思是,由于 unixtime 时间戳在所有地区都是相同的,但Hour
不同,你不应该能够根据小时知道使用哪个时区吗?
在 Windows 服务器上,可以通过一些数学运算获得本地系统时区:
<?php
date_default_timezone_set('UTC');
$nowUTC = new DateTime();
$nowSys = new DateTime(exec('echo %time%'));
$offset = $nowUTC->diff($nowSys);
echo $nowUTC->format('H:i:s') . '<br />';
echo $nowSys->format('H:i:s') . '<br />';
echo $offset->format('%H');
?>
在编写此代码的输出时,从我的语言环境 (UTC-05) 来看:
22:16:41
17:16:41
05
有一个警告:时间戳有时会偏离 1 秒,导致$offset
变量为 4:59:59。始终如一地获得正确的时区应该做一些四舍五入以确保安全。