1. 序章

このチュートリアルでは、GregorianCalendarクラスを簡単に見ていきます。

2. GregorianCalendar

GregorianCalendar は、抽象クラスjava.util.Calendarの具体的な実装です。 当然のことながら、グレゴリオ暦最も広く使用されている市民ですカレンダー世界中。 

2.1. インスタンスの取得

GregorianCalendarのインスタンスを取得するために使用できるオプションは2つあります: Calendar.getInstance()とコンストラクターの1つを使用します。

静的ファクトリメソッドCalendar.getInstance()を使用することは、デフォルトのロケールに依存するインスタンスを返すため、推奨されるアプローチではありません。

タイ語の場合はBuddhistCalendar、日本語の場合はJapaneseImperialCalendarが返される場合があります。 返されるインスタンスのタイプがわからない場合、 ClassCastException が発生する可能性があります。

@Test(expected = ClassCastException.class)
public void test_Class_Cast_Exception() {
    TimeZone tz = TimeZone.getTimeZone("GMT+9:00");
    Locale loc = new Locale("ja", "JP", "JP");
    Calendar calendar = Calendar.getInstance(loc);
    GregorianCalendar gc = (GregorianCalendar) calendar;
}

7つのオーバーロードされたコンストラクターのいずれかを使用して、 Calendar オブジェクトを、オペレーティングシステムのロケールに応じてデフォルトの日付と時刻で初期化するか、日付、時刻、ロケール、およびタイムゾーンの組み合わせを指定できます。

GregorianCalendarオブジェクトをインスタンス化できるさまざまなコンストラクターを理解しましょう。

デフォルトのコンストラクターは、オペレーティングシステムのタイムゾーンとロケールの現在の日付と時刻でカレンダーを初期化します。

new GregorianCalendar();

デフォルトのロケールのデフォルトのタイムゾーンには、年、月、dayOfMonth、hourOfDay、minute 、およびsecondを指定できます。

new GregorianCalendar(2018, 6, 27, 16, 16, 47);

これらのパラメーターを持たない他のコンストラクターがあるため、 hourOfDay、minute 、およびsecondを指定する必要がないことに注意してください。

タイムゾーンをパラメータとして渡して、デフォルトのロケールでこのタイムゾーンにカレンダーを作成できます。

new GregorianCalendar(TimeZone.getTimeZone("GMT+5:30"));

ロケールをパラメータとして渡して、デフォルトのタイムゾーンでこのロケールにカレンダーを作成できます。

new GregorianCalendar(new Locale("en", "IN"));

最後に、タイムゾーンとロケールの両方をパラメーターとして渡すことができます。

new GregorianCalendar(TimeZone.getTimeZone("GMT+5:30"), new Locale("en", "IN"));

2.2. Java8の新しいメソッド

Java 8では、GregorianCalendarに新しいメソッドが導入されました。

from()メソッドは、ZonedDateTimeオブジェクトからデフォルトロケールのGregorianCalendarのインスタンスを取得します。

getCalendarType()を使用して、カレンダーインスタンスのタイプを取得できます。使用可能なカレンダータイプは、「gregory」、「buddhist」、および「Japanese」です。

たとえば、これを使用して、アプリケーションロジックに進む前に、特定のタイプのカレンダーがあることを確認できます。

@Test
public void test_Calendar_Return_Type_Valid() {
    Calendar calendar = Calendar.getInstance();
    assert ("gregory".equals(calendar.getCalendarType()));
}

toZonedDateTime()を呼び出すと、カレンダーオブジェクトをこのGregorianCalendar。と同じタイムライン上のポイントを表すZonedDateTimeオブジェクトに変換できます。

2.3. 日付の変更

カレンダーフィールドは、メソッド add() roll()、および set()を使用して変更できます。

add()メソッドを使用すると、カレンダーの内部ルールセットに基づいて、指定した単位でカレンダーに時間を追加できます。

