我在2015-03-01和2017-01-31(使用php7.2)做了一个日期差异,它返回1年,11个月和2天。但它(显然)应该是11个月和0天或10个月和30天。
这是为什么?请不要告诉我,php除以30或者其他东西 - 如果它不如手动解决方案那么可靠,我不需要日历功能!这会很疯狂,对吧?
$diff = date_create('2015-03-01')->diff(date_create('2017-01-31'));
// returns
DateInterval Object
(
[y] => 1
[m] => 11
[d] => 2
[h] => 0
[i] => 0
[s] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 702
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
// and that's simply just wrong
将时区从“Europe / Berlin”切换为“UTC”时更新
date_default_timezone_set('UTC');
但是,'欧洲/柏林'实际上也应该有效......
在阅读php.net文档comments about this function时,我发现了一个似乎有效的解决方案。有人重写了PHP 5.2和旧版本的diff()函数。
结果:1年10个月30天(但您可以将其修改为包含)
绝对不是最优雅的解决方案,但我希望这会有所帮助。
<?php
echo get_timespan_string(new Datetime('2015-03-01'), new Datetime('2017-01-31'));
function get_timespan_string($older, $newer) {
$Y1 = $older->format('Y');
$Y2 = $newer->format('Y');
$Y = $Y2 - $Y1;
$m1 = $older->format('m');
$m2 = $newer->format('m');
$m = $m2 - $m1;
$d1 = $older->format('d');
$d2 = $newer->format('d');
$d = $d2 - $d1;
$H1 = $older->format('H');
$H2 = $newer->format('H');
$H = $H2 - $H1;
$i1 = $older->format('i');
$i2 = $newer->format('i');
$i = $i2 - $i1;
$s1 = $older->format('s');
$s2 = $newer->format('s');
$s = $s2 - $s1;
if($s < 0) {
$i = $i -1;
$s = $s + 60;
}
if($i < 0) {
$H = $H - 1;
$i = $i + 60;
}
if($H < 0) {
$d = $d - 1;
$H = $H + 24;
}
if($d < 0) {
$m = $m - 1;
$d = $d + get_days_for_previous_month($m2, $Y2);
}
if($m < 0) {
$Y = $Y - 1;
$m = $m + 12;
}
$timespan_string = create_timespan_string($Y, $m, $d, $H, $i, $s);
return $timespan_string;
}
function get_days_for_previous_month($current_month, $current_year) {
$previous_month = $current_month - 1;
if($current_month == 1) {
$current_year = $current_year - 1; //going from January to previous December
$previous_month = 12;
}
if($previous_month == 11 || $previous_month == 9 || $previous_month == 6 || $previous_month == 4) {
return 30;
}
else if($previous_month == 2) {
if(($current_year % 4) == 0) { //remainder 0 for leap years
return 29;
}
else {
return 28;
}
}
else {
return 31;
}
}
function create_timespan_string($Y, $m, $d, $H, $i, $s)
{
$timespan_string = '';
$found_first_diff = false;
if($Y >= 1) {
$found_first_diff = true;
$timespan_string .= pluralize($Y, 'year').' ';
}
if($m >= 1 || $found_first_diff) {
$found_first_diff = true;
$timespan_string .= pluralize($m, 'month').' ';
}
if($d >= 1 || $found_first_diff) {
$found_first_diff = true;
$timespan_string .= pluralize($d, 'day').' ';
}
if($H >= 1 || $found_first_diff) {
$found_first_diff = true;
$timespan_string .= pluralize($H, 'hour').' ';
}
if($i >= 1 || $found_first_diff) {
$found_first_diff = true;
$timespan_string .= pluralize($i, 'minute').' ';
}
if($found_first_diff) {
$timespan_string .= 'and ';
}
$timespan_string .= pluralize($s, 'second');
return $timespan_string;
}
function pluralize( $count, $text )
{
return $count . ( ( $count == 1 ) ? ( " $text" ) : ( " ${text}s" ) );
}
这只是一个bug。已知,陈旧,永不解决。至少它在2017年重新开放......