Joda-Timeとは何か、日付ライブラリとJava 8への置き換え

著者: IT Sectr 公開日: 2026-07-14 読了時間: 10 分

Joda-Timeは、Stephen Colebourneが手間のかかるjava.util.Dateやjava.util.Calendarの代替として作成した、Javaで日付や時刻を扱うためのライブラリです。Java 8のリリース以前、このライブラリはAndroidアプリケーションを含む産業レベルの開発における日付処理の事実上の標準でした。Oracle Java Magazine(2023)によると、Android API 26のリリース後2年以内に60%以上のプロジェクトがJoda-Timeからjava.timeに移行しました。

ポイント

  • Joda-Timeは、Java 8でのjava.timeの前踊となる日付・時刻処理ライブラリ
  • 不変クラス — DateTime、LocalDate、LocalTime、LocalDateTimeはスレッド安全性を保証
  • タイムゾーン対応 — 自動更新される組み込みタイムゾーンデータベース
  • 移行 — java.time (JSR-310)はJoda-Timeを完全に置き換え、ライブラリの作者は移行を推奨
  • Android — Joda-TimeはAPI 1から動作するが、Android 8+ (API 26)ではjava.timeが推奨

Joda-Timeとは何か?

Joda-Timeは、Java言語でjava.util.Dateやjava.util.Calendarクラスの品質高い代替を提供するオープンソースライブラリ (Apache 2.0) です。このプロジェクトはStephen Colebourneによって2004年に、変更可能性、フォーマットの複雑さ、タイムゾーンサポートの制限など、標準の日付・時刻APIの多くの問題に対して作られました。このライブラリはJavaコミュニティで広く受け入れられ、大規模エンタプライズシステムやAndroidアプリケーションを含む数千のプロジェクトで使用されました。ここでは、組み込みの日付処理ツールは特に不便でした。2014年のJava 8のリリースとjava.timeパッケージ (JSR-310) の登場以来、このライブラリはメンテナンスモードに置かれています — 新しい機能は追加されず、既存の機能は新しいAPIで完全にカバーされています。

ライブラリのアーキテクチャ

Joda-Timeは不変の原理に基づいています。各日付または時刻オブジェクトは作成後に変更できません。日を追加する、月を変更する、タイムゾーンを設定するといったいかなる操作でも、新しいオブジェクトが返され、元のオブジェクトは変わりません。このアプローチにより、変更可能なjava.util.Dateやjava.util.Calendarに特徴的だった、意図しないオブジェクトの変更に伴うエラーの種類が完全に解消されます。また、不変の設計により、追加のシンクロニゼーションなしでライブラリがスレッドセーフになります。

Joda-Timeの主なクラス

このライブラリは、様々なシナリオに対応するいくつかの主なクラスを提供しています。DateTime — タイムゾーン付きの完全な日付と時刻、LocalDate — 時刻なしの日付のみ、LocalTime — 日付なしの時刻のみ、LocalDateTime — タイムゾーンに縛られない日付と時刻。さらに、インターバル (Interval)、期間 (Period)、流れ (Duration) を扱うクラスが含まれており、様々な単位で時刻間の差を計算できます。各クラスは一貫した処理のためにReadableInstantまたはReadablePartialインターフェースを実装しています。

Joda-Timeの歴史

Javaでの標準日付APIの問題は、プラットフォームの始まりから知られていました。java.util.Datejava.util.Calendarクラスには根本的な欠陷がありました。月は0から番号が始まり、Dateは日付と時刻の両方を同時に表し、Calendarは変更可能で複雑な設定が必要でした。SimpleDateFormatを通じたフォーマットはスレッドセーフではありませんでした — マルチスレッドアプリケーションでは、これが正しくない日付解析につながりました。Stephen Colebourneは、日付を多く使うプロジェクトに取り組んだ経験から、これらの問題をすべて解決する代替となるものを作ることを決めました。

