サファリの無効な日付


155
 alert(new Date('2010-11-29'));

chrome、ffにはこれで問題はありませんが、サファリは「無効な日付」と叫びます。どうして ?

編集:わかりました、以下のコメントに従って、文字列解析を使用してこれを試しました:

alert(new Date('11-29-2010')); //doesn't work in safari
alert(new Date('29-11-2010')); //doesn't work in safari
alert(new Date('2010-29-11')); //doesn't work in safari

2018年3月22日編集:人々はまだここに着陸しているようです-今日、私はそれを使うmomentか、それで終わりますdate-fns。Date-fnsは非常に簡単で軽量です。


同じ問題を見ている他の人のために:私は最終的にDateJSを使用して、私の問題を全体的に解決しました。詳細については、承認された回答を参照してください。
Shrinath

2
タイムスタンプを解析するには、moment.jsを使用します。特にクロスプラットフォームWebを扱う場合
Ming Yuen

1
これは古い質問です。ECMAScript 2015以降、ISO 8601の日付のみの文字列はUTCとして解析されます。ただし、それを解析しないか、ローカルとして扱う古いブラウザーがまだ残っている可能性があります。
RobG 2017年

回答:


167

パターンyyyy-MM-ddは、Dateコンストラクターで公式にサポートされている形式ではありません。Firefoxはそれをサポートしているようですが、同じことをしている他のブラウザを当てにしないでください。

サポートされている文字列は次のとおりです。

  • MM-dd-yyyy
  • yyyy / MM / dd
  • MM / dd / yyyy
  • MMMM dd、yyyy
  • MMM dd、yyyy

DateJSは、非標準の日付形式を解析するための優れたライブラリのようです。

編集ECMA-262標準をチェックしました。セクション15.9.1.15からの引用:

日時文字列形式

ECMAScriptは、ISO 8601拡張フォーマットの簡略化に基づいて、日時の文字列交換フォーマットを定義します。形式は次のとおりです。YYYY-MM-DDTHH:mm:ss.sssZフィールドは次のとおりです。

  • YYYYは、グレゴリオ暦の年の10進数です。
  • "-"(ハイフォン)は文字列に文字通り2回出現します。
  • MMは、01(1月)〜12(12月)の月です。
  • DDは、01から31までの月の日です。
  • "T"は文字列内に文字通り現れ、時間要素の始まりを示します。
  • HHは、真夜中から経過した完全な時間数で、2桁の10進数です。
  • ":"(コロン)は、文字列内で文字どおり2回出現します。
  • mmは、2桁の10進数としての、時間の開始以降の完全な分数です。
  • ssは、分の開始からの完全な秒数で、2桁の10進数です。
  • 「」(ドット)は文字列内にそのまま表示されます。
  • sssは、秒の開始以降の完全なミリ秒数で、3桁の10進数です。「。」の両方 ミリ秒フィールドは省略できます。
  • Zは、 "Z"(UTCの場合)または "+"または "-"の後に時間式hh:mmが続く形式で指定されたタイムゾーンオフセットです。

この形式には、日付のみのフォームが含まれます。

  • YYYY
  • YYYY-MM
  • YYYY-MM-DD

オプションのタイムゾーンオフセットが追加された時間のみのフォームも含まれます。

  • THH:mm
  • THH:mm:ss
  • THH:mm:ss.sss

上記の任意の組み合わせである「日時」も含まれます。

したがって、YYYY-MM-DDは標準に含まれているようですが、何らかの理由でSafariではサポートされていません。

更新datejsのドキュメントを見て、それを使用した後、次のようなコードを使用して問題を解決する必要があります:

var myDate1 = Date.parseExact("29-11-2010", "dd-MM-yyyy");
var myDate2 = Date.parseExact("11-29-2010", "MM-dd-yyyy");
var myDate3 = Date.parseExact("2010-11-29", "yyyy-MM-dd");
var myDate4 = Date.parseExact("2010-29-11", "yyyy-dd-MM");

4
ISO8601形式はECMAScript標準の第5版で使用されており、まだ広くサポートされていません。IMOにアクセスして日付を手動で解析する最も安全な方法:(
CMS

1
それはとても役に立ちました..ありがとう.. :)最終的に、フォーマットにdatejsを使用することになりました。
シュリナート

将来的には、datejsはほとんどの点で素晴​​らしいですが、特にSafariの場合、すべての日付フォーマットの問題が解決されるわけではないことに注意してください。これはPITAですが、問題が解決しない場合は手動で行うことをお勧めします。
totallyNotLizards

@dariooだから私は次のようにあなたの答えを試しました: "var start = Date.parseExact(timestamp、" YYYY-DD-MM HH:mm:SS ");" タイムスタンプは「2016-01-28 00:00:00」です。ただし、「Date.parseExactは関数ではありません」というエラーが表示されます。ここで何が起こっているのか知っていますか?
threxx

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

224

Safariが正しく実行できないからといって、新しいライブラリを実装するのは多すぎて、正規表現はやりすぎです。これがワンライナーです:

console.log (new Date('2011-04-12'.replace(/-/g, "/")));

