Пятая статья в серии функций small-and-sweet — продолжение предыдущей статьи, в которой была показана простая функция создания меток даты ISO . В предыдущей статье отмечалось, что этот формат не поддерживается некоторыми старыми браузерами в качестве входных данных для конструктора Date
. Эта статья покажет вам обратную функцию, которая анализирует метки даты ISO для создания метки времени Unix, что может быть даже понято в IE6!
Код для timestamp()
показан ниже.
function timestamp(datestamp) { var pattern = /^([\d]{4})\-([\d]{2})\-([\d]{2})T([\d]{2}):([\d]{2}):([\d]{2})(Z|(?:[+\-][\d]{2}[:]?[\d]{2}))$/; if(!pattern.test(datestamp)) { return null; } var components = [], zoneoffset = 0; datestamp.replace(pattern, function(a,y,m,d,h,i,s,z) { for(var bits = [y,m,d,h,i,s], i = 0; i < 6; i ++) { components[i] = parseInt(bits[i], 10); } components[1]--; if(z !== 'Z') { zoneoffset = ( ( (parseInt((z = z.replace(':', '')).substr(1,2), 10) * 3600) + (parseInt(z.substr(3,4), 10) * 60) ) * (z.charAt(0) == '-' ? 1000 : -1000) ); } }); return Date.UTC.apply(Date, components) + zoneoffset; }
времениfunction timestamp(datestamp) { var pattern = /^([\d]{4})\-([\d]{2})\-([\d]{2})T([\d]{2}):([\d]{2}):([\d]{2})(Z|(?:[+\-][\d]{2}[:]?[\d]{2}))$/; if(!pattern.test(datestamp)) { return null; } var components = [], zoneoffset = 0; datestamp.replace(pattern, function(a,y,m,d,h,i,s,z) { for(var bits = [y,m,d,h,i,s], i = 0; i < 6; i ++) { components[i] = parseInt(bits[i], 10); } components[1]--; if(z !== 'Z') { zoneoffset = ( ( (parseInt((z = z.replace(':', '')).substr(1,2), 10) * 3600) + (parseInt(z.substr(3,4), 10) * 60) ) * (z.charAt(0) == '-' ? 1000 : -1000) ); } }); return Date.UTC.apply(Date, components) + zoneoffset; }
Что делает функция
Функция timestamp()
берет timestamp()
даты ISO 8601 , такую как "2012-12-06T04:19:27+00:00"
, и преобразует ее в метку времени Unix — количество миллисекунд с момента времени UTC, которое в этом примере будет 1354767567000
. Целое число метки времени точно такое же, как и у Date.getTime()
, и в большинстве современных браузеров мы можем Date.getTime()
от одного к другому следующим образом:
new Date("2012-12-06T04:19:27+00:00").getTime();
Однако это не поддерживается некоторыми более старыми браузерами — особенно IE8 или более ранними, но также и Safari 3. Функция timestamp()
заполняет этот пробел, обеспечивая промежуточное преобразование, которое работает в более старых браузерах. Всякий раз, когда вам нужно проанализировать timestamp()
Date
ISO как Date
, вы просто сначала пропускаете ее через функцию timestamp()
, как показано ниже.
new Date(timestamp("2012-12-06T04:19:27+00:00"));
Как работает функция
Функция timestamp()
использует статический метод Date.UTC()
, который принимает в качестве входных данных набор числовых компонентов даты, например:
Date.UTC(2012, 11, 6, 4, 19, 27);
По сути, все, что нам нужно сделать, это разделить метку даты на эти компоненты, а затем передать их все в Date.UTC()
, и мы получим метку времени Unix. Однако это не так просто!
Начнем с того, что отметка даты проверяется с помощью простого регулярного выражения. Это могло бы быть более точным, но более простые выражения дешевле анализировать, и мы обычно можем предположить, что формат ввода будет либо точным, либо вообще не указывать дату в формате ISO. Тем не менее, если вы передадите метку даты с крайне неточными значениями, браузер все равно будет обрабатывать их с апломбом. Например, если вы укажете дату "2012-26-00"
она будет считаться 31 января 2014 года — добавив год и два месяца для месяца "26"
, а затем вычтя день для даты "00"
.
Если timestamp()
даты не проходит проверку, функция timestamp()
возвращает null
. В противном случае он продолжает разбивать метку даты на составляющие ее целые числа. Это делается с помощью замены строки обратным вызовом, который является мощным способом анализа строк. В функцию обратного вызова передается набор аргументов, соответствующих совпадениям регулярных выражений — один для общего соответствия, а затем один для каждой из обратных ссылок. В обратном вызове мы анализируем эти значения в целые числа и сохраняем их в массив. Для значений месяца мы также должны уменьшить значение на единицу, потому что числа месяцев JavaScript варьируются от 0
до 11
, где мы вводим от "01"
до "12"
.
Затем мы анализируем указатель часового пояса, который может быть "Z"
для "-0600"
UTC, или это может быть смещение типа "+10:00"
или "-0600"
. Смещение преобразуется в целое число в секундах, а затем снова преобразуется в положительные или отрицательные миллисекунды, в зависимости от того, в каком направлении идет смещение.
Наконец, мы передаем целые числа компонента в Date.UTC()
, затем добавляем смещение часового пояса к возвращаемому значению. Метод UTC()
предполагает, что его входные компоненты уже имеют формат UTC, поэтому мы должны добавить смещение часового пояса для компенсации значения. apply()
используется для вызова метода UTC()
, потому что он позволяет массиву components
передаваться как один аргумент.
Вывод
Функции timestamp()
и datestamp()
являются бесценным дополнением к инструментарию JavaScripter, предоставляя возможность создавать и анализировать вездесущий формат ISO. Эти функции оказываются полезными, особенно в тех старых и капризных браузерах, которые мы бы лучше забыли!