java.util.GregorianCalendarのガイド

java.util.GregorianCalendarへのガイド

1. 前書き

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

2. GregorianCalendar

GregorianCalendarは、抽象クラスjava.util.Calendarの具体的な実装です。 当然のことながら、グレゴリオ暦is the most widely used civil calendar in the world. 

2.1. インスタンスの取得

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

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

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

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

new GregorianCalendar();

year, month, dayOfMonth, hourOfDay, minuteを指定し、デフォルトのロケールでデフォルトのタイムゾーンに秒を指定できます。

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

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

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

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のインスタンスを取得します。

Using getCalendarType() we can get the type of the calendar instance.使用可能なカレンダータイプは、「gregory」、「buddhist」、および「Japanese」です。

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

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

このGregorianCalendar.と同じタイムライン上のポイントを表すCalling toZonedDateTime() we can convert the calendar object into a ZonedDateTime object

2.3. 日付の変更

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

カレンダーの内部ルールセットに基づくThe add() method allows us to add time to the calendar in a specified unit

@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);
}

We can directly set a calendar field to a specified value using the set() method.ミリ秒単位のカレンダーの時間値は、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:datexsd:timexsd:dateTimeなどの基本的なXSDスキーマタイプのマッピングに役立ちます。

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)指定されたカレンダーフィールドの最小最大値を返します。 2月の日数は28日しかないため、DAY_OF_MONTHフィールドの場合は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で表されるyear of the week を返します。

    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の特定の側面について説明しました。

いつものように、サンプルコードはover on GitHubで利用できます。