スラッシュを取得することが私の問題だけだった場合は、私はあなたの答えを「受け入れ」たでしょう(ただし、この質問をしたときの唯一の目的でした)。dateJSを見つけたので、より使いやすいMMM DD、YYYY形式を実装しました!!!
シュリナート

13
この1行のヘルプは私のニーズにぴったりでした。ありがとう!
Cyril N.

4
これも私にとっては十分に簡単でした。Safariが嫌いなのは信じられません-しかし、\\を使用した同じフォーマットは機能します。@Elzoに感謝し、質問を投稿してくれたShrinathに感謝します
ピート

1
これは、「-」の代わりに/-/ gを忘れがちな最良の答えだと思います
Jacek Pietal

12
ライブラリを実装していないことに対する拍手
lharby 2017

56

私は同様の問題に直面していました。Date.Parse("DATESTRING")Chrome(バージョン59.0.3071.115)で動作していましたが、Safari(バージョン10.1.1(11603.2.5))では動作していませんでした

サファリ:

Date.parse("2017-01-22 11:57:00")
NaN

クロム:

Date.parse("2017-01-22 11:57:00")
1485115020000

私にとってうまくいった解決策は、dateStringのスペースをに置き換えることでした"T"。(例:dateString.replace(/ /g,"T")

サファリ:

Date.parse("2017-01-22T11:57:00")
1485086220000

クロム:

Date.parse("2017-01-22T11:57:00")
1485115020000

SafariがローカルTZ(UTCより8時間遅れ)で応答を返したため、Safariブラウザからの応答はChromeブラウザで表示される応答よりも8時間(28800000ミリ秒)短いことに注意してください。

同じTZで両方の時間を取得するには

サファリ:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

クロム:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

または、両方の日付をSafariとChromeで同じにしたくない場合は、new Date(year, month, date, hours, minutes, seconds, milliseconds)コンストラクターを使用できます。コンストラクタでこれらのコンポーネントを使用するために、文字列dateをそのコンポーネントの配列に解析します。@nizantzこのような例を回答に追加できるとしたら、すばらしいでしょう。
h3dkandi 2017年

日付は現地時間ではなくUTCで取得されるため、特に有用ではありません。
JonasÄppelgran18年

1
このdateString.replace(/ /g,"T")魔法のコード行が私を形作りました。:)
Mazdak Shojaie 2018

replace(/-/ g、 '/')
Jack Hu

11

瞬間を使って問題を解決します。例えば

var startDate = moment('2015-07-06 08:00', 'YYYY-MM-DD HH:mm').toDate();

10

ほとんどのブラウザーでソリューションを機能させるには、この形式で日付オブジェクトを作成する必要があります

(year, month, date, hours, minutes, seconds, ms)

例えば:

dateObj = new Date(2014, 6, 25); //UTC time / Months are mapped from 0 to 11
alert(dateObj.getTime()); //gives back timestamp in ms

IE、FF、Chrome、Safariで正常に動作します。古いバージョンでも。

IEデベロッパーセンター:日付オブジェクト(JavaScript)

Mozilla Dev Network:日付


6

文字列を日付から日付に変換します(サーバーのタイムゾーンを知っている必要があります)

new Date('2015-06-16 11:00:00'.replace(/\s+/g, 'T').concat('.000+08:00')).getTime()  

ここで+08:00 =サーバーからのtimeZone


これはDSTを考慮していません。TZオフセットは変動する可能性があり、日付自体(および時刻)に依存します。
コスタ

5

同じ問題があり、それから私はモーメントを使用しました。Js.Problemが消えました。

文字列からモーメントを作成する場合、まず文字列が既知のISO 8601形式と一致するかどうかを確認し、既知の形式が見つからない場合は新しいDate(string)にフォールバックします。

警告:文字列の解析に対するブラウザのサポートに一貫性がありません。サポートするフォーマットについての仕様がないため、一部のブラウザーで機能するものは他のブラウザーでは機能しません。

ISO 8601文字列以外の解析で一貫した結果を得るには、文字列+形式を使用する必要があります。

例えば

var date= moment(String);

3

ブラウザーがISO 8601(またはその日付のみのサブセット)をサポートすることを望むかもしれませんが、これは当てはまりません。私が知っているすべてのブラウザー(少なくとも私が使用する米国/英語のロケールでは)は、恐ろしい米国のMM/DD/YYYY形式を解析できます。

日付の一部がすでにある場合は、代わりにDate.UTC()を使用することをお勧めします。そうでない場合でも、YYYY-MM-DD形式を使用する必要があります。正規表現を使用して、知っている部分を解析し、それらをに渡すことをお勧めしますDate.UTC()


