strtotime () считается вредным? - PullRequest
10 голосов
/ 13 марта 2011

Кажется, что многие люди борются с проблемами даты / времени в PHP, и неизбежно, многие из принятых ответов имеют тенденцию быть " Использовать strtotime таким образом ."

Действительно ли это лучший способ направлять людей, имеющих дело со свиданиями? Я начинаю чувствовать, что strtotime - это изящный трюк, на который не обязательно полагаться при важных вычислениях даты и времени, и по своей природе он принимает произвольные строки, кажется, что это потенциальный источник ошибок, трудно предсказуемое поведение. Его неспособность провести различие между ММ / ДД / ГГГГ и ДД / ММ / ГГГГ является чем-то большим, не так ли?

StackOverflow обычно очень хорош в продвижении хороших практик (я редко вижу разговор mysql_real_escape_string, в котором не говорится, что кто-то говорит: «Используйте вместо этого PDO»)

Но, похоже, не существует общепринятой нормы в отношении проблем с датами в PHP, так как многие люди обращаются к костылю strtotime.

Итак, что мы должны делать с этим, если вообще что-то делать? Есть ли лучшая норма, которую мы должны соблюдать для людей, задающих вопросы типа «Как добавить 1 неделю в X» или «Как преобразовать этот формат даты в этот другой формат даты?»

Какой самый лучший и самый надежный способ справиться с проблемами даты / времени, как strtotime пытается, но слишком часто терпит неудачу?

Ответы [ 7 ]

19 голосов
/ 18 марта 2011

Начну с того, что я большой сторонник использования объекта DateTime, который позволяет вам использовать функцию DateTime::createFromFormat().Объект DateTime делает код намного более читабельным и избавляет от необходимости делать всю модификацию метки времени Unix, используя 60 * 60 * 24 для продвижения дней даты.

При этом произвольная строка, которую принимает strtotime ()не очень сложно предсказать. Поддерживаемые форматы даты и времени содержит список поддерживаемых форматов.

В соответствии с вашим примером неспособности провести различие между MM / DD / YYYY и DD / MM / YYYY, он различает на основев форматах даты .Даты, которые используют косую черту, всегда читаются как американский формат.Таким образом, дата в формате 00/00/0000 всегда будет читаться как ММ / ДД / ГГГГ.Альтернативно использование тире или точек будет DMY.например, 00-00-0000 всегда будет читаться как ДД-ММ-ГГГГ.

Вот несколько примеров:

<?php
$dates = array(
    // MM DD YYYY
    '11/12/2013' => strtotime('2013-11-12'),
    // Using 0 goes to the previous month
    '0/12/2013' => strtotime('2012-12-12'), 
    // 31st of November (30 days) goes to 1st December
    '11/31/2013' => strtotime('2013-12-01'), 
    // There isn't a 25th month... expect false
    '25/12/2013' => false,

    // DD MM YYYY
    '11-12-2013' => strtotime('2013-12-11'),
    '11.12.2013' => strtotime('2013-12-11'),
    '31.12.2013' => strtotime('2013-12-31'),
    // There isn't a 25th month expect false
    '12.25.2013' => false,
);

foreach($dates as $date => $expected) {
    assert(strtotime($date) == $expected);
}

Как видите, несколько ключевых примеров: 25/12/2013и 12.25.2013, которые оба были бы действительны, если считывать в противоположном формате, однако они возвращают false, поскольку они недопустимы в соответствии с поддерживаемыми форматами даты и времени ...

Так что, как видите, поведение вполне предсказуемо.Как всегда, если вы получаете дату от ввода данных, вы должны сначала проверить эти данные.Никакой метод не сработает, если вы сначала не проверяете ввод.

Если вы хотите быть очень точным в отношении читаемой даты, или заданный вами формат не поддерживается, то я рекомендую использоватьDateTime::createFromFormat().

8 голосов
/ 13 марта 2011

strtotime() предлагается, потому что он был в PHP со времен v4.x, поэтому в основном гарантированно будет доступен. Доступность превосходит нечетное время (без каламбура), когда оно обернется и укусит вас в задницу с неправильно проанализированной датой.

В настоящее время «правильным» способом вычисления даты будет использование объектов DateTime / DateInterval, но это более недавние дополнения к PHP (я думаю, 5.2 / 5.3), и поэтому они не всегда доступны - существует множество хостов. все еще на 4.x.

2 голосов
/ 13 марта 2011

Я часто использую strtotime().Дело в том, что вы не должны использовать его в качестве костыля, но вы должны знать о его ограничениях.

Если вы хотите применить стандарт, то я полагаю, вам следует использовать основанный на c mktime(),Например, чтобы получить 1 неделю спустя:

date('Y-m-d', mktime(0, 0, 0, date('n'), date('j') + 7);
0 голосов
/ 19 апреля 2013

Это, конечно, возможно в PHP: проверьте руководство strtotime, особенно этот комментарий .

Если у вас есть доступное соединение MySQL, SELECT DATE_ADD ('2011-05-31', INTERVAL 1 MONTH) будет менее избыточным, поскольку (правильная) функциональность уже реализована без необходимости ее самостоятельной реализации.

0 голосов
/ 19 марта 2011

Проблема в том, что вы должны выбрать строгий формат данных для ваших значений даты / времени / зоны (ISO8601: 2004) во всех слоях вашего приложения и найти функцию PHP, которая лучше всего обрабатывает этот формат, а именно: DateTime::createFromFormat().

ИМХО с разными форматами даты / времени / зоны предназначен для пользовательского интерфейса (уровень GUI), попытка угадать ввод даты в функции PHP означает, что вы не выполняли никакой очистки ваших данных на стороне клиента(возможно, с использованием Javascript?), и вы переносите данные из веб-формы в неизвестном формате.

Если формат даты / времени / зоны не соответствует ISO8601 на стороне сервера, вы просто отклоняете его,et voilà!

Надеюсь, это поможет!

0 голосов
/ 18 марта 2011

Самый надежный способ вычисления даты в PHP - использование временной метки.

Это правда, что оно ограничено 32-битным целым числом, но использование объекта Date не является опцией при вводе некоторых странных символов.окружение, как, например, PHP 4.

Чтобы быть уверенным в том, что вы получаете наиболее правильное поведение, я бы предложил использовать strptime(), чтобы получить метку времени из читаемой человеком даты.Это лучше, чем strtotime() и strftime(), потому что он не пытается угадать, какой формат даты, а скорее использует предоставленный вами формат даты.

После того, как вы получили правильную метку времени, вы можетеиспользуйте несколько методов в PHP, чтобы выполнить работу.

ОБНОВЛЕНИЕ: Для PHP> = 5.3 date_parse_from_format () следует использовать вместо этого.Примечание. strptime() может вести себя по-разному в разных операционных системах, поскольку полагается на strptime(), предоставляемый системной библиотекой C.

0 голосов
/ 18 марта 2011

Дерек Ретанс выступил на Froscon 2010 с докладом на тему «Расширенная обработка даты и времени в PHP» .

Найдите слайды в формате PDF на http://derickrethans.nl/talks/time-froscon10.pdf. Они основаны на недавнем PHP (5.2 и выше), использование которого также должно быть наилучшей практикой.

...