2017-06-23 7 views
-4

ISO 8601の日付文字列をエポックタイムに変換しようとしています。どのように負の日付を扱うのですか?以下のコードは正しいですか?私は単純な日付書式ライブラリの代わりに何か他のものを使うべきですか?マイナスの日付はBCです。Javaで負のISO 8601の日付文字列を処理する方法は?

String formatString = "yyyy-MM-dd'T'hh:mm:ssX"; 
SimpleDateFormat formatter = new SimpleDateFormat(formatString); 
Date date = formatter.parse("-2017-01-04T12:30:00+05:00"); 
System.out.println(date.getTime()/1000); 

Answer: -125818806600L 
+3

*否定的な日付*とは何ですか? '-2017-01-04'が有効な日付であるカレンダーはありますか? –

+0

エポックの1年前にしたい場合は、エポックから1年後に作成してください。 –

+0

達成しようとしていることを明確にすることができますか? –

答えて

6

TL; DR:いいえ、あなたのコードが正しくありません。はい、SimpleDateFormatの代わりに最新のJavaの日付と時刻APIを使用することをおすすめします。

あなたの最初の問題は、共通の時代(BCE、 "キリストの前")の前の年の正確さを定義することです。

私がWikipediaを読んだとき、ISO 8601はその範囲内の日付の解釈方法を明確に定義していません。その年自体は大きな問題ではありません。「0000年は1 BCEと等しい」ので、-1は2 BCE、-2017はBCE 2018です。 mayは、グレゴリオ暦を1582年の正式な導入に先立って延長して作成された予防的グレゴリオ暦を使用しますが、これは伝統的に使用されているユリウス暦とは異なるので注意してください。歴史書の1月4日と同じ日ではありません。また、負の年の使用とプロポーショナルなグレゴリオ暦は、ISO 8601の要件ではなく、当事者間の合意によってのみ行われます。予約:歴史書にBCEの2018年1月4日の定義があるかどうかはわかりません。私たちはユリウス暦の導入前に戻っています(紀元前46年にジュリアス・カエサルによって提案されました)。

The documentation of SimpleDateFormatグレゴリオ暦が導入される前の日付の処理方法は記載されていません。これは、日付/時刻フォーマッタに関連付けられたCalendarオブジェクトに依存するようです。このようなCalendarオブジェクトはほとんどのコンピュータとJVMではGregorianCalendarですが、必ずしもそうとは限りません。だから私はあなたのコードからの出力はすべてのコンピュータで同じであることが保証されていないことを取る。そして、GregorianCalendarは、通常、ユリウス暦の教皇グレゴール前の日付を扱うことができるので、の結果はは歴史書には同意しますが、ISO 8601には同意しません。 2018年1月4日、BCE。だからこれらの理由で私はあなたの結果が正しいとは思わない。

テストでは、あなたのコードの出力を、Javaの日付と時刻APIの同様の使い方の出力と比較しました。コードを実行すると、-125818806600も得られます。だから私が試した:

System.out.println(OffsetDateTime.parse("-2017-01-04T12:30:00+05:00") 
      .toInstant() 
      .getEpochSecond()); 

これらのクラスは、ISO 8601に準拠しなければなりませんので、私は(それも少し簡単です)あなたの上にこのコードを好むだろう。私はそれは同じではありませんので、あなたのコードが正しい結果が得られていないことを別の記号

-125817294600 

を得ました。差は1512000秒で、17日の12時間と同じです。私が理解していないことを認めて始めましょう。私はすぐにジュリアンとグレゴリオ暦の違いが17日か18日の違いを説明できると思います。しかし12時間は私を混乱させる。

編集:12時間は、フォーマットパターン文字列に小文字のhhを使用したことに由来します。 AM/PMマーカーがないので、大文字のHHを使用する必要があります。このエラーを修正、あなたのコードからの出力は、今すぐあなたのコードと私の間の差は1468800秒または正確に17日である

-125818763400 

です。

hhは、1〜12の範囲のAMまたはPM内の時間です。大文字のHHは、1日中の0〜23です。 SimpleDateFormatとよくある間違いです(現代のクラスではなく、それをキャッチして修正します)。ほとんどの時間は同じ結果になるので、それは気付かれないことがあります。 SimpleDateFormatはAMをデフォルトとして使用し、たとえば14:30の解析を行い、午後2:30と理解しています。しかし、文字列の時間が12になるので、12:30 AMはその日の0:30を意味し、ISO 12:30は12:30 PMを意味します。したがって、12時間のエラー。

+2

FYI:a) 'SimpleDateFormat'は1582-10-15より前の日付をユリウス暦の日付として扱います(非常に単純化された歴史的モデルです)。 b)印刷時にJava-8 -DateTimeFormatterでHの代わりにhを使用してよく見られる間違い(時刻が意図されている場所)もJava-8 -DateTimeFormatterで発生する可能性があります。 c)入力がISO-8601形式のものであれば、解釈は実際にはグレゴリオ暦(Java-8のように)でなければなりません。 –

関連する問題