Javaで時間なしで日付を取得する

Javaで時間のない日付を取得する

1. 前書き

この短いチュートリアルでは、Javaで時間をかけずにDateを取得する方法を示します。

Java8で新しいtimeAPIがリリースされた後、状況が少し変わったため、Java8の前後でこれを行う方法を示します。

2. Java 8より前

Java 8より前は、Joda-timeのようなサードパーティのライブラリを使用していない限り、時間なしでDateを取得する直接的な方法はありませんでした。

これは、the Date class in Java is a representation of a specific instant in time, expressed in millisecondsが原因です。 したがって、これにより、Dateの時間を無視することができなくなります。

次のセクションでは、この問題に取り組むためのいくつかの一般的な回避策を示します。

2.1. Calendarの使用

時間なしでDateを取得する最も一般的な方法の1つは、use the Calendar class to set the time to zeroを使用することです。 これを行うことにより、1日の始めに設定された時刻で、クリーンな日付を取得します。

コードで見てみましょう:

public static Date getDateWithoutTimeUsingCalendar() {
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);

    return calendar.getTime();
}

このメソッドを呼び出すと、次のような日付が取得されます。

Sat Jun 23 00:00:00 CEST 2018

ご覧のとおり、時刻がゼロに設定された完全な日付が返されますが、we can’t ignore the timeです。

また、返されるDateに時間が設定されていないことを確認するために、次のテストを作成できます。

@Test
public void whenGettingDateWithoutTimeUsingCalendar_thenReturnDateWithoutTime() {
    Date dateWithoutTime = DateWithoutTime.getDateWithoutTimeUsingCalendar();

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(dateWithoutTime);
    int day = calendar.get(Calendar.DAY_OF_MONTH);

    calendar.setTimeInMillis(dateWithoutTime.getTime() + MILLISECONDS_PER_DAY - 1);
    assertEquals(day, calendar.get(Calendar.DAY_OF_MONTH));

    calendar.setTimeInMillis(dateWithoutTime.getTime() + MILLISECONDS_PER_DAY);
    assertNotEquals(day, calendar.get(Calendar.DAY_OF_MONTH));
}

ご覧のとおり、1日のミリ秒から1ミリ秒を引いた日付を追加すると、同じ日が取得されますが、1日を追加すると翌日が取得されます。

2.2. フォーマッタの使用

これを行う別の方法は、formatting a Date into a String without the time and then convert that String back to a Dateによるものです。 Stringは時刻なしでフォーマットされているため、変換されたDateの時刻はゼロに設定されます。

それを実装して、どのように機能するかを見てみましょう。

public static Date getDateWithoutTimeUsingFormat()
  throws ParseException {
    SimpleDateFormat formatter = new SimpleDateFormat(
      "dd/MM/yyyy");
    return formatter.parse(formatter.format(new Date()));
}

この実装は、前のセクションで示したメソッドと同じ結果を返します。

Sat Jun 23 00:00:00 CEST 2018

繰り返しになりますが、以前と同じようにテストを使用して、返されたDateに時間がないことを確認できます。

3. Java 8の使い方

Java 8の新しい時間APIのリリースにより、時間なしで日付を取得する簡単な方法があります。 この新しいAPIがもたらした新機能の1つは、時間の有無に関係なく日付を処理したり、時間のみを処理したりするためのクラスがいくつかあることです。

この記事では、クラスLocalDateに焦点を当てます。これは、必要なもの、つまり時刻のない日付を正確に表します。

この例でそれを見てみましょう:

public static LocalDate getLocalDate() {
    return LocalDate.now();
}

このメソッドは、次の日付表現を持つLocalDateオブジェクトを返します。

2018-06-23

ご覧のとおり、日付the time is completely ignoredのみが返されます。

繰り返しますが、前と同じようにテストして、このメソッドが期待どおりに機能することを確認しましょう。

@Test
public void whenGettingLocalDate_thenReturnDateWithoutTime() {
    LocalDate localDate = DateWithoutTime.getLocalDate();

    long millisLocalDate = localDate
      .atStartOfDay()
      .toInstant(OffsetDateTime
        .now()
        .getOffset())
      .toEpochMilli();

    Calendar calendar = Calendar.getInstance();

    calendar.setTimeInMillis(
      millisLocalDate + MILLISECONDS_PER_DAY - 1);
    assertEquals(
      localDate.getDayOfMonth(),
      calendar.get(Calendar.DAY_OF_MONTH));

    calendar.setTimeInMillis(millisLocalDate + MILLISECONDS_PER_DAY);
    assertNotEquals(
      localDate.getDayOfMonth(),
      calendar.get(Calendar.DAY_OF_MONTH));
}

4. 結論

この記事では、Javaで時間をかけずにDateを取得する方法を示しました。 最初に、Java 8より前にJava 8を使用する方法を示しました。

記事で実装された例でわかるように、Java 8 should be always the preferred optionを使用します。これは、時間のない日付を処理するための特定の表現があるためです。

いつものように、例の完全なソースコードはover on GitHubで入手できます。