Самый эффективный способ преобразования даты ISO в временную метку Unix?

В моем приложении у меня есть некоторые записи, которые мне нужно фильтровать на основе некоторых временных параметров. Чтобы сравнить даты, мне нужно преобразовать даты в моих записях (строку в формате 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 

Мне кажется, что, если вы действительно хотите наиболее эффективный способ сделать это, вам придется сделать все, что вы предложили, плюс любые другие, которые вы найдете, провести некоторые бенчмаркинга и выбрать победителя.

Поскольку строка красиво наращивается, я бы построил временную метку, идущую по строке слева направо. Вы можете предварительно построить таблицу лет -> секунд, месяцев -> секунд, дней -> секунд и исправить для високосных лет. Умножение зла 🙂

Или с меньшими усилиями создайте хэш-таблицу, чтобы устранить дубликаты.

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