InfoQ(2014)のインタビューによると、Colebourneは初めてのパブリックリリースの前に、1年以上にわたって製品プロジェクトでJoda-Timeをテストしました。初版は2004年にリリースされ、すぐにコミュニティの注目を集めました。2010年までに、SpringやHibernateなどのフレームワークを含む大多数のJavaプロジェクトで、このライブラリは標準的な依存関係となりました。Joda-Timeの成功は、Java 8に含まれたJSR-310仮格 (Date and Time API) に直接影響を与えました — 同じStephen Colebourneが仮格リーダーを務めました。

Javaエコシステムへの影響

Joda-Timeは日付の問題を解決しただけではありません — JavaにおけるAPI設計への考え方を変えました。このライブラリによって示された不変のバリューオブジェクトの概念は、Java 8におけるすべての新しいAPIの標準として採用されました。さらに、Joda-Timeの人気はOracleに、コミュニティが低品質な標準ライブラリを受け入れる気はないことを示しました — Joda-Timeの後、Javaのファイル処理 (NIO.2)、時刻 (java.time)、オプショナル値 (Optional) のためのAPIが再デザインされました。

Joda-Timeライブラリの主な機能

Joda-Timeは、Java 8以前には標準ライブラリで利用できなかった機能を提供しています。主なメリットには、自動夏時間対応付きの200以上のタイムゾーンサポート、パターンやロケールに対応した豊富なフォーマットAPI、さらに様々な単位(年、月、日、時)の日付間の期間計算があります。特に注目すべきは、インターバルシステムです。Interval(2つの瞬間の間の期間)、Period(カレンダー単位での差)、Duration(ミリ秒での正確な長さ)。

フォーマットと解析

Joda-TimeのDateTimeFormatterクラスは、java.text.SimpleDateFormatとは異なり、スレッドセーフな日付フォーマットを提供します。フォーマッタは、パターン(例えば、“yyyy-MM-dd HH:mm:ss”)またはロケール出力のためのスタイル(SHORT、MEDIUM、LONG、FULL)を通じて作成できます。また、フォーマッタのキャッシングをサポートしており、高負荷アプリケーションでのパフォーマンスが向上します。文字列からの日付解析は、厳密さの制御で実行され、不完全または不正な日付を許可または拒否できます。

インターバルと計算

Joda-Timeの強みの一つは、時間インターバルの扱いです。Intervalクラスは、2つの瞬間の間の正確な時間の期間を表し、置き合わせや結合、収められているかの確認をサポートします。PeriodはIntervalとは異なり、カレンダー単位で動作します。例えば、3月1日と4月1日の差はまったく1ヶ月ですが、期間では28–31日になりうるます。一方Durationは、カレンダーに縛られず、ミリ秒での正確な長さを表し、操作実行時間の測定に適しています。

java
import org.joda.time.*;
import org.joda.time.format.*;

DateTime now = new DateTime();
DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
String formatted = fmt.print(now);

DateTime nextWeek = now.plusWeeks(1);
Period period = new Period(now, nextWeek);
int days = period.getDays(); // 日 = 7

Interval interval = new Interval(now, nextWeek);
boolean contains = interval.contains(now); // 真

Joda-Timeとjava.timeの比較

java.timeパッケージ (JSR-310) は、同じ作者であるStephen Colebourneによって開発され、Joda-Timeの最も優れたアイデアを十年の運用経験とともに取り入れています。両方のAPIは不変クラスを使用し、タイムゾーンをサポートし、豊富な操作を提供しています。ただし、java.timeはJava標準ライブラリに完全統合されており、外部依存は不要で、より一貫した名称付けシステムを使用しています。ReadableInstantの代わりにInstant、LocalDateの代わりにLocalDate(名称は保持)、DateTimeの代わりにZonedDateTimeです。

特徴Joda-Timejava.time
リリース年20042014 (Java 8)
状態メンテナンス現在も開発中
基本日付/時刻DateTimeZonedDateTime
日付のみLocalDateLocalDate
不変性はいはい
フォーマットDateTimeFormatterDateTimeFormatter
日付の差Period / DurationPeriod / Duration

主な違い

