web-dev-qa-db-ja.com

Java 8 Date Time API(Java.time)とJoda-Timeの違い

私は Java.util.Date とJoda-Timeに関連した質問があることを知っています。しかし、少し掘ってみると、 Java.time API の違いについてのスレッドが見つかりませんでした( Java 8 の新機能)。 、 JSR 310 )および Joda-Time で定義されます。

私は、Java 8のJava.time APIが、Joda-Timeよりもはるかにきれいで、はるかに多くのことができると聞いたことがあります。しかし、両者を比較した例は見当たりません。

  • Joda-TimeがJava.timeにできることは何ですか?
  • Java.timeはJoda-Timeよりも優れていますか?
  • Java.timeのほうがパフォーマンスは良いですか?
244
Zack

一般的な機能

a)両方のライブラリは不変型を使用します。 Joda-Timeは、MutableDateTimeなどの追加の可変タイプも提供します。

b)さらに:両方のライブラリはデザインスタディからインスピレーションを受けています エリックエバンスの「TimeAndMoney」 または ドメインドリブンスタイルについてのマーティンファウラー流fluentなプログラミングスタイル (常に完璧ではありません;-))。

c)両方のライブラリを使用して、実際のカレンダー日付タイプ(LocalDateと呼ばれる)、実際の壁時間タイプ(LocalTimeと呼ばれる)、および構成(LocalDateTimeと呼ばれる)を取得します。これは、古いJava.util.CalendarおよびJava.util.Dateと比較して非常に大きな勝利です。

d)両方のライブラリはメソッド中心のアプローチを使用します。つまり、getDayOfYear()の代わりにget(DAY_OF_YEAR)を使用するようユーザーに促します。これにより、Java.util.Calendarと比較して多くの余分なメソッドが発生します(ただし、後者はintの過度の使用によりタイプセーフではありません)。

パフォーマンス

@ OO7による他の回答は、Mikhail Vorontsovの分析を示していますが、ポイント3(例外のキャッチ)はおそらく時代遅れです- this JDK-bug を参照してください。さまざまなパフォーマンス(一般的に JSR-31 が望ましい)は、主に Joda-Time の内部実装が常にマシンタイムライクを使用するという事実によるものです。ロングプリミティブ(ミリ秒単位)。

Null

Joda-Timeは多くの場合、システムタイムゾーン、デフォルトロケール、現在のタイムスタンプなどのデフォルトとしてNULLを使用しますが、JSR-310はほとんどの場合NULL値を拒否します。

精度

JSR-310は nanosecond 精度を処理しますが、Joda-Timeは millisecond 精度に制限されます。

サポートされているフィールド:

Java-8(JSR-310)でサポートされているフィールドの概要は、temporal-packageの一部のクラス(たとえば、 ChronoField および WeekFields )によって提供されますが、Joda-Timeはこの領域ではかなり弱い- DateTimeFieldType を参照。 Joda-Timeの最大の欠如は、ローカライズされた週関連のフィールドがないことです。両方のフィールド実装設計の共通の特徴は、両方がlong型の値に基づいていることです(他の型はなく、列挙型さえも)。

Enum

JSR-310は enumsDayOfWeekまたはMonthのように提供しますが、Joda-Timeは主に2002-2004年前に開発されたため、これを提供しません Java 5

ゾーンAPI

a)JSR-310は、Joda-Timeよりも多くのタイムゾーン機能を提供します。 JSR-310はこれを行うことができますが、後者はタイムゾーンオフセット遷移の履歴にプログラムからアクセスすることはできません。

b)ご参考まで:JSR-310は、内部タイムゾーンリポジトリを新しい場所と異なる形式に移動しました。古いライブラリフォルダーlib/ziはもう存在しません。

調整器とプロパティ

JSR-310は、一時的な計算と操作を外部化する形式化された方法としてTemporalAdjuster-インターフェースを導入しました。特にライブラリまたはフレームワークライターの場合、これはJSR-310の新しい拡張機能(以前のJava.util.Date)の静的ヘルパークラスに相当します。

