Самый эффективный способ конвертировать дату ISO в метку времени Unix? - PullRequest
2 голосов
/ 27 марта 2009

В моем приложении у меня есть несколько записей, которые мне нужно отфильтровать по некоторым параметрам времени. Для сравнения дат мне нужно преобразовать даты в моих записях (строка в формате YYYY-MM-DD) в метку времени unix (секунды с 1970 года). Поскольку у меня много тысяч записей, я действительно хочу найти наиболее эффективный способ сделать это.

Ответы на другой вопрос предложил сделать это в базе данных (к сожалению, здесь не вариант), используя strtotime() или strptime(), но они не чувствуются как 1008 * Вы знаете, самые эффективные в плане памяти и времени методы?

Учитывая, что я знаю точный формат ввода, возможно, будет лучше использовать какую-либо форму манипуляции со строками (substr или explode) в сочетании с mktime?

Если вы считаете, что я преждевременен в своей оптимизации, тогда просто позабавьте меня, хорошо?

Ответы [ 5 ]

5 голосов
/ 27 марта 2009

Почему вы думаете, что strtotime () неэффективная функция? Вы сделали какие-либо тесты? Имейте в виду, что strtotime () является встроенной библиотечной функцией, которая будет написана непосредственно на C, тогда как все, что вы придумаете, будет выполняться через интерпретатор php.

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

Что касается альтернативного более быстрого метода, я думаю, что использование substr () для анализа будет быстрее, чем регулярное выражение. Подайте результаты в mktime () и все готово.

2 голосов
/ 31 марта 2009

Хорошо, я протестировал 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
2 голосов
/ 27 марта 2009

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);
}
1 голос
/ 27 марта 2009

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

0 голосов
/ 27 марта 2009

Так как строка хорошо построена, я бы построил временную метку, проходя строку слева направо. Вы можете предварительно построить таблицу лет -> секунд, месяцев -> секунд, дней -> секунд и скорректировать на високосные годы. Умножение это зло:)

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...