@Test
public void test_whenAddOneDay_thenMonthIsChanged() {
    int finalDay1 = 1;
    int finalMonthJul = 6; 
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 5, 30);
    calendarExpected.add(Calendar.DATE, 1);
    System.out.println(calendarExpected.getTime());
 
    assertEquals(calendarExpected.get(Calendar.DATE), finalDay1);
    assertEquals(calendarExpected.get(Calendar.MONTH), finalMonthJul);
}

add()メソッドを使用して、カレンダーオブジェクトから時間を減算することもできます。

@Test
public void test_whenSubtractOneDay_thenMonthIsChanged() {
    int finalDay31 = 31;
    int finalMonthMay = 4; 
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 5, 1);
    calendarExpected.add(Calendar.DATE, -1);

    assertEquals(calendarExpected.get(Calendar.DATE), finalDay31);
    assertEquals(calendarExpected.get(Calendar.MONTH), finalMonthMay);
}

add()メソッドを実行すると、カレンダーのミリ秒とすべてのフィールドが即座に再計算されます。

add()を使用すると、上位のカレンダーフィールド(この場合はMONTH)も変更される可能性があることに注意してください。

roll()メソッドは、大きなフィールドを変更せずに、指定されたカレンダーフィールドに署名された金額を追加します。 フィールドが大きいほど、時間の単位が大きくなります。 たとえば、DAY_OF_MONTHHOUR。よりも大きいです。

月をロールアップする方法の例を見てみましょう。

この場合、より大きなフィールドであるYEARはインクリメントされません。

@Test
public void test_whenRollUpOneMonth_thenYearIsUnchanged() {
    int rolledUpMonthJuly = 7, orginalYear2018 = 2018;
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
    calendarExpected.roll(Calendar.MONTH, 1);
 
    assertEquals(calendarExpected.get(Calendar.MONTH), rolledUpMonthJuly);
    assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
}

同様に、月をロールダウンできます。

@Test
public void test_whenRollDownOneMonth_thenYearIsUnchanged() {
    int rolledDownMonthJune = 5, orginalYear2018 = 2018;
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
    calendarExpected.roll(Calendar.MONTH, -1);
 
    assertEquals(calendarExpected.get(Calendar.MONTH), rolledDownMonthJune);
    assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
}

set()メソッドを使用して、カレンダーフィールドを指定された値に直接設定できます。カレンダーのミリ秒単位の時間値は、 get()が次に呼び出されるまで再計算されません。 ] getTime() add()または roll()が作成されます。

したがって、 set()を複数回呼び出しても、不要な計算はトリガーされません。

月のフィールドを3に設定する例を見てみましょう(つまり、 4月):

@Test
public void test_setMonth() {
    GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
    GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
    calendarExpected.set(Calendar.MONTH, 3);
    Date expectedDate = calendarExpected.getTime();

    assertEquals(expectedDate, calendarDemo.setMonth(calendarActual, 3));
}

2.4. XMLGregorianCalendarの操作

JAXBを使用すると、JavaクラスをXML表現にマッピングできます。 javax.xml.datatype.XMLGregorianCalendar タイプは、 xsd:date xsd:time xsdなどの基本的なXSDスキーマタイプのマッピングに役立ちます。 :dateTime

GregorianCalendarタイプからXMLGregorianCalendarタイプに変換する例を見てみましょう。

@Test
public void test_toXMLGregorianCalendar() throws Exception {
    GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
    DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
    GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
    XMLGregorianCalendar expectedXMLGregorianCalendar = datatypeFactory
      .newXMLGregorianCalendar(calendarExpected);
 
    assertEquals(
      expectedXMLGregorianCalendar, 
      alendarDemo.toXMLGregorianCalendar(calendarActual));
}

カレンダーオブジェクトがXML形式に変換されると、メッセージングやWebサービス呼び出しなど、日付をシリアル化する必要があるすべてのユースケースで使用できます。

XMLGregorianCalendarタイプからGregorianCalendarに変換する方法の例を見てみましょう。

