IE8およびSafari 5でISO-8601の日付「2011-04-26T13:16:50Z」を解析できませんでしたが、Chrome 10、FF4で動作しました。サポートはかなり混ざっているようです。 ?
どのブラウザがこの形式を解析できるかについて、実際のステータスを知っている人はいますか? IE6と7も失敗すると思います。
var d = Date.parse("2011-04-26T13:16:50Z");
今日はこの問題がありました。 momentjs は、クロスブラウザマナーでISO 8601日付を解析する良い方法であることがわかりました。
momentjsを使用して、異なる形式で日付を出力することもできます。
いくつかのテストで必要な場合にのみシムと言います。
ここに私がすでに書いたものがあります:
_(function() {
var d = window.Date,
regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,3})(?:Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/;
if (d.parse('2011-11-29T15:52:30.5') !== 1322581950500 ||
d.parse('2011-11-29T15:52:30.52') !== 1322581950520 ||
d.parse('2011-11-29T15:52:18.867') !== 1322581938867 ||
d.parse('2011-11-29T15:52:18.867Z') !== 1322581938867 ||
d.parse('2011-11-29T15:52:18.867-03:30') !== 1322594538867 ||
d.parse('2011-11-29') !== 1322524800000 ||
d.parse('2011-11') !== 1320105600000 ||
d.parse('2011') !== 1293840000000) {
d.__parse = d.parse;
d.parse = function(v) {
var m = regexIso8601.exec(v);
if (m) {
return Date.UTC(
m[1],
(m[2] || 1) - 1,
m[3] || 1,
m[4] - (m[8] ? m[8] + m[9] : 0) || 0,
m[5] - (m[8] ? m[8] + m[10] : 0) || 0,
m[6] || 0,
((m[7] || 0) + '00').substr(0, 3)
);
}
return d.__parse.apply(this, arguments);
};
}
d.__fromString = d.fromString;
d.fromString = function(v) {
if (!d.__fromString || regexIso8601.test(v)) {
return new d(d.parse(v));
}
return d.__fromString.apply(this, arguments);
};
})();
_
そして、あなたのコードでは、常にDate.fromString(...)
の代わりにnew Date(...)
を使うだけです
シムが使用されるかどうかをブラウザでテストします:
http://jsbin.com/efivib/1/edit
すべての主要なブラウザで動作し、これらの参照を使用しました:
http://dev.w3.org/html5/spec/common-microsyntaxes.html
http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
http://msdn.Microsoft.com/en-us/library/windows/apps/ff743760(v = vs.94).aspx
http://msdn.Microsoft.com/en-us/library/windows/apps/wz6stk2z(v = vs.94).aspx
http://msdn.Microsoft.com/en-us/library/windows/apps/k4w173wk(v = vs.94).aspx
!-Microsoft Connectを表示するには、ログインが必要です。
IE9は3以外の桁数でミリ秒単位で失敗していました(IE10で修正済み) https://connect.Microsoft.com/IE/feedback/details/723740/date-parse-and-new-date-fail -on-valid-formats
IE10は、タイムゾーンが省略された場合(ECMAによれば、ローカルではなくZまたはUTCにデファルトする必要があります)、まだ(2013年1月17日現在)失敗しています: https://connect.Microsoft.com/ IE/feedback/details/776783/date-parse-and-new-date-fail-on-valid-formats
-標準が現在どこにあるのか、将来どこに行くのか、そしてIEチームがIE10の実装が技術的に正しくありません:
ECMAScript-262 v6.0は、「タイムゾーンインジケータが省略されている場合、現地時間を想定する」のiso8601準拠バージョンに少し移行する予定です。したがって、矛盾、この実装、クロム、モバイルサファリ、operaはすべてECMAScript-262 v5.1に準拠していますが、IE10、firefox、デスクトップサファリはすべてiso8601準拠のECMAScript-262 v6.0仕様に準拠しているようです。これは控えめに言ってもわかりにくいです。 chromeまたはモバイルサファリがトリガーを引いてES6実装に移行するとき、この実装はES5.1を少数のままにしていくべきだと思います。これはバージョン5.1の「正誤表」に記載されていますが、見つかりませんでした。私はまだES6でトリガーを引くのは少し早いという意見の方が多いですが、コードは実用的で理想的ではなく、ブラウザメーカーが移動する場所に移動する必要があるという意見もあります。とはいえ、現時点では50/50の決定であるように思われるため、以下にこのコードの「将来」バージョンを示します。
また、どちらのバージョンのコードも、「非準拠」ブラウザーを正規化して、他のブラウザーの動作に一致させることを言及する必要があります。
ここIS ECMAScript-262 v6.0(JavaScript Future)と互換性のある適応バージョン
関連セクションを参照してください:(これは私が見つけることができる仕様の唯一のオンラインhtmlバージョンです) http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.9.1.15 =
_(function() {
var d = window.Date,
regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})\.(\d{1,})(Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/,
lOff, lHrs, lMin;
if (d.parse('2011-11-29T15:52:30.5') !== 1322599950500 ||
d.parse('2011-11-29T15:52:30.52') !== 1322599950520 ||
d.parse('2011-11-29T15:52:18.867') !== 1322599938867 ||
d.parse('2011-11-29T15:52:18.867Z') !== 1322581938867 ||
d.parse('2011-11-29T15:52:18.867-03:30') !== 1322594538867 ||
d.parse('2011-11-29') !== 1322524800000 ||
d.parse('2011-11') !== 1320105600000 ||
d.parse('2011') !== 1293840000000) {
d.__parse = d.parse;
lOff = -(new Date().getTimezoneOffset());
lHrs = Math.floor(lOff / 60);
lMin = lOff % 60;
d.parse = function(v) {
var m = regexIso8601.exec(v);
if (m) {
return Date.UTC(
m[1],
(m[2] || 1) - 1,
m[3] || 1,
m[4] - (m[8] ? m[9] ? m[9] + m[10] : 0 : lHrs) || 0,
m[5] - (m[8] ? m[9] ? m[9] + m[11] : 0 : lMin) || 0,
m[6] || 0,
((m[7] || 0) + '00').substr(0, 3)
);
}
return d.__parse.apply(this, arguments);
};
}
d.__fromString = d.fromString;
d.fromString = function(v) {
if (!d.__fromString || regexIso8601.test(v)) {
return new d(d.parse(v));
}
return d.__fromString.apply(this, arguments);
};
})();
_
これが役に立つことを願って
任意のブラウザーでISO8601日付形式を解析する単純な関数:
function dateFromISO8601(isoDateString) {
var parts = isoDateString.match(/\d+/g);
var isoTime = Date.UTC(parts[0], parts[1] - 1, parts[2], parts[3], parts[4], parts[5]);
var isoDate = new Date(isoTime);
return isoDate;
}
はい、Date.parseは異なるブラウザに対して一貫性がありません。あなたは出来る:
一部の古いブラウザは、ISO日付文字列を解析するとwrong date(NaNではなく)を返します。
すべてのブラウザで独自のメソッドを使用できます。または、正しく実装されている場合はDate.parseを使用できます。既知のタイムスタンプを確認してください。
Date.fromISO= (function(){
var diso= Date.parse('2011-04-26T13:16:50Z');
if(diso=== 1303823810000) return function(s){
return new Date(Date.parse(s));
}
else return function(s){
var day, tz,
rx= /^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
p= rx.exec(s) || [];
if(p[1]){
day= p[1].split(/\D/).map(function(itm){
return parseInt(itm, 10) || 0;
});
day[1]-= 1;
day= new Date(Date.UTC.apply(Date, day));
if(!day.getDate()) return NaN;
if(p[5]){
tz= parseInt(p[5], 10)*60;
if(p[6]) tz += parseInt(p[6], 10);
if(p[4]== "+") tz*= -1;
if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
}
return day;
}
return NaN;
}
})()
ES5仕様は、特にタイムゾーンインジケータ/オフセットなしの日付の処理に関しては、ISO8601仕様から逸脱しています。 https://bugs.ecmascript.org/show_bug.cgi?id=112 に問題を説明するバグチケットがあり、ES6で修正される予定です。
今のところ、クロスブラウザ実装については、 https://github.com/csnover/js-iso8601 を参照することをお勧めします。 https://github.com/csnover/js-iso8601/tree/lax を使用します。これはES5仕様に準拠していませんが、JSON.NETなどの他のJSONシリアル化ライブラリとの相互運用性が向上しています。
前述のように、ISO 8601スタイルの日付がECMAScriptバージョン5に追加されました。このバージョンでは、実装に一貫性がなく、すべてのブラウザーで利用できるわけではありません。 numberof が利用可能なスクリプトスタブがありますが、独自のDate.parse *メソッドを単純に追加することもできます。
(function() {
//ISO-8601 Date Matching
var reIsoDate = /^(\d{4})-(\d{2})-(\d{2})((T)(\d{2}):(\d{2})(:(\d{2})(\.\d*)?)?)?(Z|[+-]00(\:00)?)?$/;
Date.parseISO = function(val) {
var m;
m = typeof val === 'string' && val.match(reIsoDate);
if (m) return new Date(Date.UTC(+m[1], +m[2] - 1, +m[3], +m[6] || 0, +m[7] || 0, +m[9] || 0, parseInt((+m[10]) * 1000) || 0));
return null;
}
//MS-Ajax Date Matching
var reMsAjaxDate = /^\\?\/Date\((\-?\d+)\)\\?\/$/;
Date.parseAjax = function(val) {
var m;
m = typeof val === 'string' && val.match(reMsAjaxDate);
if (m) return new Date(+m[1]);
return null;
}
}();
日付のJSON.parseハイドレーションに上記のメソッドを使用します...
JSON.parse(text, function(key, val) {
return Date.parseISO(val) || Date.parseAjax(val) || val;
});
Ckozlの回答は本当に便利で面白いと思いましたが、正規表現は完璧ではなく、私の場合はうまくいきませんでした。
分、秒、ミリ秒のない日付は解析されないという事実とは別に、ISO 8501仕様では、「-」と「:」の区切り文字はオプションであるため、「2013-12-27」と「20131227」は両方とも有効です。私の場合、PHPのJavaScript変数でサーバーの日付と時刻を設定しているため、これは重要です。
var serverDate = new Date(Date.parse("<?php date(DateTime::ISO8601); ?>"));
このコードは次のようなものを生成します。
<script>
var serverDate = new Date(Date.parse("2013-12-27T15:27:34+0100"));
</script>
重要な部分は、「:」が欠落しているタイムゾーン指定子「+0100」です。 Firefoxはその文字列を正しく解析しますが、IE(11)は失敗します( ':'を追加すると、IEも機能します)。ゾーンタイムに関する頭痛の種また、PHPは常にタイムゾーン指定子を追加するため、ckozlで記述されているECMAScript仕様は重要ではありません。
私が使用している正規表現は、ckozlのものではなく:
var regexIso8601 = /^(\d{4}|\+\d{6})(?:-?(\d{2})(?:-?(\d{2})(?:T(\d{2})(?::?(\d{2})(?::?(\d{2})(?:(?:\.|,)(\d{1,}))?)?)?(Z|([\-+])(\d{2})(?::?(\d{2}))?)?)?)?)?$/;
この正規表現も完璧ではないことに注意してください。 ISO 8501では、週の指定(2007年1月1日、月曜日の2007-W01-1)、または時間と分での小数部(18:30:00の場合は18.50、18:30:15の場合は18:30.25)が許可されます。しかし、それらは非常に珍しいです。
P.D.この答えは、元のchozlの答えに対するコメントであるはずですが、評判が十分ではありません:(
ISO 8601 日付形式は ECMAScript-262 v5で追加されました。そのため、ブラウザがv5互換でない場合、単にexpectISO 8601形式を処理できません。
V5と互換性のないブラウザは、実装固有の日付形式を使用できます。ただし、それらのほとんどは、少なくとも RFC822 / RFC112 日付形式をサポートしています。例:
var d = Date.parse("Wed, 26 Apr 2011 13:16:50 GMT+0200");
Microsoft Sharepoint 2013は、「2013-04-30T22:00:00Z」などの異なる表記を使用しています
Sharepoint 2013のRESTサービスをInternet Explorer 8(IE8)と組み合わせて使用する場合、ckozlのソリューションは機能しません。NaNを取得します
正規表現の行を次のように変更します。
regexIso8601 = /^(\d{4}|\+\d{6})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2}):(\d{2})(\.(\d{1,3}))?(?:Z|([\-+])(\d{2}):(\d{2}))?)?)?)?$/;
これにより、マイクロ秒ビットがオプションになります!
チェリオ、レオ