java.timeは、Joda-Timeのいくつかのアーキテクチャ的決定を修正しています。まず、java.timeはnullを返すメソッドと欠落値の混乱を解消し、代わりにOptionalを使用します。次に、Chronologyインターフェースを通じて、代替カレンダーシステム(日本、タイ、イスラム)のサポートが追加されています。さらに、java.timeにはカレンダーに縛られずにUTC時刻を扱うためのInstantクラスが含まれており、ネットワークプロトコルやデータベースとの統合が簡素化されます。AndroidではAPI 26 (Android 8.0) 以降はjava.timeを使用することが推奨され、古いバージョンではdesugaringを使用します。

Joda-Timeからjava.timeへの移行

Joda-Timeからjava.timeへの移行は、ライブラリの作者ができるだけ安全で予測可能にしようとしたプロセスです。大多数のクラスには直接対応するものがあります。DateTime → ZonedDateTime、LocalDate → LocalDate(名称は同じ)、LocalTime → LocalTime、DateTimeZone → ZoneId、Period → Period、Duration → Duration。主な変更は、オブジェクトの作成方法とメソッド名に関係しています。例えば、`now.toDate()`の代わりに`Date.from(instant)`を使い、`DateTime.now()`は`ZonedDateTime.now()`に置き換えられます。

ステップバイステップの移行策略

移行は、Joda-Timeを薄い抽象レイヤーにアイソレートすることから始めることをお勧めします。これにより、コードベース全体を触らずに、ライブラリを段階的に置き換えることができます。最初のステップは通常、LocalDateとLocalTimeの扱いを置き換えることです。これらのクラスは、両ライブラリ間の違いが最も少ないからです。第2段階ではDateTime(ZonedDateTimeへ)とタイムゾーンを移行します。第3段階ではInterval、Period、Durationを置き換えます。ここでは夏時間の動作をよく確認する必要があります。移行完了後、Joda-Timeはプロジェクトの依存関係から完全に削除されます。

kotlin
// Joda-Time (移行前)
val dateTime = DateTime.now(DateTimeZone.forID("Europe/Moscow"))
val formatted = dateTime.toString("dd.MM.yyyy")
val plusDay = dateTime.plusDays(1)

// java.time (移行後)
val zonedDateTime = ZonedDateTime.now(ZoneId.of("Europe/Moscow"))
val formatted2 = zonedDateTime.format(
    DateTimeFormatter.ofPattern("dd.MM.yyyy")
)
val plusDay2 = zonedDateTime.plusDays(1)

移行ツール

Joda-Timeからjava.timeへの移行を簡素化するユーティリティがいくつか存在します。OpenRewrite (Moderne作) はorg.openrewrite.java.migrate.JodaTimeToJavaTimeレシピを通じて自動移行をサポートします。プログラムのロジックを保持しながら、クラス、メソッド、インポートを置き換えます。Gradleプロジェクトでは、de.fayard.refreshVersionsプラグインにも移行ルールが含まれています。手動では、IDEAを使って移行するのが最も簡単です。Java Time Migration AssistantプラグインがJoda-Timeの呼出しをハイライトし、対応するjava.timeの置き換えを提案します。手動の置き換えに比べて2–3倍速くなります。

Joda-Timeコード例

AndroidアプリケーションでJoda-Timeを使った実践的な例を見てみましょう。このライブラリは、ローカル標準に従った日付フォーマット、ユーザーの年齢計算、イベントの期間確定、2つの日付間のインターバル計算に特に役立ちます。すべての例では不変オブジェクトを使用しており、各呼出しで新しいインスタンスが返され、元のオブジェクトは変わりません。

kotlin
// ユーザーの年齢を計算
val birthDate = LocalDate.parse("1990-05-15")
val today = LocalDate.now()
val age = Years.yearsBetween(birthDate, today).getYears()
// 年齢 == 36

// ユーザーのロケールでフォーマット
val dateTime = DateTime.now()
val formatter = DateTimeFormat.forStyle("MM").withLocale(Locale.getDefault())
val localized = formatter.print(dateTime)

インターバルの扱い

