PHP strtotime без високосных лет - PullRequest
0 голосов
/ 24 декабря 2010

Что касается этой темы , я разработал частичное решение:

function strtosecs($time,$now=null){
    static $LEAPDIFF=86400;
    $time=strtotime($time,$now);
    return $time-(round((date('Y',$time)-1968)/4)*$LEAPDIFF);
}

Предполагается, что функция получает количество секунд, заданное для строки, без проверки високосных лет.

Он рассчитывает число високосных лет 1970 [(год-1986) / 4], умножив его на разницу в секундах между високосным годом и обычным годом (что в итоге является просто числом секунд в дне).

Наконец, я просто удаляю все лишние секунды високосного года из расчетного времени. Вот несколько примеров входов / выходов:

// test code
echo strtosecs('+20 years',0).'=>'.(strtosecs('+20 years',0)/31536000);
echo strtosecs('+1 years',0).'=>'.(strtosecs('+1 years',0)/31536000);

// test output
630676800 => 19.998630136986
31471200  => 0.99794520547945

Вы, вероятно, спросите, почему я делаю на выходе? Это чтобы проверить это; 31536000 - это количество секунд в году, поэтому 19,99 ... должно быть 20, а 0,99 ... должно быть 1. Конечно, я мог бы все это обойти и получить «правильный» ответ, но я беспокоюсь о неточностях.

Edit1: Так как это не кажется очевидным, моя проблема с inveteracies; Вы просто не спрашиваете PHP в течение 20 лет, и это дает вам 19,99 ..., верно?

Edit2: Кажется, все сводится к 1968 году;

  • 1970; нашел его точным во всех тестах, которые я пробовал.
  • 1969; Нашел его используется здесь (...ex: (2008-1969)/4 = 9.75...), а также упоминается здесь . Точность после 2-го года (+3 года) и далее.
  • 1968; как подробно описано ниже, это «нулевой год» високосных лет от времени Unix (1970). Это звучит "правильно" (для меня), но это не точно, вообще .

Ответы [ 2 ]

1 голос
/ 24 декабря 2010

Вы должны заменить 1968 в своих вычислениях (откуда это происходит?) На начало времени Unix: 1970, и вы получите более точные результаты. Редактировать

Вы должны сделать intval для подсчета количества високосных годов, которое должно быть целым числом:

return $time - (intval( (date('Y', $time) - 1969) / 4) * $LEAPDIFF);

Это даст вам правильные результаты в диапазоне +0 -> +68, время окончания unix на 32-битной машине

1 голос
/ 24 декабря 2010

Может ли это быть связано с присущей ему неточностью при использовании PHP для управления числами с плавающей запятой?

http://php.net/manual/en/language.types.float.php

...