неправильный счет на php date_diff - PullRequest
0 голосов
/ 23 апреля 2019

Я делаю разность дат 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

ОБНОВЛЕНИЕ работает при переключении часового пояса с «Европа / Берлин» на «UTC»

date_default_timezone_set('UTC');

но да, «Европа / Берлин» на самом деле тоже должно работать...

Ответы [ 2 ]

0 голосов
/ 24 апреля 2019

это просто ошибка.известный, старый, никогда не решаемый.по крайней мере, он был вновь открыт в 2017 году ...

PHP DateTime Timedifference только правильно в часовом поясе UTC?

0 голосов
/ 23 апреля 2019

Читая документацию php.net комментирует эту функцию , я нашел решение, которое, кажется, работает.Кто-то переписал функцию diff () для PHP 5.2 и более ранних версий.

Результат: 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" ) ); 
}
...