この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:T
更新日時:2026-06-11 07:10:02

タイトル: Calendar.getInstance
SEOタイトル: Java Calendar.getInstance() 使い方|タイムゾーン/ロケール指定・年月日曜日の取得・LocalDate との比較

この記事の要点
  • Calendar.getInstance() はデフォルトのタイムゾーン・ロケールで Calendar を取得する static ファクトリメソッド
  • cal.get(Calendar.YEAR) のように定数で年・月・日・曜日を取り出せる。月は 0 始まりなので注意
  • タイムゾーンやロケールを明示する場合は getInstance(TimeZone, Locale) を使う
  • Java 8 以降は LocalDate / ZonedDateTime が推奨。新規コードは java.time を使うべき

Calendar.getInstance() とは

java.util.Calendar クラスの getInstance() は、Java で日付・時刻を扱うためのインスタンスを生成する static ファクトリメソッドです。new Calendar() はできない(Calendar は抽象クラス)ため、生成はこのメソッド経由で行います。

返却される実体は環境のロケールに応じた具象クラスで、日本環境では通常 GregorianCalendar が返ります。

オーバーロード一覧

シグネチャ説明
static Calendar getInstance()デフォルトのタイムゾーンおよびロケールを使用してカレンダを取得
static Calendar getInstance(Locale aLocale)デフォルトのタイムゾーンおよび指定ロケールを使用
static Calendar getInstance(TimeZone zone)指定タイムゾーンおよびデフォルトロケールを使用
static Calendar getInstance(TimeZone zone, Locale aLocale)指定タイムゾーンおよびロケールを使用

基本的な使い方

取得したインスタンスから get(int field) でフィールド単位の値を取り出します。フィールドには Calendar.YEAR など定数を渡します。

import java.util.Calendar;

public class CalendarSample {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();

        System.out.println("YEAR        : " + cal.get(Calendar.YEAR));
        System.out.println("MONTH       : " + cal.get(Calendar.MONTH));        // 0 始まり
        System.out.println("DATE        : " + cal.get(Calendar.DATE));
        System.out.println("HOUR_OF_DAY : " + cal.get(Calendar.HOUR_OF_DAY));
        System.out.println("MINUTE      : " + cal.get(Calendar.MINUTE));
        System.out.println("DAY_OF_WEEK : " + cal.get(Calendar.DAY_OF_WEEK)); // 1=日曜
    }
}

出力例

YEAR        : 2026
MONTH       : 5       # 6月 (0 始まり)
DATE        : 11
HOUR_OF_DAY : 14
MINUTE      : 32
DAY_OF_WEEK : 5       # 木曜日

月の数値が 1 ずれる理由

初学者がほぼ必ず引っかかるのが、MONTH が 0 始まりである点です。1 月は 0、12 月は 11 として返却されます。表示用に整形する場合は + 1 するか、定数 Calendar.JANUARYDECEMBER で比較します。

Calendar cal = Calendar.getInstance();
int month1Based = cal.get(Calendar.MONTH) + 1;
System.out.println("表示用の月: " + month1Based);

if (cal.get(Calendar.MONTH) == Calendar.DECEMBER) {
    System.out.println("年末です");
}

曜日の数値マッピング

DAY_OF_WEEK は 1〜7 で返り、対応関係は次の通りです。すべて定数で定義されているので、生数値での比較は避けるのが安全です。

定数曜日
1Calendar.SUNDAY
2Calendar.MONDAY
3Calendar.TUESDAY
4Calendar.WEDNESDAY
5Calendar.THURSDAY
6Calendar.FRIDAY
7Calendar.SATURDAY

タイムゾーン・ロケールの指定

サーバーのタイムゾーン設定に依存させたくない場合は、明示的に TimeZone を渡します。バッチ処理や国際対応のアプリでは特に重要です。

import java.util.Calendar;
import java.util.Locale;
import java.util.TimeZone;

