Java Date&Time APIの何が問題になっていますか?[閉まっている]


105

Java Dateやその他の日時に関連するクラスに対する否定的なフィードバックに遭遇することがよくあります。私は.NET開発者なので、実際に何が問題になっているのか(完全に使用せずに)完全に理解することはできません。

誰かがこれに光を当てることができますか?


回答:


142

ああ、Java Dateクラス。おそらく、どの言語でもどこでも何もしないようにする方法の最も良い例の1つでしょう。どこから始めますか?

JavaDocを読むと、開発者が実際に良いアイデアを持っていると考えるようになるかもしれません。UTCとの違いについてGMT二つの違いは基本的に(起こらない秒飛躍されているにもかかわらず、長さでかなり めったにが)。

ただし、設計上の決定は、適切に設計されたAPIであるという考えを無駄にすることになります。ここでは、よくある間違いをいくつか紹介します。

  • ミレニアムの最後の10年間で設計されたにもかかわらず、それは1900年以来2桁と評価されています。この卑劣な決定の結果として、Javaの世界では1900+(または1900-)を実行する回避策が文字通り数百万あります。
  • 月にはゼロのインデックスが付けられ、月の配列があり、最初の要素がを含む13個の要素の配列と共存しないという異常なケースに対応しnullます。その結果、0..11(今日は109年の月11)になります。文字列に変換するために、同様の数の++と-が月にあります。
  • 彼らは 可変です。その結果、日付を返す(たとえば、インスタンス構造として)場合は常に、日付オブジェクト自体ではなく、その日付のクローンを返す必要があります(それ以外の場合は、構造を変更できるためです)。
  • Calendarを「修正」するように設計されたは、実際には同じ間違いを犯します。彼らはまだ変更可能です。
  • Date を表す DateTimeますが、SQLランドのそれらを順守するためにjava.sql.Date、1日を表す別のサブクラスがあります(ただし、タイムゾーンは関連付けられていません)。
  • TimeZone関連付けられたはないDateため、範囲(「終日」など)はしばしば真夜中-真夜中(しばしば任意のタイムゾーン)として表されます

最後に、うるう秒は一般に、1時間以内にntpで更新される適切なシステムクロックに対して自動的に修正されることに注意してください(以下のリンクを参照)。2うるう秒(実際には数年ごとに最低6か月ごと)が導入されてもシステムが稼働し続ける可能性はほとんどありません。特に、新しいバージョンのコードを時々再デプロイする必要があるという事実を考慮すると、 。クラスを再生成する動的言語やWARエンジンのようなものを使用しても、クラススペースが汚染され、最終的にpermgenが不足します。


43

Java 8 でjava.timeを使用して古い日時クラスを置き換えたJSR 310は、次のように元のJSRで正当化されます。

2.5提案された仕様では、Javaコミュニティのどのようなニーズに対応しますか?

現在、Java SEには、java.util.Dateとjava.util.Calendarという2つの別個の日時APIがあります。両方のAPIは、Java開発者がウェブログやフォーラムで使用するのが難しいと一貫して説明されています。特に、両方とも数か月間ゼロインデックスを使用するため、多くのバグが発生します。カレンダーは、主にその状態を内部で2つの異なる方法で保存するため、長年にわたって多くのバグとパフォーマンスの問題に悩まされてきました。

1つの古典的なバグ(4639407)により、特定の日付がCalendarオブジェクトに作成されませんでした。一部のユーザーが正しい生年月日を入力できないようにする効果がある、一部の年では日付を作成できるが他の年では作成できない一連のコードを書くことができます。これは、Calendarクラスが夏の夏時間の1時間の増加しか許さなかったために発生しました。このバグは修正されましたが、将来、ある国で夏時間に3時間の夏時間の追加が導入された場合、Calendarクラスは再び機能しなくなります。

現在のJava SE APIは、マルチスレッド環境でも問題があります。不変クラスは、状態を変更できないため、本質的にスレッドセーフであることが知られています。ただし、日付とカレンダーはどちらも変更可能であるため、プログラマーは複製とスレッド化を明示的に考慮する必要があります。さらに、DateTimeFormatにスレッドセーフ性がないことは広く知られていないため、スレッド化の問題を追跡するのが難しい多くの原因となっています。

Java SEが日時に対して持つクラスの問題に加えて、Java SEには他の概念をモデル化するためのクラスがありません。非タイムゾーンの日付または時刻、期間、期間、および間隔は、Java SEではクラス表現を持ちません。その結果、開発者は頻繁にintを使用して期間を表し、javadocで単位を指定します。

包括的な日時モデルがないため、多くの一般的な操作が本来よりも扱いにくくなっています。たとえば、2つの日付間の日数を計算することは、現在のところ特に難しい問題です。

このJSRは、日付と時刻(タイムゾーンの有無にかかわらず)、期間と期間、間隔、フォーマット、解析を含む完全な日付と時刻モデルの問題に取り組みます。


28
  • 日付インスタンスは変更可能ですであり、ほとんどの場合不便です。
  • 彼らは二重の性質を持っています。それらはタイムスタンプとカレンダー日付の両方を表します。日付で計算を行う場合、これは問題があることがわかりました。
  • カレンダーデータの数値表現は、多くの場合直観に反しています。例:getMonth()はゼロベース、getYear()1900ベースです(つまり、2009年は109として表されます)。
  • Dateクラスに期待する多くの機能が欠けています。

13

私はあなたのために感じます...以前の.NETプログラマーとして、私は同じ質問をしました。.NETのタイムAPI(タイムスパン、オペレーターのオーバーロード)は非常に便利です。

まず、特定の日付を作成するには、廃止されたAPIを使用するか、次のいずれかを行います。

Calendar c = Calendar.getInstance();
c.set(2000, 31, 12)

1日を引くには、次のような悪事を行います

Date firstDate = ...
Calendar c = Calendar.getInstance();
c.setTime(fistDate);
c.add(Calendar.DATE,-1);
Date dayAgo = c.getTime();

または悪い

Date d = new Date();
Date d2 = new Date(d.getTime() - 1000*60*60*24);

2つの日付の間に経過した日数(日/週/月)を確認するには...さらに悪化します

ただし、Apache()のDateUtilsにorg.apache.commons.lang.time.DateUtils便利なメソッドがいくつかあり、最近ではそれらだけを使用していることに気付きました

Brabsterが書いたように、Joda Timeも優れた外部ライブラリですが、Apacheは他の何よりも「一般的」に見えます...


その方法を教えてください(「2つの日付の間に経過した時間を調べてください」)。
Anton Gogolev、2009

私はvlolatile日私はうるう年、びくびくヶ月を含む...簡単な方法を知っていたい、と...
エランメダン

1
参照してください、org.apache.commons.lang.time:commons.apache.org/lang//api/org/apache/commons/lang/time/...
trashgod

@AntonGogolev java.timeではPeriodDurationクラスを使用して経過時間を計算し、それぞれ年月日および時間分秒のスケールで表します。
バジルブルク

4

正直なところ、JavaのDate APIは使用可能です。私が見たと聞いた問題のほとんどは、冗長性、便利なもの(行うために複数のクラスが関与する必要性に関連してCalendarDateDateFormat/ SimpleDateFormat)などの単純なアクセサがないことをgetDayOfWeek()

Joda TimeはJavaで高く評価されている代替APIであり、Why Joda Timeのセクションでは、なぜそれが興味深い可能性のある実行可能な代替であるかについて、さらにいくつかの議論を提供しています。

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