Это заготовка, я буду ее редактировать! Не спешите срать в каменты. Первое, что должен усвоить новичек, это то, что существуют разные типы данных. Почти любое значение можно преобразовать в строку и наоборот из строки получить значение какого-то типа. PHP очень хорошо умеет работать со строками и обычно неявно преобразует строки в числа и обратно так, что вы даже не догадываетесь. Но с датами случай особый! Запомните, для значений типа "дата" или "дата+время" в PHP используются целые числа! Это число секунд, прошедших с полуночи 1 января 1970г по гринвичскому времени ("дата рождения Unix"). Дата-время в виде числа дает нам массу возможностей: можно прибавлять значения, находить разницу между двумя значениями и корректно сравнивать их на больше-меньше. Со строковой записью даты вы такого проделать не сможете!!! Пример 1: несколько понятных выражений Код (PHP): <?php // получим целое число, соответствующее "сегодня", т.е. 00:00:00 сегодняшней даты $d1 = strtotime('today'); // для отладки выведем как есть echo $d1, "\n"; // выведется большое целое число // узнаем сколько секунд прошло с полуночи echo time() - $d1, "\n"; // выведется не очень большое целое число // получим дату "завтра" $d2 = $d1 + 60*60*24; // сравним даты if ($d1 < $d2) { echo "Сегодня наступает раньше чем завтра\n"; } else { echo "Случился провал во времени\n"; } // наконец мы вычислили всё, что нужно и хотим красиво вывести дату и время на страницу echo date('d.m.Y H:i:s', $d2), "\n"; // что-то вроде '22.11.2014 00:00:00' В базе MySQL тоже используются различные типы, но шлюз между базой и скриптом на PHP устроен так, что вы всегда получаете данные уже сформатированными в строки. Не забывайте об этом и, когда нужно, преобразуйте типы явно! Поясню: Если вы совершили ошибку и для хранения даты завели колонку типа VARCHAR, то там может оказаться, например, такое значение: '20.11.2014 года'. Это геморой, который можно показать на странице, но невозможно как-то использовать в вычислениях/сравнениях ни на стороне БД, ни на стороне PHP! А если вы хороший человек и храните дату в колонке типа DATE, то ваше значение после считывания в PHP будет выглядеть как '2014-11-20'. В текстах по базам данных такой формат называют "ISO date" (см. стандарт ISO 9075 про язык SQL). В MySQL вы можете напрямую работать с такими значениями как с датой. В PHP её распознает strtotime(). Пример 2: MySQL. пусть колонка test.bithday имеет тип DATE. нам надо выбрать все записи пользователей, которые родились не позже чем 7 февраля 2014г (старт Олимпиады в Сочи) Код (Text): SELECT * FROM test WHERE birthday <= '2014-02-07' Пример 3: В PHP вы можете сделать так: Код (PHP): // Дата церемонии открытия $dateX = strtotime('2014-02-07'); // читаем запись из БД как массив строк, например ['id' =>101, 'name'=>'John', 'birthday' => '1992-10-12'] $row = mysqli_fetch_assoc($result); // а теперь у будет настоящая дата, которую можно использовать в вычислениях $row['birthday'] = strtotime($row['birthday']); if ($row['birthday'] > $dateX) { printf("%s слишком молод!\n", $row['name']); } else { printf("%s мог присутствовать.\n", $row['name']); } Не всякая строка может корректно преобразовываться в дату. Например здесь ошибка: Код (PHP): var_dump(strtotime('20.11.2014 года')); // выведет bool(false). ВНЕЗАПНО! Теперь для упертых д*в, которые скажут "мне удобно работать с датой именно в таком виде". Окей, попробуем насколько удобно. Строки ведь можно сравнивать, проверим результат: Код (PHP): if ('12.10.1992' > '07.02.2014') { echo "John слишком молод!\n"; } else { echo "John мог присутствовать.\n"; } Угадайте что выведется? ))) Получается, что день важнее чем год, круто, да?! С американским стандартом m/d/Y было бы тоже весело. Или попробуйте к "дате" '12.10.1992' прибавить один день. Приходит на ум такое: (опять же синтаксической ошибки не будет, поэтому нуб будет долго думать что же пошло не так) Код (PHP): echo '12.10.1992' + 1; // = 13.1 внезапно! Общий совет: следуйте парадигме MVC. Храните данные в базе в колонках с подходящим типом: DATE для даты, DATETIME для даты+время. NUMERIC для денежных величин, VARCHAR или TEXT для настоящих строк. После считывания из базы в PHP, сразу преобразуйте не-строковые данные к нужному типу. В Модели и Контроллере работайте с данными в правильном типе, чтобы все вычисления и преобразования проходили легко и непринужденно. И только при выводе на страницу (то есть в Представлении) форматируйте данные так, как вам хочется их видеть. Пример 4: Код (PHP): <?php // эти данные какбы считаны в mysqli_row() :) то есть изначально это массив строковых значений $row = [ 'name' => 'John', 'start_date' => '2012-02-08', 'amount' => '100.50' ]; // Приводим в рабочий вид: // честная дата $row['start_date'] = strtotime($row['start_date']); // деньги как вещественный тип $row['amount'] = floatval($row['amount']); // Банки считают немного сложнее, но для нашего примера пойдёт: // начислим процент на разницу в годах $today = strtotime('today'); $years = idate('Y', $today) - idate('Y', $row['start_date']); $amountWithPct = $row['amount'] + 0.01 * $years; // Результат красиво выведем printf( "%s открыл счет %s и теперь у него $%.2F", $row['name'], date('d.m.Y', $row['start_date']), $amountWithPct ); ----- Кое-что по русски про типы данных MySQL DATETIME, DATE и TIMESTAMP[/*:m] Mysql Date and Time Functions (english)[/*:m] Популярное на Stackoverflow с тегами php+date (english)[/*:m] Популярное на Stackoverflow с тегами mysql+php+date (english)[/*:m][/list:u]
Обычная ошибка нуба, это то, что php-шная функция date() якобы возвращает текущую дату. На самом деле она возвращает строку и не обязательно по текущей дате — это зависит от аргументов. А текущую дату+время возвращает функция time() !!! Функции, которые возвращают тип дата-время как целое: time, strtotime, mktime, gmmktime, filemtime, filectime, getlastmod Функции, которые использую такую дату как аргумент, а возвращают что-то иное: date, getdate, idate, localtime, strftime. Все они, как date(), допускают краткий вариант с параметром по умолчанию — неявным вызовом time() Справку по любой функции вы можете получить набрав в адресной строке http://php.net/имя_функции (Есть еще прикольные встроенные в PHP классы DateTime и DateInterval. А к ним куча функций-алиасов для краткого обращения к методам. Но я бы не советовал нубам браться за них пока не освоились с классическим Unix timestamp, только мешанина в голове возникнет.) Добавлено спустя 20 минут 12 секунд: Отдельного респекта заслуживает мега-функция strtotime(). С ее помощью можно вычислить многие значения типа дата очень лаконично и наглядно. Чтобы сделать то же самое самостоятельно, вам бы понадобилось немало букв (с возможностью накосячить). Код (PHP): $d1 = strtotime('today'); // "сегодня". отличается от time() тем, что время равно 0. $d2 = strtotime(date('Y-m-1')); // первое число текущего месяца $d3 = strtotime('+1 month', $d2); // первое число следующего месяца $d4 = strtotime('+1 month -1 day', $d2); // последнее число текущего месяца $d5 = strtotime('today next Monday'); // следующий понедельник ВАЖНО: strtotime('01:00:00') означает не время равное 3600 секунд, как может показаться, а дату-время "сегодня в час ночи в текущем часовом поясе", т.е. довольно большое целое число ))) Некоторые полезные преобразования: Код (PHP): $stime24 = date('H:i', strtotime('04:25 PM')); // строку времени с AM/PM превращает в 24ч формат $timediff = strtotime('01:00:00')-strtotime('00:00:00'); // 3600 независимо от даты и часового пояса ссылки на интересные "особенности" дат в php: https://php.ru/forum/threads/php-gljuki.60966/#post-591867 https://php.ru/forum/threads/oshibka-funkcii-vfeu.75040/
artoodetoo, я как раз всё собирался задать вопрос, как кто с датой работает. Хотя явных проблем, как у чела, после поста которого вы это написали, у меня не было, но мне так лениво из ISO переводить дату при выводе всегда... Я себе в модели ActiveRecord ставил перекрытие метода __get(), чтоб поля-даты сразу приводил к нужному виду. Хотя для тех проектов это работало - там ничего с датами делать было не нужно.
ну вобщем-то я уже описал как это у меня. я бы тоже непрочь полениться, но как-то не получается ))) чуть проще выходит там, где вместо истинной даты в базе используется INT, то есть такой неродной для mysql вариант timestamp. тогда преобразования остаются только в представлении, а select и update без конвертации. activerecord я не использую. есть простой dbal - чуть больше удобства чем pdo. преобразования даты не на автомате, а вручную. и сейчас пытаюсь нарабатывать простой datamaper. там уже в методах load и save можно мутить что-то под конкретные поля. я на форуме уже пытался получить фидбек по теме dbal+orm, но как-то незаметно прошло.
Еще пару слов про мега-функцию strtotime. В мире используются несколько стандартов написания даты. Во многих европейских странах и в России принято писать так 05.12.2016 - то есть дд.мм.гггг В США и её приспешниках так 12/05/2016 - то есть мм/дд/гггг а в международные стандарты, в т.ч. по языку SQL, заложено такое написание 2016-12-05 - то есть гггг-мм-дд функция strtotime() распознаёт все эти варианты правильно. то есть она обращает внимание на разделитель между группами цифр и делает вывод о формате Проверка Код (Text): C:\> php -r "var_dump(strtotime('05.12.2016') === strtotime('12/05/2016'));" bool(true)
1 день не всегда равен 86400 секунд демонстрация проблемы: https://gist.github.com/artoodetoo/2915dc07d1904a173e76f0bf5966e00f в Москве '2018-10-06 10:00:00' + 24*60*60 == '2018-10-07 10:00:00' время дня осталось то же самое в Мельбурне '2018-10-06 10:00:00' + 24*60*60 == '2018-10-07 11:00:00' время изменилось Решение: strtotime('+1 day', $ts) учитывает возможную смену летнего/зимнего времени. Надо только не забыть установить временну́ю зону. Класс DateTime (и производный от него Carbon) тоже учитывает временну́ю зону и DST.
Храните данные в базе в колонках с подходящим типом: DATE для даты, DATETIME да да да, а потом этот гамнокод не сравнивается с функцией date текущей датой в запросе к БД