|
|
|
| timestamp - помогите разобраться.
Есть массив, который описывает год в промежутках разной длины.
даты в массиве представлены в виде timestamp.
Например:
01.01.2009 - 28.02.2009
01.03.2009 - 31.08.2009
01.09.2009 - 31.10.2009
01.11.2009 - 31.12.2009
Есть две даты заданные пользователем. Бегаю по массиву, и выясняю, сколько дней из каждого периода задевает отрезок, заданный пользователем, получаю кол-во "задетых" дней в периоде, складываю, и на выходе имею общее кол-во дней (ночей).
Делаю это вот так (это внутри цикла):
if ($userFrom >= $Base->From)
{
if ($userTo <= $Base->To) $nights = (($userTo - $userFrom)/86400);
if ($userTo > $Base->To) $nights = (($Base->To - $userFrom)/86400);
}
if ($userFrom <= $Base->From)
{
if ($userTo < $Base->To) $nights = ($userTo - $Base->From)/86400;
if ($userTo >= $Base->To) $nights = ($Base->To - $Base->From)/86400;
}
|
Вот здесь начинается интересное.
В самом конце, для проверки правильности расчётов, полученное значение (сумму всех ночей) сравниваю с разницей заданных ользователем дат ($controlNights = round(($userTo-$userFrom)/86400);)
Пока же в цикле я складываю отдельно значение переменной $nights;
$nights - дробное число. Если я просто складываю все значения, то на выходе результат заведомо больше реального ($controlNights - накапливается дробная часть).
Если брать целую часть - то всё работает пучком, но при некоторых значениях заданных пользователем дат - наблюдается ошибка: общее кол-во $nights выходит на 1 меньше или больше, чем $controlNights.
Никак не могу понять, где возникает ошибка? Даты пробовал задавать самые разные, и максимум что могу предположить - связано это как-то с переводом стрелок весной и осенью, хотя при некоторых исходных параметрах даже в этот период происходит правильный расчёт.
Буду очень признателен за помощь. | |
|
|
|
|
|
|
|
для: Zilog
(30.11.2009 в 16:30)
| | Если у вас даты именно так, то для начала сделайте "реверс" датам - год вперед, день в конец. | |
|
|
|
|
|
|
|
для: sim5
(30.11.2009 в 16:34)
| | >Если у вас даты именно так, то для начала сделайте "реверс" датам - год вперед, день в конец.
даты в массиве представлены как unix timestamp (и далее везде) . Здесь я их так описал для удобства восприятия. | |
|
|
|
|
|
|
|
для: Zilog
(30.11.2009 в 16:39)
| | Ясно. А зачем такие сложности, ведь день года можно узнать функцией date для начальной и конечной меток, ну соответственно их разница даст период. | |
|
|
|
|
|
|
|
для: sim5
(30.11.2009 в 16:51)
| | >Ясно. А зачем такие сложности,
выборку по базе проще делать, как мне кажется.
Вариант описания только дат - рассматривал.
Уж не помню всю историю, но решил остановиться именно на таком решении.
Пример глюка:
Если период описан как 02.03.2009 - 31.05.2009,
а заданные пользователем даты: 26.03.2009 и 31.03.2009,
то результат будет 4 ночи (4.9583333333333 если не брать только целую часть - округлять до бОльшего смысла нет, т.к. ошибка плавает в обе стороны). | |
|
|
|
|
|
|
|
для: Zilog
(30.11.2009 в 16:56)
| | вопрос всё ещё актуален | |
|
|
|
|
|
|
|
для: Zilog
(30.11.2009 в 16:30)
| | В постановке задачи очень много неопределенности.
Пересечение интервалов вычисляется значительно проще. | |
|
|
|
|
|
|
|
для: Trianon
(30.11.2009 в 18:20)
| | >В постановке задачи очень много неопределенности.
да. главная - что периоды, да и все расчёты (функции работы с временем) в БД надо было перевести в ГМТ. Всё заработало
>Пересечение интервалов вычисляется значительно проще.
как? | |
|
|
|
|
|
|
|
для: Zilog
(30.11.2009 в 18:26)
| |
[PQ) = [AB) & [CD)
p = max(a, c)
q = min(b, d)
A*-----------------oB
C*---------------------oD
P*----------oQ
|
| |
|
|
|