Joda-Timeのインターバルは、時間インターバルの重なり確認、置き合わせの計算、最も近いイベントの検索などのタスクを効率的に解決できます。例えば、カレンダーアプリを開発する際に、新しいイベントが既存のイベントと重なっているか確認できます。Intervalクラスはcontains、overlaps、gap、abutsの操作をサポートしており、abutsはインターバルが境界で接しているかを示します。Durationは、2つの瞬間の間の長さをミリ秒単位で測るために使用されます。

java
// インターバルの重なりを確認
Interval meeting1 = new Interval(
    new DateTime(2026, 7, 21, 10, 0),
    new DateTime(2026, 7, 21, 11, 0)
);
Interval meeting2 = new Interval(
    new DateTime(2026, 7, 21, 10, 30),
    new DateTime(2026, 7, 21, 11, 30)
);

boolean overlaps = meeting1.overlaps(meeting2); // 真
Duration gap = meeting1.gap(meeting2); // ヌル (隙間なし)

よくある質問

Joda-Timeとは何か、なぜ必要なのか?

Joda-Timeは、Java 8のリリース以前に作られた、Javaで日付と時刻を扱うためのライブラリです。java.util.Dateやjava.util.Calendarの欠点(変更可能性、0からの月の番号、完全なタイムゾーンサポートの欠如、非スレッドセーフなフォーマット)を修正しました。

Joda-Timeとjava.timeの違いは何ですか?

Java.time (JSR-310)は、同じ作者によって開発されたJoda-Timeの後継です。主な違いは、java.timeはJava 8+標準ライブラリに組み込まれており、より一貫した名称付けシステムを使用し、代替カレンダーシステムをサポートし、UTC時刻を扱うためのInstantクラスを含めています。

新しいプロジェクトでJoda-Timeを使うべきですか?

いいえ、新しいプロジェクトではjava.timeを使用することをお勧めします。Joda-Timeは2014年からメンテナンスモードで、新しい機能は追加されていません。Android API 26+では、java.timeがネイティブで利用でき、古いバージョンではdesugaringを使用します。API 19+のデバイスでjava.timeを使えるようにするメカニズムです。

Joda-Timeからjava.timeへコードを移行する方法は?

移行は段階的に実行します。Joda-Timeを抽象化し、まずLocalDateとLocalTimeを置き換え、次にDateTime → ZonedDateTime、最後にPeriod、Duration、Intervalを置き換えます。OpenRewriteツールはJodaTimeToJavaTimeレシピを通じて自動移行をサポートし、プロセスを2–3倍加速します。

Joda-Timeのどのクラスがjava.timeに対応しますか?

DateTime → ZonedDateTime、LocalDate → LocalDate(一致)、LocalTime → LocalTime、LocalDateTime → LocalDateTime、DateTimeZone → ZoneId、Interval → 直接の対応はなし(Instant + Durationの組み合わせを使用)、Period → Period、Duration → Duration。メソッド名も似ています。plusDaysminusMonthswithZoneが両ライブラリで利用可能です。

まとめ

  • Joda-TimeはJavaの日付・時刻ライブラリで、Java 8以前に標準となり、JSR-310仮格に直接影響を与えました
  • 不変の設計 — すべてのJoda-Timeクラスは不変で、スレッド安全性を確保し、意図せざるオブジェクトの変更を防ぎます
  • 主なクラス — DateTime、LocalDate、LocalTime、LocalDateTime、Period、Duration、Intervalがすべての日付・時刻シナリオをカバー
  • タイムゾーン対応 — 200以上のタイムゾーンを収録した組み込みデータベース、自動夏時間対応と更新を実現
  • java.timeへの移行 — すべてのプロジェクトに推奨。OpenRewriteツールとIDEの機能を使って段階的に実行
  • Android互換性 — Joda-TimeはAPI 1から動作するが、API 26+ではjava.timeが推奨、古いバージョンではdesugaringで利用可能
  • 歴史的意義 — Joda-TimeはJavaにおけるAPI設計への考え方を変え、不変のバリューオブジェクトの利点をコミュニティに示した

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください