Статьи

Анализ даты ISO

Пятая статья в серии функций 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. Эти функции оказываются полезными, особенно в тех старых и капризных браузерах, которые мы бы лучше забыли!