誰かがiso日時を一致させるための良い正規表現パターンを持っていますか?
すなわち:2010-06-15T00:00:00
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 の日付形式を確認するための正規表現を次に示します。これを実行するには、「空白を無視する」必要があります。空白のない圧縮バージョンは regexlib にあります: http://regexlib.com/REDetails.aspx?regexp_id=3344
ISO 8601 には他にもあります。この正規表現は日付のみを扱いますが、時間の検証をサポートするように簡単に拡張できますが、これはそれほど難しいことではありません。
更新: これは javascript で動作するようになりました (後読みなし)
^(?:
(?=
[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 での出力も確認できます。残念ながら、週を適切に実装していないため、仕様どおりには機能しません。ISO-8601 の週番号 01 の定義は重要であり、カレンダーをブラウジングして、週 1 がどこから始まるか、指定された年の日数に関して正確に何を意味するかを判断する必要があります。これはおそらくかなり簡単に修正できます (私はそれで遊ぶのにうんざりしています)。
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"))
ここでのほとんどの回答の説明が多すぎます。これは、いくつかの奇妙なシナリオ(のような)に対処する@Sergeyの回答の短いバリエーションです。これは日付のみを気にします:2020-00-00
RegExp
yyyy-MM-dd
// yyyy-MM-dd
^\d{4}-([0][1-9]|1[0-2])-([0-2][1-9]|[1-3]0|3[01])$
また、これは 1 か月あたりの日数を気にしません2020-11-31
(11 月は 30 日しかないため)。
私のユースケースはString
a をDate
( API
param から) に変換することで、入力文字列に奇妙なものが含まれていないことを知るだけでよかったので、実際のDate
オブジェクトに対して次の検証を行います。
解決しようとしている根本的な問題に関連しているかどうかはわかりませんが、ISO 日付文字列をコンストラクタ引数として Date() に渡し、そこからオブジェクトを取得できます。コンストラクターは、文字列を日付に変換するという点で、実際には非常に柔軟です。
ブロックスの回答は適切ですが、一致させようとしているのが日付文字列のみの場合は、接頭辞/接尾辞を許可しないように、^ で始まり $ で終わる必要があります。