【问题标题】:php date_parse_from_format() does not recognise difference between y and Yphp date_parse_from_format() 无法识别 y 和 Y 之间的差异
【发布时间】:2016-04-08 01:18:19
【问题描述】:

一直在使用 Laravel 验证器,我注意到验证日期的一个奇怪问题。

Laravel date_format 依赖于 php date_parse_from_format 方法。但是,当您将格式设置为 d/m/Y 时,此方法似乎无法识别 y 和 Y 之间的区别。因此,如果您传入 01/01/15 或 01/01/2015 两者都解析没有错误。你会认为前者会出错,或者至少我会。

如果您将格式更改为 d/m/y,它将按预期工作。即 15 年 1 月 1 日通过,2015 年 1 月 1 日失败。

我很想知道是否有其他人对此有任何想法,以及我是否遗漏了一些明显的东西。这可能对 PHP 和 Laravel 都有影响。

注意我使用的是php 5.6.16,我的输出如下...

string 'd/m/Y' (length=5)
string '01/01/15' (length=8)

array (size=12)
  'year' => int 15
  'month' => int 1
  'day' => int 1
  'hour' => boolean false
  'minute' => boolean false
  'second' => boolean false
  'fraction' => boolean false
  'warning_count' => int 0
  'warnings' => 
    array (size=0)
      empty
  'error_count' => int 0
  'errors' => 
    array (size=0)
      empty
  'is_localtime' => boolean false

string 'd/m/Y' (length=5)
string '01/01/2015' (length=10)

array (size=12)
  'year' => int 2015
  'month' => int 1
  'day' => int 1
  'hour' => boolean false
  'minute' => boolean false
  'second' => boolean false
  'fraction' => boolean false
  'warning_count' => int 0
  'warnings' => 
    array (size=0)
      empty
  'error_count' => int 0
  'errors' => 
    array (size=0)
      empty
  'is_localtime' => boolean false

string 'd/m/y' (length=5)
string '01/01/15' (length=8)

array (size=12)
  'year' => int 2015
  'month' => int 1
  'day' => int 1
  'hour' => boolean false
  'minute' => boolean false
  'second' => boolean false
  'fraction' => boolean false
  'warning_count' => int 0
  'warnings' => 
    array (size=0)
      empty
  'error_count' => int 0
  'errors' => 
    array (size=0)
      empty
  'is_localtime' => boolean false

string 'd/m/y' (length=5)
string '01/01/2015' (length=10)

array (size=12)
  'year' => int 2020
  'month' => int 1
  'day' => int 1
  'hour' => boolean false
  'minute' => boolean false
  'second' => boolean false
  'fraction' => boolean false
  'warning_count' => int 0
  'warnings' => 
    array (size=0)
      empty
  'error_count' => int 1
  'errors' => 
    array (size=1)
      8 => string 'Trailing data' (length=13)
  'is_localtime' => boolean false

输出数据的示例代码是...

$format = 'd/m/Y';
var_dump($format);
$date = '01/01/15';
var_dump($date);
var_dump(date_parse_from_format($format, $date));

$format = 'd/m/Y';
var_dump($format);
$date = '01/01/2015';
var_dump($date);
var_dump(date_parse_from_format($format, $date));

etc...

【问题讨论】:

  • 你实际上是如何解析你的日期的?你能给我们看一些代码吗?
  • 可能是因为15,即15AD是一个有效年份,可以假定为0015
  • 添加了一些代码。我还假设它与公元 15 年有关,但 Y 暗示 yyyy。所以当然它不应该在那个基础上解析。它需要四位数?
  • 不,Y 暗示这是一个完整的日期。无论如何,该函数将拆分日期的片段,然后尝试将其转换为整数。 string('15') 将成功转换为 int(15)
  • 那么 date_parse_from_format 不是正确的方法,如果你想检查一个日期是否正好是 'dd/mm/yyyy' 那么?

标签: php validation date laravel


【解决方案1】:

这是预期的行为,而不是错误。

15 将被解释为 0015 A.D.,然后,d/m/Y 将能够成功解析它。

另一个可能的结果:

$date3 = date_parse_from_format('d/m/y', '01/01/2015');
var_dump($date3);

这将生成:

array(12) {
  ["year"]=>
  int(2020)
  ["month"]=>
  int(1)
  ["day"]=>
  int(1)
  ["hour"]=>
  bool(false)
  ["minute"]=>
  bool(false)
  ["second"]=>
  bool(false)
  ["fraction"]=>
  bool(false)
  ["warning_count"]=>
  int(0)
  ["warnings"]=>
  array(0) {
  }
  ["error_count"]=>
  int(1)
  ["errors"]=>
  array(1) {
    [8]=>
    string(13) "Trailing data"
  }
  ["is_localtime"]=>
  bool(false)
}

注意errors 索引。它将成功地将01/01/20 解释为 2020 年 1 月 1 日,并会生成一个发现尾随数据的错误。

编辑

当您切换到 OO API DateTime::createFromFormat 时,默认行为会发生变化并按预期工作

$date3 = DateTime::createFromFormat('d/m/y', '01/01/2015');
var_dump($date3); // will yield FALSE, as it does not recognize the intput

从 PHP 5.3.9 开始,我们可以使用 + 标志,其行为类似于 date_parse_from_format

$date3 = DateTime::createFromFormat('d/m/y+', '01/01/2015');
var_dump($date3); // will yield a DateTime object

您可以使用DateTime::getLastErrors() 获取生成的错误。

请参阅docs

【讨论】:

  • 我测试了 'd/m/y' 并得到了预期的结果,请参阅我的输出。对我来说,这里的问题是 php 中的文档说 Y 应该匹配四位数字。所以只有 0015 应该匹配,而 15 应该错误。 php.net/manual/en/datetime.createfromformat.php
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-13
  • 2021-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
  • 2021-09-11
相关资源
最近更新 更多