首页 > 解决方案 > 为什么 PHP 会将一些浮点数解析为奇怪的日期?

问题描述

今天是 9 月 21 日。为什么以下浮点数会被解析为奇怪的日期?我意识到它们首先被转换为字符串,然后被解析,但格式似乎没有任何意义。这些是遵循我不知道的某种格式,还是未定义的行为?

我没有看到任何适用的格式:

var_dump(new DateTime(5.123456));
class DateTime#1 (3) {
  public $date =>
  string(26) "3456-09-21 05:12:00.000000"
  public $timezone_type =>
  int(3)
  public $timezone =>
  string(3) "UTC"
}

5.123456

  • 小时:5
  • 分钟:12
  • 秒:0.0
  • 年:3456
  • 月份:现在 (9)
  • 日期:现在 (21)
var_dump(new DateTime(5.1203047891));
class DateTime#1 (3) {
  public $date =>
  string(26) "7891-09-21 05:12:00.000000"
  public $timezone_type =>
  int(3)
  public $timezone =>
  string(3) "UTC"
}

5.1203047891

  • 小时:5
  • 分钟:12
  • 秒:0.0
  • 忽略: 0304
  • 年:7891
  • 月份:现在 (9)
  • 日期:现在 (21)

其他一些字符串:

我已经能够预测某些部分,但它并没有遵循合理的整体格式。这里发生了什么?

标签: phpdatetime

解决方案


只有 DateTime 类代码的创建者才能完全回答这个问题。我只是想解释一下动机。DateTime 想要解释许多可能的免费格式。首先,将输入转换为字符串。

class test{
  public function __toString(){
    return "2001-02-03 04:05:06";
  }
}

$d = new DateTime(new test);
//object(DateTime)#2 (3) { ["date"]=> string(19) "2001-02-03 04:05:06" ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/Berlin" } 

此处使用的方法 __toString 证实了这一点。如果字符串为空,则从当前日期和当前时间生成日期。这也是输入中缺少信息的基础。然后尝试识别时间(时间格式)。

该测试表明,第一次尝试是确定时间。请看以下测试或确认。这在手册Date Formats中有描述:

年份(也就是年份)YY“1978”、“2008”

'1978' 不能是时间,所以它被解析为一年。

var_dump(new DateTime('1978'));  //"1978-09-23 09:46:43.000000"

但“2008”可以代表一个时间。它被解析为时间 20:08。

var_dump(new DateTime('2008'));  //  "2019-09-23 20:08:00.000000"

小时、分钟和秒可以通过:,,来改变。或者没有什么可以分开的。如果仅检测到一个时间,则将当前日期作为日期。示例(今天是 2019 年 9 月 23 日):

'04:08','0408','04.08'      => "2019-09-23 04:08:00.000000"
'04.08.05','04.08:05','040805'  => "2019-09-23 04:08:05.000000"

然后尝试解析日期。输入中的订单日期/时间或时间日期无关紧要。所有字符串解析为“2001-02-03 04:05:00.000000”:

'04:05 2001-02-03'
'04.05 20010203'
'04.0520010203'
'4.0520010203'

'2001020304.05'
'20010203 04.05'

你的字符串:'5.123456'

解析器首先将 5.12 分析为时间 05:12。其余的是“3456”年。

字符串 '5.12345678901232004' 将被解析为 '5.12 34567890123 2004' 5.12 时间 05:12 和 2004 年。

var_dump(new DateTime('5.12 34567890123 2004'));
//object(DateTime)#2 (3) { ["date"]=> string(26) "2004-05-02 05:12:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(13) "Europe/Berlin" }

我不知道如何确定剩余的字符串'34567890123'第02天和第05个月。

这个问题没有完全回答。我希望有助于理解 DateTime 解析器。


推荐阅读