Так как вы управляете интерфейсом ввода, без ограничения общности мы можем предположить, что будут отдельные целые числа года / месяца / дня (правильная проверка для ... целочисленного значения :). Скажем, этот год будет отрицательным для обозначения БК.
Итак, прежде всего ... очевидный (частичный) ответ: checkdate () . Это хорошо для лет> = 1, как сказано в документации к функции.
Поэтому вы застряли с проблемой того, что делать, если год <= 0. </p>
Давайте сделаем side-trek здесь и посмотрим, почему это может быть БОЛЬШОЙ проблемой ...
Согласно ссылке на Википедию выше, юлианский календарь вступил в силу в 45 г. до н. Этот календарь для всех практических целей идентичен григорианскому календарю, который мы используем сегодня. Разница в том, что между ними существует десятидневное смещение; последний день юлианского календаря был четверг, 4 октября 1582 года, после чего последовал первый день григорианского календаря, пятница, 15 октября 1582 года (цикл рабочих дней не был затронут).
Это уже означает, что даты в диапазоне от 5 октября 1582 до 14 октября 1582 (включительно) недействительны , если вы следуете григорианскому календарю ; их никогда не было.
Возвращаясь оттуда, вы хороши до 45 г. до н. Начиная с 46 г. до н. Э. Вместо юлианского использовался римский календарь .
Я не собираюсь вдаваться в этот беспорядок здесь, но просто упомяну, что, поскольку этот календарь сильно отличался от григорианского, ваши пользователи не будут готовы увидеть «форму ввода даты римского календаря». Я предлагаю лучше сделать ваше приложение пригодным для использования, чем технически правильным.
Если можно предположить, что никто в здравом уме не будет на самом деле знать дату до нашей эры или знать, как правильно ее указать, даже если они и сделали, вы можете произвольно предположить, что все даты до нашей эры имеют форму 1 / 1 ГОД. Поэтому ваш интерфейс может отключить элементы управления месяц / день, если установлен флажок «BC», иметь отдельные групповые поля для BC и AD или что-либо еще подходящее.
Единственная остающаяся проблема после всего этого, на мой взгляд, это проверка дат високосных лет. Они были введены с юлианским календарем, но на самом деле не были правильно реализованы до 8 н. Э. .
Последняя ссылка выше подтверждает, что в течение 45 г. до н.э. - 4 г. н.э. (включительно) високосные годы не были правильно рассчитаны. Функция скачка на год, которая учитывает это несоответствие, плюс переключатель julian / gregorian будет:
define('YEAR_JULIAN_CALENDAR_INTRODUCED', -45);
define('YEAR_JULIAN_CALENDAR_LEAP_IMPLEMENTED_CORRECTLY', 8);
define('YEAR_GREGORIAN_CALENDAR_INTRODUCED', 1582);
function is_leap_year($year) {
if($year < YEAR_JULIAN_CALENDAR_INTRODUCED) {
return false; // or good luck :)
}
if($year < YEAR_JULIAN_CALENDAR_LEAP_IMPLEMENTED_CORRECTLY) {
return $year <= -9 && $year % 3 == 0;
}
if($year < YEAR_GREGORIAN_CALENDAR_INTRODUCED) {
return $year % 4 == 0;
}
// Otherwise, Gregorian is in effect
return $year % 4 == 0 && ($year % 100 != 0 || $year % 400 == 0);
}
Вооружившись этим, вы могли бы написать функцию, которая правильно сообщает вам, сколько дней в году. Тогда на этом можно построить вычитание / сложение даты.
После всего этого обсуждения (я восхищаюсь мужеством любого, кто прочитал это далеко :) Я должен спросить:
Сколько точности вам на самом деле нужно?
Если вы решите, что вам нужно разбираться в «технических деталях», я лично реализовал бы функции, упомянутые выше, а затем: а) использовал бы их в качестве моей библиотеки дат ручной работы или б) использовал их для проверки Интересующая меня сторонняя библиотека действительно реализована правильно .
Если вам не нужно этого делать, просто притворитесь, что вы никогда не читали все это. :)