web-dev-qa-db-ja.com

JavaScriptでの日付解析は、サファリとchrome

私は次のコードを持っています

var c = new Date(Date.parse("2011-06-21T14:27:28.593Z"));
console.log(c);

On Chromeコンソールに日付を正しく出力します。Safariでは失敗します。誰が正しいか、さらに重要なことは、これを処理する最善の方法は何ですか?

55
bradgonesurfing

実際にDate.parseを使用することはできません。 new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )を使用することをお勧めします

文字列を分割するには、試すことができます

var s = '2011-06-21T14:27:28.593Z';
var a = s.split(/[^0-9]/);
//for (i=0;i<a.length;i++) { alert(a[i]); }
var d=new Date (a[0],a[1]-1,a[2],a[3],a[4],a[5] );
alert(s+ " "+d);
94
Erik

この質問の他の回答に従って、私はDate.parseを避ける傾向があります。日付を確実に処理するための移植可能な方法ではないようです。

代わりに、以下の関数のようなものを使用しました。これは、jQueryを使用して文字列配列を数値配列にマッピングしますが、これは削除/変更が非常に簡単な依存関係です。また、同じ関数を使用して2007-01-092007-01-09T09:42:00を解析できるように、適切なデフォルトと見なすものも含めます。

function dateFromString(str) {
  var a = $.map(str.split(/[^0-9]/), function(s) { return parseInt(s, 10) });
  return new Date(a[0], a[1]-1 || 0, a[2] || 1, a[3] || 0, a[4] || 0, a[5] || 0, a[6] || 0);
}
15
jabley

いくつかのブラウザーで確認しましたが、はい、safariは_invalid date_を返します。ちなみに、ここで_Date.parse_を使用する必要はありません。new Date([datestring])だけでも機能します。 Safariは、明らかに、指定した日付文字列のより多くのフォーマットを必要とします。 「-」を「/」に置き換え、Tとドット(.593Z)の後のすべてを削除すると、有効な日付が得られます。このコードはテスト済みで、Safariで動作します

_var datestr = '2011-06-21T14:27:28.593Z'.split(/[-T.]/);
var safdat = new Date( datestr.slice(0,3).join('/')+' '+datestr[3] );
_

またはString.replace(...)を使用:

_new Date("2016-02-17T00:05:01+0000".replace(/-/g,'/').replace('T',' ').replace(/(\..*|\+.*/,""))
_
11
KooiInc

私の同様の問題は、SafariがRFC 822タイムゾーン形式でタイムゾーンを読み取る方法を知らないことが原因でした。 ISO 8601形式を使用して、これを修正できました。日付形式を制御できる場合は、JavaのSimpleDateFormat "yyyy-MM-dd'T'HH:mm:ss.sssXXX"で動作します。 「2018-02-06T20:00:00.000 + 04:00」。何らかの理由でSafariが「2018-02-06T20:00:00.000 + 0400」を読み取れない場合、タイムゾーン形式にコロンがないことに注意してください。

// Works
var c = new Date("2018-02-06T20:00:00.000+04:00"));
console.log(c);

// Doesn't work
var c = new Date("2018-02-06T20:00:00.000+0400"));
console.log(c);
10
Olmstov

私はこれを相殺するためにライブラリを使用することになりました:

http://zetafleet.com/blog/javascript-dateparse-for-iso-8601

そのライブラリが含まれたら、次のコードを使用して新しい日付を作成します。

var date = new Date(Date.parse(datestring));

私たちのプロジェクトではミリ秒の指定子を使用していませんでしたが、それが問題を引き起こすとは思いません。

5
AaronSieb

タイムゾーンで日付を解析するために次の関数を使用します。 ChromeおよびSafari:

function parseDate(date) {
  const parsed = Date.parse(date);
  if (!isNaN(parsed)) {
    return parsed;
  }

  return Date.parse(date.replace(/-/g, '/').replace(/[a-z]+/gi, ' '));
}

console.log(parseDate('2017-02-09T13:22:18+0300'));  // 1486635738000 time in ms
4
Londeren

私はそれを切り捨てて、そのように解析することで変換された日付を試しました。

var dateString = "2016-01-22T08:18:10.000+0000";
 var hours = parseInt(dateString.split("+")[1].substr("0","2"));
 var mins = parseInt(dateString.split("+")[1].substr("2"));
 var date = new Date(dateString.split("+")[0]);
 date.setHours(date.getHours()-hours);
 date.setMinutes(date.getMinutes()-mins);
1
Anky

以下は、他の人が投稿したものよりも堅牢なISO 8601パーサーです。週形式は処理しませんが、他のすべての有効なISO 8601日付をすべてのブラウザーで一貫して処理する必要があります。

function newDate(value) {
  var field = value.match(/^([+-]?\d{4}(?!\d\d\b))(?:-?(?:(0[1-9]|1[0-2])(?:-?([12]\d|0[1-9]|3[01]))?)(?:[T\s](?:(?:([01]\d|2[0-3])(?::?([0-5]\d))?|24\:?00)([.,]\d+(?!:))?)?(?::?([0-5]\d)(?:[.,](\d+))?)?([zZ]|([+-](?:[01]\d|2[0-3])):?([0-5]\d)?)?)?)?$/) || [];
  var result = new Date(field[1], field[2] - 1 | 0, field[3] || 1, field[4] | 0, field[5] | 0, field[7] | 0, field[8] | 0)
  if (field[9]) {
    result.setUTCMinutes(result.getUTCMinutes() - result.getTimezoneOffset() - ((field[10] * 60 + +field[11]) || 0));
  }
  return result;
}

console.log(newDate('2011-06-21T14:27:28.593Z'));
console.log(newDate('1970-12-31T06:00Z'));
console.log(newDate('1970-12-31T06:00-1200'));
0
Adam Leggett

日付文字列の最後に「Z」を使用する代わりに、ローカルクライアントのタイムゾーンオフセットを追加できます。おそらくそれを生成するメソッドが必要になるでしょう:

_let timezoneOffset = () => {
    let date = new Date(),
        timezoneOffset = date.getTimezoneOffset(),
        hours = ('00' + Math.floor(Math.abs(timezoneOffset/60))).slice(-2),
        minutes = ('00' + Math.abs(timezoneOffset%60)).slice(-2),
        string = (timezoneOffset >= 0 ? '-' : '+') + hours + ':' + minutes;
    return string;
}
_

したがって、最終結果は次のようになります。

var c = new Date("2011-06-21T14:27:28.593" + timezoneOffset());

0
adjwilli