У кого-нибудь есть хороший шаблон регулярного выражения для сопоставления времени iso?
ie: 2010-06-15T00: 00: 00
У кого-нибудь есть хороший шаблон регулярного выражения для сопоставления времени iso?
ie: 2010-06-15T00: 00: 00
Для строгого, полного datetime, включая миллисекунды, за W3C возьмет спецификацию.:
//-- Complete precision:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/
//-- No milliseconds:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)/
//-- No Seconds:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)/
//-- Putting it all together:
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/
.
Дополнительные изменения, разрешенные фактическим ISO 8601: 2004 (E) doc:
/********************************************
** No time-zone varients:
*/
//-- Complete precision:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+/
//-- No milliseconds:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d/
//-- No Seconds:
/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d/
//-- Putting it all together:
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d)/
ПРЕДУПРЕЖДЕНИЕ: все это становится беспорядочно быстрым, и еще допускает определенную ерунду, такую как 14-й месяц. Кроме того, ISO 8601: 2004 (E) допускает несколько других вариантов.
. "2010-06-15T00: 00: 00" не является законным, потому что у него нет обозначения часового пояса.
Вот регулярное выражение для проверки формата ISO 8601 date, включая високосные годы и короткие месяцы. Чтобы запустить это, вам нужно "игнорировать пустое пространство". Компактная версия без белого пространства находится в regexlib: http://regexlib.com/REDetails.aspx?regexp_id=3344
Там больше по ISO 8601 - это регулярное выражение заботится только о датах, но вы можете легко расширить его, чтобы поддерживать проверку времени, которая не так сложна.
Обновление: теперь это работает с javascript (без lookbehinds)
^(?:
(?=
[02468][048]00
|[13579][26]00
|[0-9][0-9]0[48]
|[0-9][0-9][2468][048]
|[0-9][0-9][13579][26]
)
\d{4}
(?:
(-|)
(?:
(?:
00[1-9]
|0[1-9][0-9]
|[1-2][0-9][0-9]
|3[0-5][0-9]
|36[0-6]
)
|
(?:01|03|05|07|08|10|12)
(?:
\1
(?:0[1-9]|[12][0-9]|3[01])
)?
|
(?:04|06|09|11)
(?:
\1
(?:0[1-9]|[12][0-9]|30)
)?
|
02
(?:
\1
(?:0[1-9]|[12][0-9])
)?
|
W(?:0[1-9]|[1-4][0-9]|5[0-3])
(?:
\1
[1-7]
)?
)
)?
)$
|
^(?:
(?!
[02468][048]00
|[13579][26]00
|[0-9][0-9]0[48]
|[0-9][0-9][2468][048]
|[0-9][0-9][13579][26]
)
\d{4}
(?:
(-|)
(?:
(?:
00[1-9]
|0[1-9][0-9]
|[1-2][0-9][0-9]
|3[0-5][0-9]
|36[0-5]
)
|
(?:01|03|05|07|08|10|12)
(?:
\2
(?:0[1-9]|[12][0-9]|3[01])
)?
|
(?:04|06|09|11)
(?:
\2
(?:0[1-9]|[12][0-9]|30)
)?
|
(?:02)
(?:
\2
(?:0[1-9]|1[0-9]|2[0-8])
)?
|
W(?:0[1-9]|[1-4][0-9]|5[0-3])
(?:
\2
[1-7]
)?
)
)?
)$
Чтобы удовлетворить время, добавьте что-то подобное в смесь (от: http://underground.infovark.com/2008/07/22/iso-date-validation-regex/):
([T\s](([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)?(\15([0-5]\d))?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?
Спецификация ISO 8601 позволяет использовать самые разные форматы даты. Там посредственное объяснение, как это сделать здесь. Существует довольно небольшое расхождение между тем, как форматирование ввода даты в формате Javascript и форматирование ISO для простых дат, которые не определяют часовые пояса, и его можно легко смягчить, используя строку замена. Полная поддержка спецификации ISO-8601 является нетривиальной.
Вот ссылочный пример, который я не гарантирую, чтобы быть полным, хотя он анализирует даты несрочности с вышеупомянутой страницы Википедии.
Ниже приведен пример, и вы также можете увидеть его вывод на ideone. К сожалению, он не работает для спецификации, поскольку он не выполняет целые недели. Определение номера недели 01 в ISO-8601 является нетривиальным и требует некоторого просмотра календаря, чтобы определить, где начинается первая неделя, и что именно это означает с точки зрения количества дней в указанном году. Это, вероятно, можно довольно легко исправить (я просто устал от игры с ним).
function parseISODate (input) {
var iso = /^(\d{4})(?:-?W(\d+)(?:-?(\d+)D?)?|(?:-(\d+))?-(\d+))(?:[T ](\d+):(\d+)(?::(\d+)(?:\.(\d+))?)?)?(?:Z(-?\d*))?$/;
var parts = input.match(iso);
if (parts == null) {
throw new Error("Invalid Date");
}
var year = Number(parts[1]);
if (typeof parts[2] != "undefined") {
/* Convert weeks to days, months 0 */
var weeks = Number(parts[2]) - 1;
var days = Number(parts[3]);
if (typeof days == "undefined") {
days = 0;
}
days += weeks * 7;
var months = 0;
}
else {
if (typeof parts[4] != "undefined") {
var months = Number(parts[4]) - 1;
}
else {
/* it an ordinal date... */
var months = 0;
}
var days = Number(parts[5]);
}
if (typeof parts[6] != "undefined" &&
typeof parts[7] != "undefined")
{
var hours = Number(parts[6]);
var minutes = Number(parts[7]);
if (typeof parts[8] != "undefined") {
var seconds = Number(parts[8]);
if (typeof parts[9] != "undefined") {
var fractional = Number(parts[9]);
var milliseconds = fractional / 100;
}
else {
var milliseconds = 0
}
}
else {
var seconds = 0;
var milliseconds = 0;
}
}
else {
var hours = 0;
var minutes = 0;
var seconds = 0;
var fractional = 0;
var milliseconds = 0;
}
if (typeof parts[10] != "undefined") {
/* Timezone adjustment, offset the minutes appropriately */
var localzone = -(new Date().getTimezoneOffset());
var timezone = parts[10] * 60;
minutes = Number(minutes) + (timezone - localzone);
}
return new Date(year, months, days, hours, minutes, seconds, milliseconds);
}
print(parseISODate("2010-06-29T15:33:00Z-7"))
print(parseISODate("2010-06-29 06:14Z"))
print(parseISODate("2010-06-29T06:14Z"))
print(parseISODate("2010-06-29T06:14:30.2034Z"))
print(parseISODate("2010-W26-2"))
print(parseISODate("2010-180"))
Я переработал верхний ответ во что-то более сжатое. Вместо того, чтобы записывать каждый из трех необязательных шаблонов, элементы вставляются в качестве необязательных операторов.
/[+-]?\d{4}(-[01]\d(-[0-3]\d(T[0-2]\d:[0-5]\d:?([0-5]\d(\.\d+)?)?[+-][0-2]\d:[0-5]\dZ?)?)?)?/
Мне любопытно, есть ли недостатки в этом подходе?
Вы можете найти тесты для моего предлагаемого ответа здесь: http://regexr.com/3e0lh
Для сопоставления только даты ISO, например 2017-09-22, вы можете использовать это регулярное выражение:
^\d{4}-([0]\d|1[0-2])-([0-2]\d|3[01])$
Он будет соответствовать любому числовому году, любому месяцу, указанному двумя цифрами в диапазоне 00-12, и любой дате, указанной двумя цифрами в диапазоне 00-31
Не уверен, что это относится к основной проблеме, которую вы пытаетесь решить, но вы можете передать строку даты ISO как конструктор arg в Date() и получить объект из него. Конструктор на самом деле очень гибкий с точки зрения принудительного ввода строки в Date.