数错 php date_diff
wrong count on php date_diff
我在 2015-03-01 和 2017-01-31(使用 php7.2)上做日期差异 returns 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');
但是,是的,'Europe/Berlin' 实际上也应该有效...
在阅读 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" ) );
}
这只是一个错误。已知的,古老的,从未解决过的。至少它在2017年重新开放...
我在 2015-03-01 和 2017-01-31(使用 php7.2)上做日期差异 returns 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');
但是,是的,'Europe/Berlin' 实际上也应该有效...
在阅读 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" ) );
}
这只是一个错误。已知的,古老的,从未解决过的。至少它在2017年重新开放...