@Test
public void test_toDate() throws DatatypeConfigurationException {
    GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
    DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
    XMLGregorianCalendar expectedXMLGregorianCalendar = datatypeFactory
      .newXMLGregorianCalendar(calendarActual);
    expectedXMLGregorianCalendar.toGregorianCalendar().getTime();
    assertEquals(
      calendarActual.getTime(), 
      expectedXMLGregorianCalendar.toGregorianCalendar().getTime() );
}

2.5. 日付の比較

CalendarクラスのcompareTo()メソッドを使用して、日付を比較できます。 結果は、基準日が将来の場合は正になり、基準データが次の日付と比較した場合は負になります。

@Test
public void test_Compare_Date_FirstDate_Greater_SecondDate() {
    GregorianCalendar firstDate = new GregorianCalendar(2018, 6, 28);
    GregorianCalendar secondDate = new GregorianCalendar(2018, 5, 28);
    assertTrue(1 == firstDate.compareTo(secondDate));
}

@Test
public void test_Compare_Date_FirstDate_Smaller_SecondDate() {
    GregorianCalendar firstDate = new GregorianCalendar(2018, 5, 28);
    GregorianCalendar secondDate = new GregorianCalendar(2018, 6, 28);
    assertTrue(-1 == firstDate.compareTo(secondDate));
}

@Test
public void test_Compare_Date_Both_Dates_Equal() {
    GregorianCalendar firstDate = new GregorianCalendar(2018, 6, 28);
    GregorianCalendar secondDate = new GregorianCalendar(2018, 6, 28);
    assertTrue(0 == firstDate.compareTo(secondDate));
}

2.6. 日付のフォーマット

ZonedDateTimeDateTimeFormatterの組み合わせを使用して、 GregorianCalendar を特定の形式に変換し、目的の出力を取得できます。

@Test
public void test_dateFormatdMMMuuuu() {
    String expectedDate = new GregorianCalendar(2018, 6, 28).toZonedDateTime()
      .format(DateTimeFormatter.ofPattern("d MMM uuuu"));
    assertEquals("28 Jul 2018", expectedDate);
}

2.7. カレンダーに関する情報の取得

GregorianCalendar は、さまざまなカレンダー属性をフェッチするために使用できるいくつかのgetメソッドを提供します。 私たちが持っているさまざまなオプションを見てみましょう:

  • getActualMaximum(int field)– は、現在の時刻値を考慮して、指定されたカレンダーフィールドの最大値を返します。 次の例では、6月には30日があるため、DAY_OF_MONTHフィールドに値30が返されます。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(30 == calendar.getActualMaximum(calendar.DAY_OF_MONTH));
  • getActualMinimum(int field)– は、現在の時刻の値を考慮して、指定されたカレンダーフィールドの最小値を返します。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getActualMinimum(calendar.DAY_OF_MONTH));
  • getGreatestMinimum(int field)– は、指定されたカレンダーフィールドの最大最小値を返します。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getGreatestMinimum(calendar.DAY_OF_MONTH));
  • getLeastMaximum(int field)–指定されたカレンダーフィールドの最小の最大値を返します。  DAY_OF_MONTH フィールドの場合、2月の日数は28日しかないため、これは28日です。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(28 == calendar.getLeastMaximum(calendar.DAY_OF_MONTH));
  • getMaximum(int field)– は、指定されたカレンダーフィールドの最大値を返します。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(31 == calendar.getMaximum(calendar.DAY_OF_MONTH));
  • getMinimum(int field)– は、指定されたカレンダーフィールドの最小値を返します。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getMinimum(calendar.DAY_OF_MONTH));
  • getWeekYear()– は、このGregorianCalendarで表されるを返します。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(2018 == calendar.getWeekYear());
  • getWeeksInWeekYear()– は、暦年の週の週数を返します。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(52 == calendar.getWeeksInWeekYear());
  • isLeapYear()– は、うるう年の場合にtrueを返します。
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(false == calendar.isLeapYear(calendar.YEAR));

3. 結論

この記事では、GregorianCalendarの特定の側面について説明しました。

いつものように、サンプルコードはGitHubから入手できます。