у кого-либо есть хороший regex шаблон для соответствия ISO datetimes?
т.е.: 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) :
/********************************************
** 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 в качестве аргумента конструктора в Date () и получить из нее объект. Конструктор на самом деле очень гибкий с точки зрения преобразования строки в Date.
Спецификация 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's 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"))