Calendar jp = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo"), Locale.JAPAN);
Calendar utc = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

System.out.println(jp.getTime());
System.out.println(utc.getTime());

日付の加算・減算

add(int field, int amount) でフィールド単位の加減算ができます。「1 か月後」「3 日前」などの相対日付を求める定番手段です。

Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, 1);   // 1 か月後
cal.add(Calendar.DATE, -3);   // さらに 3 日前
System.out.println(cal.getTime());

Java 8 以降は LocalDate を使うのが推奨

Java 8 で java.time パッケージが導入されたため、新規コードでは Calendar ではなく LocalDate / LocalDateTime / ZonedDateTime を使うのが推奨です。Calendar はミュータブル(状態を変更できる)でスレッドセーフでなく、月が 0 始まりという落とし穴もあるため、保守性で大きく劣ります。

import java.time.LocalDate;
import java.time.ZonedDateTime;
import java.time.ZoneId;

LocalDate today = LocalDate.now();
System.out.println(today.getYear() + "/" + today.getMonthValue() + "/" + today.getDayOfMonth());

ZonedDateTime jpNow = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println(jpNow);

既存コードの保守で Calendar を扱うケース、サードパーティ API が Calendar を要求するケースは残りますが、自分で書く処理は java.time に揃えるのが安全です。

Calendar と Date と LocalDate の対応関係

Java の日時 API は歴史的に複雑です。整理しておきます。java.util.Date は最も古いクラスで、コンストラクタの多くが非推奨化されており、月の扱いも独特です。Calendar はそれを置き換える目的で導入されましたが、依然としてミュータブルでスレッドセーフでないという欠点を抱えていました。Java 8 で導入された java.time(JSR-310)は、Joda-Time の知見を取り込んだ完全に新しい不変オブジェクト型 API で、Year・YearMonth・LocalDate・LocalTime・LocalDateTime・ZonedDateTime・Instant など用途別に型が分かれています。

相互変換も用意されており、レガシーコードと共存させる場合は Date.from(instant)date.toInstant()Calendar.toInstant() などのブリッジメソッドで橋渡しできます。新規コードからレガシーへ渡すときは、できるだけ境界部分でのみ変換するのが安全な設計です。

よくあるバグと回避方法

初学者が Calendar でハマる代表的な落とし穴を整理します。1 つ目は月の 0 始まり。1 月を 1 と書いてしまい、結果が 2 月になるケースです。2 つ目はset 後の getTime 不整合Calendar は内部状態を遅延計算するため、set を複数回呼んだ直後に get すると意図しない値が返ることがあります。安全のため getTime()get を呼んだ後はもう内部状態が確定すると覚えておきましょう。3 つ目はマルチスレッド時のスレッドセーフ問題Calendar は内部にカレンダー計算用フィールドを持つため、複数スレッドからアクセスすると壊れる可能性があります。ThreadLocal で囲むか、新しい java.time API(不変)に置き換えるのが定石です。

SimpleDateFormat との組み合わせ

表示用に文字列フォーマットしたい場合は SimpleDateFormat と組み合わせます。ただしこのクラスもスレッドセーフではないので、Web アプリケーションで使うときは要注意です。フォーマット文字列にはアルファベットを使い、たとえば yyyy/MM/dd HH:mm:ss なら 4 桁年・2 桁月・2 桁日・24 時間表記の時分秒を意味します。YYYY(大文字)は ISO 週ベース年で yyyy とは別物のため、年末年始に日付がずれる事故が起きるという有名なバグもあります。

パフォーマンスとメモリ

大量のレコードを処理するバッチで毎回 Calendar.getInstance() を呼ぶと、TimeZone と Locale の解決でわずかながらコストがかかります。秒間数万件規模で動くホットパスでは、いったん基準の Calendar を作って clone() で複製する、あるいは java.time の不変オブジェクトに切り替えてキャッシュを効かせる、といった最適化が効果的です。

関連記事