ただし、ほとんどのユーザーにとって、この機能の価値は非常に限られています。コードを記述する負担は依然としてユーザーにあるからです。新しいTemporalAdjuster-コンセプトに基づいた組み込みソリューションはそれほど多くありません。現在、限られた操作セット(および列挙TemporalAdjustersまたはその他の一時的なヘルパークラスMonthのみが存在します。タイプ)。

Joda-Timeはフィールドパッケージを提供しますが、新しいフィールド実装のコーディングは非常に困難であるという証拠があります。一方、Joda-Timeは、JSR-310よりも操作がはるかに簡単でエレガントな、いわゆるプロパティを提供します。たとえば、 property.withMaximumValue() です。

カレンダーシステム

JSR-310は、4つの追加カレンダーシステムを提供します。最も興味深いのは malqura (サウジアラビアで使用)です。他の3つは、 Minguo (台湾)、日本語(1871年以降のモダンカレンダーのみ)および ThaiBuddhist (1940年以降のみ)です。

Joda-Timeは、計算ベースに基づいた イスラム暦 を提供しています-Umalquraのような目撃情報に基づく暦ではありません。タイ仏教も同様の形式でJoda-Timeによって提供されますが、Minguoと日本のものはそうではありません。それ以外の場合、Joda-Timeはコプト暦とエチオピア暦も提供します(ただし、国際化はサポートされていません)。

ヨーロッパ人にとってより興味深いのは、Joda-Timeは グレゴリオ暦ジュリアン および混合グレゴリオ暦とジュリアン暦を提供することです。ただし、日付履歴の異なる年の開始などの重要な機能はまったくサポートされていないため、実際の履歴計算の実用的な価値は限られています(古いJava.util.GregorianCalendarでも同じ批判が有効です)。

ヘブライ語 または ペルシャ語 または ヒンドゥー語 などの他のカレンダーは、両方のライブラリで完全に欠落しています。

エポック日

JSR-310にはクラス JulianFields がありますが、Joda-Time(バージョン2.0)にはクラス DateTimeUtils のヘルパーメソッドがいくつかあります。

時計

JSR-310にはインターフェース(設計ミス)はありませんが、クロック依存性注入に使用できる抽象クラスJava.time.Clockがあります。 Joda-Timeは、インターフェイス MillisProvider と、代わりに DateTimeUtils のヘルパーメソッドを提供します。このように、Joda-Timeは異なるクロック(モッキングなど)を使用したテスト駆動モデルをサポートすることもできます。

デュレーション計算

両方のライブラリは、1つ以上の時間単位での時間距離の計算をサポートしています。ただし、単一ユニットの期間を処理する場合、JSR-310スタイルの方が明らかに優れています(intを使用する代わりにlongベースです)。

JSR-310 => long days = ChronoUnit.DAYS.between(date1, date2);

Joda-Time => int days = DAYS.daysBetween(date1, date2).getDays();

複数ユニットの期間の処理も異なります。計算結果でさえ異なる場合があります。これを参照してください Joda-Time issue 。 JSR-310は非常にシンプルで限定的なアプローチを使用してクラスPeriod(年、月、日に基づく期間)およびDuration(秒およびナノ秒に基づく)のみを使用しますが、Joda-TimeはクラスPeriodTypeを使用したより洗練された方法で、どの単位で期間(Joda-Timeは「期間」と呼ばれる)を表現するかを制御します。 PeriodType- APIは、JSR-310によって提供されるものではありませんが、同様の方法を使用するのはやや面倒です。特に、JSR-310では、(たとえば、日と時間に基づいて)日付と時刻の混在した期間を定義することはまだできません。あるライブラリから別のライブラリへの移行に関しては注意が必要です。議論中のライブラリは、クラス名が部分的に同じにもかかわらず、互換性がありません。

間隔

JSR-310はこの機能をサポートしていませんが、Joda-Timeのサポートは限られています。こちらもご覧ください SO-answer

フォーマットと解析

