В моем приложении у меня есть некоторые записи, которые мне нужно фильтровать на основе некоторых временных параметров. Чтобы сравнить даты, мне нужно преобразовать даты в моих записях (строку в формате YYYY-MM-DD), в временную метку unix (в секундах с 1970 года). Поскольку у меня много тысяч записей, я действительно хочу найти наиболее эффективный способ сделать это.
Ответы на другой вопрос предлагали сделать это в базе данных (не вариант здесь, к сожалению), используя strtotime()
или strptime()
, но они не чувствуют себя наиболее эффективными с точки зрения памяти и времени методами, вы знаете?
Учитывая, что я знаю точный формат ввода, возможно, с использованием какой-либо формы манипуляции с строкой ( substr
или explode
) в сочетании с mktime
будет лучше?
Если вы считаете, что я преждевременно в своей оптимизации, то просто настройте на меня юмор?
Как вы думаете, почему strtotime () не является эффективной функцией? Вы сделали какие-то тесты. Имейте в виду, что strtotime () является встроенной библиотечной функцией, которая будет написана непосредственно на C, тогда как все, что вы придете, будет проходить через PHP-интерпретатор.
Также имейте в виду, что расчеты по дате по своей сути сложны, делайте это по видам лет и времени.
Что касается альтернативного более быстрого метода, я думаю, что использование substr () для синтаксического анализа будет быстрее, чем регулярное выражение. Добавьте результаты в mktime (), и вы установите.
strtotime
– это путь (и я имею в виду WAAAY) быстрее, чем все, что вы можете придумать.
Насколько вероятны даты в вашей записи? Если они не будут полностью уникальными, вы можете сделать какое-то кэширование. Предполагая, что вы в классе:
protected $_timestamps = array(); public function toTimestamp($date) { if (!array_key_exists($date, $this->_timestamps)) { $this->_timestamps[$date] = strtotime($date); } return $this->_timestamps[$date]; }
Теперь вам просто нужно сделать:
foreach ($records as $record) { $timestamp = $this->toTimestamp($record->date); }
Хорошо, я сравнивал 4 разных метода:
function _strtotime($date) { return strtotime($date); } function _preg($date) { preg_match("@^(\\d+)-(\\d\\d)-(\\d\\d)$@", $date, $matches); return mktime(0, 0, 0, $matches[2], $matches[3], $matches[1]); } function _explode($date) { list($y,$m,$d) = explode("-", $date); return mktime(0, 0, 0, $m, $d, $y); } function _substr($date) { $y = substr($date, 0, 4); $m = substr($date, 5, 2); $d = substr($date, 8); return mktime(0, 0, 0, $m, $d, $y); } // I also added this one as sort of a "control" function _hardCoded() { return mktime(0, 0, 0, 3, 31, 2009); }
И вот результаты каждой функции 100 000 раз. С вводом «2009-03-31»
_hardCoded: 2.02547 _strtotime: 2.35341 _preg: 2.70448 _explode: 2.31173 _substr: 2.27883
Мне кажется, что, если вы действительно хотите наиболее эффективный способ сделать это, вам придется сделать все, что вы предложили, плюс любые другие, которые вы найдете, провести некоторые бенчмаркинга и выбрать победителя.
Поскольку строка красиво наращивается, я бы построил временную метку, идущую по строке слева направо. Вы можете предварительно построить таблицу лет -> секунд, месяцев -> секунд, дней -> секунд и исправить для високосных лет. Умножение зла 🙂
Или с меньшими усилиями создайте хэш-таблицу, чтобы устранить дубликаты.
Но для этого вам потребуется много записей, чтобы быть быстрее. И, похоже, вы используете базу данных. Это несовместимо с быстрым …