将strtotime与时区和计算一起使用时会产生意外结果。我的PHP设置为UTC。 strtotime("-6 days 00:00:00 America/Chicago");
似乎给出了意外的结果。我认为,通过提供时区,可以在该时区中“计算”出来,但情况并非如此。
在我的示例中,无论PHP的默认时区为何,我都希望结果相同,因为strtotime中使用了“ America / Chicago”。取而代之的是,它似乎要花费当前日期(根据默认时区)并减去天数,然后在提供的时区中计算00:00:00。
我格式化错误吗?
我为混乱的代码表示歉意,但这只是一个例子,展示了我在说什么。
date_default_timezone_set("UTC");
echo date_default_timezone_get();
echo "</br>";
echo "</br>";
echo convertTS(time(), "America/Chicago");
echo "</br>";
echo "</br>";
$test = strtotime("-6 days 00:00:00 America/Chicago");
echo $test;
echo "</br>";
echo convertTS($test, "America/Chicago");
echo "</br>";
$test = strtotime("-7 days 00:00:00 America/Chicago");
echo $test;
echo "</br>";
echo convertTS($test, "America/Chicago");
echo "</br>";
echo "</br>";
echo "-----------------";
echo "</br>";
echo "</br>";
///now in America/Chicago
date_default_timezone_set("America/Chicago");
echo date_default_timezone_get();
echo "</br>";
echo "</br>";
echo convertTS(time(), "America/Chicago");
echo "</br>";
echo "</br>";
$test = strtotime("-6 days 00:00:00 America/Chicago");
echo $test;
echo "</br>";
echo convertTS($test, "America/Chicago");
echo "</br>";
$test = strtotime("-7 days 00:00:00 America/Chicago");
echo $test;
echo "</br>";
echo convertTS($test, "America/Chicago");
function convertTS($timestamp, $timezone)
{
if( empty($timestamp) )
{
return 'n/a';
}
else
{
//output the time
$dt = new DateTime('@'.$timestamp);
$dt->setTimeZone(new DateTimeZone($timezone));
return $dt->format('D, m/d/y @ g:i:s a T');
}
}
我在运行时得到的上述结果:
UTC
Fri, 01/04/19 @ 11:39:15 pm CST
1546149600
Sun, 12/30/18 @ 12:00:00 am CST
1546063200
Sat, 12/29/18 @ 12:00:00 am CST
-----------------
America/Chicago
Fri, 01/04/19 @ 11:39:15 pm CST
1546063200
Sat, 12/29/18 @ 12:00:00 am CST
1545976800
Fri, 12/28/18 @ 12:00:00 am CST
我制作了一个沙盒来随时here来重新创建此问题。提供时间戳是不同的,而不是使用time()
来显示默认时区如何根据当前时间影响结果。
答案 0 :(得分:1)
首先,让我们开始解释一些小事情:
convertTS
将始终返回与默认时区无关的相同结果调用convertTS
函数时,它将采用UTC的时间戳,并以CST时区进行转换和显示。当您将1546578000作为参数传递时,您将获得“ 2019-01-03 23:00:00.000000”。
strtotime
接受2个参数:int strtotime ( string $time [, int $now = time() ] )
。但是PHP文档说,此函数的两个参数都使用默认时区,除非在该参数中指定了时区。在您的示例中,您每次都在第一个参数中明确指定时区。第二个参数读取默认时间戳,并在计算相对日期之前将UTC UNIX时间戳转换为该时区。
当时区为UTC时:
date_default_timezone_set("UTC");
strtotime("-2 days 00:00:00 America/Chicago", 1546578000);
2019-01-04 05:00:00.000000
2019-01-04 06:00:00.000000 *UTC+00:00*
2019-01-02 06:00:00.000000
默认时区为CST时:
date_default_timezone_set("America/Chicago");
strtotime("-2 days 00:00:00 America/Chicago", 1546578000);
2019-01-03 23:00:00.000000
2019-01-03 06:00:00.000000 *UTC+00:00*
2019-01-01 06:00:00.000000
相对日期的PHP解析器并不完美。实际上,我认为将UNIX时间戳转换为默认时区是错误的……否则我的理解也可能有缺陷。
我将代码更改为使用DateTime
类。
date_default_timezone_set("UTC");
$dt = (new \DateTime())->setTimestamp(1546578000);
$dt->modify("-2 days 00:00:00 America/Chicago");
echo "UTC: ".$dt->format('D, m/d/y @ g:i:s a T');
echo "</br>";
echo "</br>";
echo "-----------------";
echo "</br>";
echo "</br>";
///now in America/Chicago
date_default_timezone_set("America/Chicago");
$dt = (new \DateTime())->setTimestamp(1546578000);
$dt->modify("-2 days 00:00:00 America/Chicago");
echo "CST: ".$dt->format('D, m/d/y @ g:i:s a T');
答案 1 :(得分:0)
必须明确考虑字符串中的时区:
date_default_timezone_set('UTC');
var_dump(date('r', strtotime('-6 days 00:00:00 America/Chicago')));
var_dump(date('r', strtotime('-6 days 00:00:00 Europe/Madrid')));
string(31) "Sun, 30 Dec 2018 06:00:00 +0000"
string(31) "Sat, 29 Dec 2018 23:00:00 +0000"
也许令人困惑的是,结果是在配置的时区中显示:
date_default_timezone_set('UTC');
var_dump(date('r', strtotime('-6 days 00:00:00 America/Chicago')));
date_default_timezone_set('Europe/Madrid');
var_dump(date('r', strtotime('-6 days 00:00:00 America/Chicago')));
string(31) "Sun, 30 Dec 2018 06:00:00 +0000"
string(31) "Sun, 30 Dec 2018 07:00:00 +0100"
...但实际时间相同:
date_default_timezone_set('UTC');
var_dump(strtotime('-6 days 00:00:00 America/Chicago'));
date_default_timezone_set('Europe/Madrid');
var_dump(strtotime('-6 days 00:00:00 America/Chicago'));
string(10) "1546149600"
string(10) "1546149600"
答案 2 :(得分:0)
在@Dharman的帮助下,指出strtotime如何实际处理事情(我仍然认为这是错误的),无论php的默认时区如何,我都可以修改一些内容并得出期望的结果。这样可以提供我期望的结果...在指定的时区中进行计算(减去天数并设置为00:00:00)。
date_default_timezone_set("UTC");
$time = time();
//$time = 1546578000;
$tz = "Europe/Amsterdam";
$dt = new DateTime('@'.$time);
$dt->setTimeZone(new DateTimeZone('UTC'));
echo $dt->format('D, m/d/y @ g:i:s a T');
echo "\n";
echo $dt->format('U');
echo "\n";
echo "\n";
$dt = new DateTime('@'.$time);
$dt->setTimeZone(new DateTimeZone('UTC'));
$dt->modify("-2 days 00:00:00");
echo $dt->format('D, m/d/y @ g:i:s a T');
echo "\n";
echo $dt->format('U');
echo "\n";
echo "\n";
echo "---------------";
echo "\n";
echo "\n";
$dt = new DateTime('@'.$time);
$dt->setTimeZone(new DateTimeZone($tz));
echo $dt->format('D, m/d/y @ g:i:s a T');
echo "\n";
echo $dt->format('U');
echo "\n";
echo "\n";
$dt = new DateTime('@'.$time);
$dt->setTimeZone(new DateTimeZone($tz));
$dt->modify("-2 days 00:00:00");
echo $dt->format('D, m/d/y @ g:i:s a T');
echo "\n";
echo $dt->format('U');
在这种情况下将输出:
Sat, 01/05/19 @ 6:51:18 pm UTC
1546714278
Thu, 01/03/19 @ 12:00:00 am UTC
1546473600
---------------
Sat, 01/05/19 @ 7:51:18 pm CET
1546714278
Thu, 01/03/19 @ 12:00:00 am CET
1546470000