両方のライブラリを比較する最良の方法は、同じ名前のクラス DateTimeFormatterBuilder (JSR-310)および DateTimeFormatterBuilder (Joda-Time)を表示することです。 JSR-310バリアントはもう少し強力です(フィールド実装者が resolve() のようないくつかの拡張ポイントをコーディングできた場合、あらゆる種類のTemporalFieldも処理できます)。しかし、最も重要な違いは-私の意見では:

JSR-310は、タイムゾーン名(フォーマットパターンシンボルz)をよりよく解析できますが、Joda-Timeは以前のバージョンではまったく実行できず、現在は非常に限られた方法でしか実行できません。

JSR-310のもう1つの利点は、ロシア語やポーランド語などの言語で重要なスタンドアロンの月名のサポートです。Joda-Timeには そのようなリソースへのアクセスなし -Java-8プラットフォームでもありません。

JSR-310のパターン構文は、Joda-Timeよりも柔軟性があり、オプションのセクション(角括弧を使用)を許可し、CLDR標準に向けられ、パディング(文字記号p)およびより多くのフィールドを提供します。

それ以外の場合、Joda-Timeは PeriodFormatter を使用して期間をフォーマットできることに注意してください。 JSR-310はこれを行うことができません。


この概要がお役に立てば幸いです。収集されたすべての情報は、より良い日時ライブラリを設計および実装する方法(完璧なものは何もありません)の私の努力と調査により、主にそこにあります。

2015-06-24からの更新:

その間、私はJavaのさまざまなタイムライブラリについて記述し、 表形式の概要を公開 する時間を見つけました。表には、Joda-Time v2.8.1とJava-8(JSR-310)の比較も含まれています。この投稿よりも詳細です。

398
Meno Hochschild

Java 8日時:

  1. Java 8クラスは、人間の時代を中心に構築されています。それは人間の日時演算/変換のためにそれらを速くします。
  2. getDayOfMonthのような日付/時刻コンポーネントのゲッターは、Java 8の実装においてO(1)の複雑さを持ちます。
  3. Java 8 ea b121では、JDK内部で例外がスローされてキャッチされるため、OffsetDateTime/OffsetTime/ZonedDateTimeの解析が非常に遅くなります。
  4. 一連のパッケージ:Java.time.*Java.time.chrono.*Java.time.format.*Java.time.temporal.*Java.time.zone.*
  5. インスタンス(タイムスタンプ)日付と時刻部分的な日付と時刻パーサーとフォーマッタタイムゾーンさまざまな年表(カレンダー)。
  6. DateはI18NやL10Nをサポートしていないなど、既存のクラスには問題があります。彼らはミュータブルです!
  7. よりシンプルで堅牢.
  8. クロックを注入することができます。
  9. 時計は、静的時計、モック時計、低精度時計(秒、分など)のさまざまなプロパティで作成できます。
  10. 時計は特定のタイムゾーンで作成できます。 Clock.system(Zone.of("America/Los_Angeles"))
  11. コード処理の日時をテスト可能にします。
  12. テストをタイムゾーンとは無関係にします。

Joda-Time:

  1. Joda-Timeは内部で機械時間を使用しています。 int/long値に基づく手動の実装ははるかに高速です。
  2. Joda-Timeゲッターはゲッターコールごとにコンピュータから人間への時間の計算を必要とします。これはJoda-Timeをそのようなシナリオのボトルネックにします。
  3. インスタンス、日付と時刻、部分、および期間を処理する不変クラスで構成されています。
  4. 日付を瞬間として表します。しかし、日付と時刻は複数の瞬間に対応することがあります。夏時間が終了したときの重複時間。まったくそれに対応する瞬間を持っていないだけでなく。夏時間が始まるときのギャップ時間。簡単な操作のために複雑な計算を実行しなければなりません。
  5. ほとんどのメソッドで有効な値としてnullを受け入れます。微妙なバグにつながります。

より詳細な比較については、 - を参照してください。

Java 8 Date/Timeライブラリのパフォーマンス(およびJoda-Time 2.3とj.u.Calendar) 。 & Java 8の新しいDate&Time API

39
OO7