日期转换错误(ndY 转 Y-m-d H:i:s)

3

我的代码返回的日期转换结果不正确

<?php
$date = '8312015';
$newDate = DateTime::createFromFormat('ndY', $date);
$convertedDate = $newDate->format('Y-m-d H:i:s');
echo $convertedDate;

返回

0021-11-12 17:04:56

期望:

2015-08-31 00:00:00

问题:

  1. 为什么PHP无法将ndY转换为Y-m-d H:i:s
  2. 为什么PHP追加当前小时,而不是00:00:00

注意:我尝试使用date()date_createdate_format,但得到同样的结果(错误日期)


3
那种日期格式不明确,请使用更易于解析的格式。如果未指定,PHP 将返回当前小时数。有关如何执行此操作,请参阅 DateTime::createFromFormat() 的手册。 - John Conde
3
“1152015”这个数字应该是1月15日还是11月5日呢?确切的说,没有人能确定。 - CBroe
应该返回1月15日。 - Leandro Papasidero
1
@Lea,请把它清理一下。如果长度小于8个字符,在前面加一个“0”。很简单! - Octopus
2
清理输入并不一定是黑客攻击。 - Octopus
显示剩余7条评论
2个回答

2

离成功只差一步!m实际上是:

月份的数字表示,前导零从01到12

(http://php.net/manual/en/function.date.php)

也就是说,它期望月份有两个字符,而不是一个。如果你输入

$date = '08312015';
$newDate = DateTime::createFromFormat('ndY', $date);

它按照你的意愿运作

当你执行以下操作时:

$date = '8312015';
$newDate = DateTime::createFromFormat('ndY', $date);

您得到的是month=83,day=12,year=015

83个月是6年11个月,所以015+6=21年+11个月=21年11月11日,即(0021-11-12),与输出匹配。

编辑: 显然你想表达的是n而非m,问题在于日期部分没有分隔符,所以如前所述,月份应该是8还是83是不明确的...

再次编辑 我的“答案”只是解释了问题,没有显示如何解决它,所以...

如果字段没有用定界符(例如-)或字段长度(即,m始终是2个字符)进行分隔,则转换是模棱两可的。鉴于显然php认为83是一个有效的月份,并且格式为n的月份可以有1个或多个数字,当php看到83时,它真的不能知道您是否表示“第8个月,然后以3开头的某些内容”还是“第83个月”。

因此,您需要消除歧义。一种消除歧义的方法是在左侧填充0,因为d(出于所有实际目的而言Y)始终是相同数量的数字(分别为2和4)。

因此,$date = str_pad($ date,8,“0”,STR_PAD_LEFT);将8312015变为08312015,然后您可以使用m进行格式化而不是n,然后从那里开始就可以了。对于大于9的月份,它不会更改输入字符串,因此对于该ndY格式中的所有字符串都是安全的。


OP实际上指定了“n”而不是“m”,但是它并不知道他是否指的是第8个月还是第83个月。为了减少歧义,OP应该使用“m”。 - Octopus
当我回答这个问题时,它是带有“m”的...后来被编辑为带有“n”。 - chiliNUT
@chiliNUT 所以答案是...你不能转换它吗?如果小于10,n并没有告诉你它只有一位数字? - Leandro Papasidero
@LeaTano,看一下更新,我和Octopus想出了大致相同的解决方案。 - chiliNUT

1
答案是您的输入数据必须归一化。我不知道您使用的标准是什么,但我假设最后四个字符总是年份。
现在我不知道的是:日期中的月份是否总是两个字符,或者您是否可以得到像“112015”这样的日期?如果是这样,那么对于“1112015”应该怎么办?1月11日还是11月1日?
归一化数据非常重要。
假设每月的日期始终为两位数,最简单的解决方案是:
if ( strlen($date)<8 ) {
  $date = '0'.$date;
} 

如果日期和月份都可能是一位数,那么你就有麻烦了!

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