【问题标题】:Strange behaviour of my code with strtotime我的代码与 strtotime 的奇怪行为
【发布时间】:2011-04-08 16:08:15
【问题描述】:

我对 PHP 中的日期有些头疼。我从表单中获取一些数据并尝试通过 ajax 调用“提交”它以更新网络而不重新加载页面。

我有一个允许选择日期范围的日期选择器,因此,我做了一个脏函数来分隔开始日期和结束日期,并将其分别发布到 PHP(以防选择日期范围)。它们的格式是这样的:01/04/2011,08/04/2011

在 PHP 中,我有日期变量并尝试格式化它们以通过这种方式执行一些数据库查询:

$date_start = $_POST['date_start'];
$date_start_form = date("Y-m-d",  strtotime($date_start));

经过一些测试,我发现如果日期高于任何一个月的第 12 天,然后尝试对其进行格式化,它会返回 1970-01-01。

有人知道为什么会这样吗?

【问题讨论】:

    标签: php datepicker


    【解决方案1】:

    顺便说一句,解决问题的方法是不使用 / 作为日期分隔符,如果 - 或 .像 08.04.2011 或 08-04-2011 一样使用,则将假定使用欧洲方法。

    如果您只能接收 08/04/2011 格式的日期,那么一个简单的 str_replace 将处理它:

    $date = "08/04/2011";
    $date = str_replace('/','.',$date); //08.04.2011
    echo date('Y-m-d',strtotime($date));  //2011-04-08
    

    【讨论】:

    • 不错!这解决了这个问题:D
    • 欢迎您,如果您修改发送日期的任何内容,在 - 或 .格式而不是使用 str_replace,但无论哪种方式,str_replace 都是一个非常快的函数。
    • 哦,废话,刚刚意识到我的代码中有错误应该是echo date('Y-m-d',strtotime($date));$date = strtotime(str_replace('/','.',$date))
    【解决方案2】:

    它们的格式是这样的:01/04/2011,08/04/2011

    这可能是您的问题:如果这些日期应该在四月,那么您使用的是欧洲书写日期的方式。 strtotime 需要美国日期,因此它可能将月份解释为日期和月份中的日期(这也是如果日期大于 12 会中断的原因)。

    维基百科:Date and time notation in the United States

    【讨论】:

    • Meh 领先我一分钟 =\ 哦,好吧,+1。 @op:像往常一样,当某些事情不能正常工作时,阅读手册可能会有所帮助。
    • 是的,我也是这么想的,但是解决办法是什么?我应该按分数打破他们,然后他们拉一个新的日期吗?好像有点脏。
    • @Antonio 您可以更改传入日期的格式。如果这是不可能的,一个非常干净的方法是DateTime::CreateFromFormat - 如果你有 PHP 5.3
    【解决方案3】:

    听起来你把日期和月份搞混了。当您将它们提供给 strtotime() 时,它期望月份是第二个数字,而不是第一个。

    【讨论】:

    • 这就是问题所在,但你知道解决办法是什么吗?
    【解决方案4】:

    那是时区问题。 strtotime 将其考虑在内。您可以使用

    设置正确的
    date_default_timezone_set('Europe/London');
    

    或 strtotime 调用之前的任何一个。请参阅list of supported timezones

    【讨论】:

    • 不,更改时区不起作用,看看我的回答。如果更改时区有效,那么您在论坛或用户可以设置自己的时区的任何地方都会有非常奇怪的行为。
    • @Phoenix:如果您查看 strtotime 手册,它清楚地说“此函数将使用 TZ 环境变量(如果可用)来计算时间戳。”不过,您是对的,TZ 可能不会影响用于解析的日期格式。
    • 是的,它使用时区来确定与 UTC 的偏移量,以得出从 1970 年 1 月 1 日 00:00:00 UTC 开始的秒数。本质上,它假定给 strtotime 的时间/日期是当前设置的时区的时间/日期。
    【解决方案5】:

    据我所知,strptime 是唯一一个接受日期作为字符串和日期格式的 php 函数,然后您可以使用返回的数组生成时间戳。

    例如:

    $timeArr = strptime($date_start ,"DD/MM/YY");
    $timestamp = mktime(0, 0, 0, $timeArr['tm_mon']+1, $timeArr['tm_mday'], $timeArr['tm_year']);
    $date_start_form = date("Y-m-d", $timestamp);
    

    或者你可以直接构建字符串,例如:

    $timeArr = strptime($date_start ,"DD/MM/YY");
    $date_start_form = sprintf(%d-%d-%d, $timeArr['tm_year'], $timeArr['tm_mon']+1, $timeArr['tm_mday']);
    

    尽管考虑一下,您可以将传入日期视为需要重新排列的字符串,而忽略它是日期的事实,例如:

    $timeArr = explode($date_start ,"/");
    $date_start_form = sprintf(%d-%d-%d, $timeArr[2], $timeArr[1], $timeArr[0]);
    

    【讨论】:

    • 这应该返回一个数组,而不是解决问题 AFAIK
    • 我已经更新了我的答案以包含更多细节。我建议使用 strptime,因为它是接受日期格式的函数。可以使用数组生成新字符串
    【解决方案6】:

    如果您使用 php=>5.3,可能值得一看 DateTime::createFromFormat 函数。 对于您的情况,它可以像这样实现:

    $date = "08/04/2011";
    $date_object = DateTime::createFromFormat('d/m/y', $date);
    $timestamp = $date_object->getTimestamp();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多