文字列の解析が進むべき道だと思います:(
Shrinath

1

以下のフォーマットを使用すると、すべてのブラウザーで機能します

var year = 2016;
var month = 02;           // month varies from 0-11 (Jan-Dec)
var day = 23;

month = month<10?"0"+month:month;        // to ensure YYYY-MM-DD format
day = day<10?"0"+day:day;

dateObj = new Date(year+"-"+month+"-"+day);

alert(dateObj); 

//出力は次のようになります "Wed Mar 23 2016 00:00:00 GMT + 0530(IST)"

//これはISTで示される現在のタイムゾーンにあることに注意してください。UTCタイムゾーンに変換するには、含めることができます

alert(dateObj.toUTCSting);

//出力は次のようになります "火曜日、22 Mar 2016 18:30:00 GMT"

dateObjは時刻をGMT形式で表示することに注意してください。また、日付と時刻が対応して変更されていることにも注意してください。

「toUTCSting」関数は、グリニッジ子午線での対応する時間を取得します。これは、現在のタイムゾーンとグリニッジ子午線のタイムゾーンとの時差を確立することによって達成されます。

上記の場合、変換前の時間は2016年の3月23日の00:00時間と分でした。そして、GMT + 0530(IST)時間からGMTへの変換後(これでは、基本的に、指定されたタイムスタンプから5.30時間を差し引きます)ケース)時間は、2016年の3月22日の18.30時間を反映します(最初の時間より正確に5.30時間)。

さらに、日付オブジェクトをタイムスタンプに変換するために使用できます

alert(dateObj.getTime());

//出力はこの「1458671400000」のようなものになります

これにより、時間の一意のタイムスタンプが得られます



1

これを行う最良の方法は、次の形式を使用することです。

new Date(year, month, day, hours, minutes, seconds, milliseconds)
var d = new Date(2018, 11, 24, 10, 33, 30, 0);

これはすべてのブラウザでサポートされており、問題は発生しません。月は0〜11の範囲で書かれていることに注意してください。


SafariとChromeで問題なく動作しますが、Firefoxでも問題があります。Safari:var date = new Date(2018,06,08,19,17)Sun Jul 08 2018 19:17:00 GMT + 0800(+08)Chrome:var date = new Date(2018,06,08,19、 17)2018年7月8日19:17:00 GMT + 0800(マレーシア時間)Firefox:var date = new Date(2018,06,08,19,17)Date 2018-07-08T11:17:00.000Z
Biranchi

0

Safariで直面している同じ問題と、これをWebページに挿入することで解決しました

 <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script> 

それがあなたのケースでもうまくいくことを願っています

ありがとう


なぜこれがうまくいくと思いますか?スクリプトを見たところ、Dateオブジェクトのメソッドをオーバーライドしていないようです。私はここに行きました:polyfill.io/v3/url-builderそして日付の解析について何もないようです。
コスタ

0

@nizantzが前述したように、Date.parse()を使用しても、Safariでは機能しませんでした。少し調べたところ、FileオブジェクトのlastDateModifiedプロパティが非推奨になり、Safariでサポートされなくなったことがわかりました。FileオブジェクトのlastModifiedプロパティを使用すると、問題が解決しました。オンラインで悪い情報が見つかった場合は、きっと嫌いになります。

この投稿に寄稿してくれたすべての人に感謝します。私の問題について学ぶために必要な道を進むのを助けてくれました。この情報がなければ、おそらく根本的な問題を理解できなかったでしょう。多分これは私の同じような状況で他の誰かを助けるでしょう。


0

Safariブラウザでも同じ問題に直面しています

var date = new Date("2011-02-07");
console.log(date) // IE you get ‘NaN’ returned and in Safari you get ‘Invalid Date’

ここでのソリューション:

var d = new Date(2011, 01, 07); // yyyy, mm-1, dd  
var d = new Date(2011, 01, 07, 11, 05, 00); // yyyy, mm-1, dd, hh, mm, ss  
var d = new Date("02/07/2011"); // "mm/dd/yyyy"  
var d = new Date("02/07/2011 11:05:00"); // "mm/dd/yyyy hh:mm:ss"  
var d = new Date(1297076700000); // milliseconds  
var d = new Date("Mon Feb 07 2011 11:05:00 GMT"); // ""Day Mon dd yyyy hh:mm:ss GMT/UTC 

0

これは最善の解決策ではありませんが、エラーをキャッチして現在の日付を返信するだけです。私は個人的には、ユーザーがsh * t非標準に準拠したブラウザーを使用したい場合、Safariの問題を解決したくないと感じています-彼らは奇抜な生活をしなければなりません。

function safeDate(dateString = "") {
  let date = new Date();
  try {
    if (Date.parse(dateString)) {
      date = new Date(Date.parse(dateString))
    }
  } catch (error) {
    // do nothing.
  }
  return date;
}

バックエンドにISO日付を送信させることをお勧めします。


すべての点で、ユーザーコードを記述したブラウザーを使用する必要があることを意味する場合、それは一般的には見た目が悪いように見えます。また、それは私たちのユースケースと対象読者にも依存します-大量市場の消費のためにウェブサイトが構築されているなら、少なくとも私たちはIE10もサポートするでしょう。MSの誰かがInternet Explorerの設計/コーディングをしているときに同じことを考えたと思います。私たちは皆、それが今どのように語られているかを知っています。
Shrinath

-1

「mm / dd / yyyy」の形式を使用します。例:-新しい日付('02 / 28/2015 ')。すべてのブラウザで正常に動作します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.