Боремся с 77 февраля: мой вариант

В общем, вчерашняя моя задачка во многом потеряла смысл, когда Дима Смирнов указал мне на наличие функции checkdate (). Просто когда проблема возникла я не пошёл читать мануал в поисках готовой функции, так как был уверен, что после того, как я намучился с проблемой часовых поясов и летнего времени (и стал мировым экспертом в этой области), я уже по-любому знаю все функции, связанные с датой временем. Оказалось, что я ошибся.

Впрочем, придумывать сложной математики мне не пришлось. Моё решение было однострочным и работало так:

return (
  gmdate ('Y/n/d', gmmktime (0, 0, 0, $m, $d, $y))
  == $y .'/'. $m .'/'. $d
);

Функция mktime умеет делать нормальный «тайм-штамп» из любых входных параметров. Например, если дать ей 25 часов 99 минут 32 декабря 2008 когда, то она вернёт штамп для 2 часов 39 минут 2 января 2009 не поперхнувшись.

Это свойство функции mktime () страшно удобно, потому, что если нужно посчитать, какими будут дата и время через 55 часов, то можно тупо прибавить 55 к часам и забыть про суточные, месячные и годовые переходы, забыть про учёт високосности — функция всё сделает сама.

Короче, критерий правильности даты — то, что функции не пришлось ничего «исправлять». (На самом деле, я уверен, что функция ничего и не исправляет, просто формулы в ней написаны так, чтобы всё работало независимо от корректности входных параметров.) А GMT-версии функций я использую «для надёжности», чтобы нигде часовые пояса не могли что-нибудь испортить.

Сергей Коваленко в комментариях к прошлой заметке предложил это же решение, причём совершенно справедливо не стал проверять день.

Подписаться на блог
Отправить
Дальше
5 комментариев
Сергей Коваленко 2008

мне кажется, использование gm-функций здесь не оправдано. Они дают штамп времени по Гринвичу, в отличие от простых функций, показывающих штамп поясного серверного времени; и соответственно, они должны работать незметно медленнее. А поскольку в нашей функции мы ищем различия в штапме по одному и тому же поясу, то и приведение ко Гринвичу ничего не изменяет в данном случае. Т. е. gmdate(gmmktime()) будет эквивалентно date(mktime()).

Лёха zloy и красивый 2008
Илья Бирман 2008

Из описания функции не следует, что она вернёт -1 для несуществующей даты. Там сказано просто, что она вернёт -1 «в случае ошибки». Но может оказаться, что речь идёт просто об ошибке парсинга.

Лёха zloy и красивый 2008

Парсинга чего, пхп? :)

Если ты имел в виду дату, то — да. Дату надо писать в любом буржуазном формате. А в функцию mktime() писать параметры в правильной последовательности. Ох уж этот пхп.

Илья Бирман 2008

Парсинга той херни, которую ты передаёшь шаманской функции strtotime ().

Лёха zloy и красивый 2008

Ну ты и ленивый. А попробовать функцию?

(gmdate (’Y/n/d’, gmmktime (0, 0, 0, $m, $d, $y)) == $y .’/’. $m .’/’. $d);

Тоже самое:
strtotime($y .’/’. $m .’/’. $d) > 0;

Или (более читаемый без подсветки):
strtotime(sprintf(’%s/%s/%s’, $y, $m, $d)) > 0;

В функции нет ничего шаманского. Она просто много делает, что для PHP нехарактерно. Но у неё много плюшек и если с strrotime() поближе познакомиться, то можно упростить и жизнь и код. :)

Илья Бирман 2008

Если я мгновенно придумал решение, в котором не сомневаюсь, зачем мне придумывать какое-то ещё решение, которое, тем более, нужно ещё и проверять? :-)

Сергей К. 2008

«Цайтштемпель» (http://de.wikipedia.org/wiki/Zeitstempel)

Нужно помнить только два формата даты: ’Y-m-d’ и ’d.m.Y’. При этом первый формат универсален, понимается всеми парсерами и правильно пишется в БД, а второй более привычен на письме для русского глаза.

Мои книги