strftime获取错误日期

6
我正在使用strftime来显示未来日期,但是在使用时...
strftime('%a., %d. %B %Y',time()+60*60*24*4)

我今天使用时得到的是2013年4月1日星期一,而不是2013年3月31日星期日。(Unix时间戳为1364423120)
strftime('%a., %d. %B %Y',time()+60*60*24*3)

显示正确的日期为2013年3月30日周六。
这里有什么问题,三月的最后一天是什么?

你的服务器时区是什么呢?请更仔细地查看这个函数/设置:http://php.net/manual/en/function.date-default-timezone-set.php - ducin
@tkoomzaaskz 有没有任何时区在3月31日缺失?我不这么认为 ;) - gronostaj
@gronostaj 糟糕的三月天气... - Sammitch
@tkoomzaaskz:服务器时区设置为欧洲/柏林,但正如gronostaj所指出的那样,这并不重要(请检查3月30日星期六和4月1日星期一)。 - crnm
底线:在添加天数时,不要忘记一天的长度只有平均24小时,但在夏令时切换时会偶尔出现23或25小时的情况。 - Sven
5个回答

5

时间戳表示当地时间为23:25:20。由于夏令时于3月31日生效,添加96小时将导致本地时间为00:25:20,因此比预期晚了一天。使用gmstrftime而不是strftime可以避免这个问题。

<?php

$timestamp = 1364423120;

echo strftime('%a., %d. %B %Y (%c %Z)', $timestamp)."\n";
echo strftime('%a., %d. %B %Y (%c %Z)', $timestamp +60*60*24*4)."\n";
echo gmstrftime('%a., %d. %B %Y (%c %Z)', $timestamp)."\n";
echo gmstrftime('%a., %d. %B %Y (%c %Z)', $timestamp +60*60*24*4)."\n";

提供

Wed., 27. March 2013 (Wed Mar 27 23:25:20 2013 CET)
Mon., 01. April 2013 (Mon Apr  1 00:25:20 2013 CEST)
Wed., 27. March 2013 (Wed Mar 27 22:25:20 2013 GMT)
Sun., 31. March 2013 (Sun Mar 31 22:25:20 2013 GMT)

这就是问题所在:夏令时带来了混乱。非常感谢 :) - crnm
谢谢您建议使用gmstrftime()。总有新东西要学习。 - crnm

1

检查你的时区。

使用以下代码查看由你的代码生成的日期的时间、时间戳和时区。

echo strftime('%s %H:%M:%S %z %Z %a., %d. %B %Y',time()+60*60*24*4);
//Output: 1364769859 15:44:19 -0700 PDT Sun., 31. March 2013

编辑:

如果这确实是您所在地区夏令时的问题[北美洲的更改是几周前],并且您只对日期的“日”部分感兴趣,那么我建议使用{{link1:date_add()}}而不是简单的算术运算,因为它将考虑到夏令时的变化和其他时间记录的特殊性。


他说明天,所以我有点困惑。 - Starx
@Starx 我有一个习惯,不太喜欢阅读问题中的冗长部分。这似乎更常常能够取得更好的效果。 - Sammitch
然而,这基本上与 OP 尝试的代码相同。除了“检查您的时区”之外,没有回答问题,这实际上只是一条评论。 - Starx
@Starx:感谢您提到date_add()。这也很有帮助。 - crnm
抱歉,我的意思是@Sammitch:感谢您提到date_add()。这是欧洲/德国的夏令时问题。 - crnm

1

根据手册

strftime - 根据区域设置格式化本地时间/日期

最好在使用时指定区域设置,以避免出现这样的问题。

setlocale(LC_TIME, "de_DE");
strftime('%a., %d. %B %Y',time()+60*60*24*4)

1
当我运行时。
echo strftime('%a., %d. %B %Y',time()+60*60*12*7)

我得到了

Sun., 31. March 2013

所以这个日期确实存在 :) 我认为它与当天发生的夏令时变化有关。当你使用整个一天(乘以24小时),你会跳过时区的变化。

感谢您的努力。这是夏令时的问题。对于任何阅读此处的人,一个快速的解决方法是使用strtotime('12:00:00')而不是time()。 - crnm
@crnm 很高兴我能帮到你。在处理时间时,你必须始终注意时区。即使现在 - 当你知道问题所在时 - 记住你的时区默认是设置在你的服务器上的。如果你的应用程序提供此功能,你还可以为已登录用户设置不同的时区。 - ducin

0

Terje D. 正确地提到了你在 DST 方面遇到的困惑。 但我也想提一种使用 DateTime 的方法,个人认为更易于理解和使用。

$dt = new DateTime('now', new DateTimeZone('UTC')); // creates a datetime object representing the current time in UTC
$dt->modify('+3 days'); // add 3 days to the datetime object
echo $dt->format('Y-m-d H:i:s')."\n"; // This will give you the time in english independent of the locale settings on your server
echo strftime('%a., %d. %B %Y', $dt->getTimeStamp()); // this will give you the time in your locale, which as mentioned before, will include DST

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接