web-dev-qa-db-ja.com

2つのJava.util.Datesを比較して、それらが同じ日にあるかどうかを確認します。

2つのDateを比較し(例:date1date2)、2つのDateが同じ日に共有されている場合はtrue、そうでない場合はfalseになるboolean sameDayを作成する必要があります。

これどうやってするの?ここには混乱の旋風があるようです...そして、可能な限りJDK以外の他の依存関係を引き込むことは避けたいと思います。

明確にするためにdate1date2が同じ年月日を共有している場合、sameDayは真、そうでなければ偽です。これにはタイムゾーンの知識が必要であることを理解しています。

もう一度、明確にするために

date1 = 2008 Jun 03 12:56:03
date2 = 2008 Jun 03 12:59:44
  => sameDate = true

date1 = 2009 Jun 03 12:56:03
date2 = 2008 Jun 03 12:59:44
  => sameDate = false

date1 = 2008 Aug 03 12:00:00
date2 = 2008 Jun 03 12:00:00
  => sameDate = false
220
Jason S
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(date1);
cal2.setTime(date2);
boolean sameDay = cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
                  cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);

「同じ日」は、異なるタイムゾーンを含めることができるときに聞こえるほど単純な概念ではありません。上記のコードは、両方の日付に対して、それが実行されているコンピュータで使用されているタイムゾーンを基準にして日を計算します。これがあなたが必要としているものではない場合、あなたが正確にあなたが「同じ日」で何を意味するのかを決定した後、あなたは関連するタイムゾーンをCalendar.getInstance()呼び出しに渡さなければなりません。

そしてそうです、Joda TimeのLocalDateは全体をもっときれいにそしてより簡単にします(タイムゾーンを含む同じ困難が存在するでしょうが)。

378

どうですか?

SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
return fmt.format(date1).equals(fmt.format(date2));

必要に応じて、タイムゾーンをSimpleDateFormatに設定することもできます。

318
Binil Thomas

これを行うには、 "Apache commons lang"パッケージを使用します(つまり、 org.Apache.commons.lang.time.DateUtils )。

boolean samedate = DateUtils.isSameDay(date1, date2);  //Takes either Calendar or Date objects
149
Brent Watson

日付ごとに ユリウス日数 を計算してからこれらを比較することで、外部依存関係とカレンダー使用によるパフォーマンスへの影響を回避できます。

public static boolean isSameDay(Date date1, Date date2) {

    // Strip out the time part of each date.
    long julianDayNumber1 = date1.getTime() / MILLIS_PER_DAY;
    long julianDayNumber2 = date2.getTime() / MILLIS_PER_DAY;

    // If they now are equal then it is the same day.
    return julianDayNumber1 == julianDayNumber2;
}
22
AntoineJ

ジョダタイム

依存関係を追加することに関しては、私はJava.util.Dateと.Calendarが本当にひどいことを恐れているので、私が新しいプロジェクトに最初にすることはJoda-Timeライブラリを追加することです。 Java 8では、Joda-Timeに着想を得た新しいJava.timeパッケージを使用できます。

Joda-Timeの中心は DateTime クラスです。 Java.util.Dateとは異なり、割り当てられたタイムゾーン( DateTimeZone )を認識します。 j.u.Dateから変換するときは、ゾーンを割り当てます。

DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTimeQuébec = new DateTime( date , zone );

LocalDate

2つの日時が同じ日付になるかどうかを確認する1つの方法は、 LocalDate オブジェクトに変換することです。

変換は割り当てられたタイムゾーンによって異なります。 LocalDateオブジェクトを比較するには、それらが同じゾーンで変換されている必要があります。

これはちょっとした実用的な方法です。

static public Boolean sameDate ( DateTime dt1 , DateTime dt2 )
{
    LocalDate ld1 = new LocalDate( dt1 );
    // LocalDate determination depends on the time zone.
    // So be sure the date-time values are adjusted to the same time zone.
    LocalDate ld2 = new LocalDate( dt2.withZone( dt1.getZone() ) );
    Boolean match = ld1.equals( ld2 );
    return match;
}

最初のDateTimeオブジェクトのタイムゾーンを使用する必要があると想定するのではなく、タイムゾーンを指定することをお勧めします。

static public Boolean sameDate ( DateTimeZone zone , DateTime dt1 , DateTime dt2 )
{
    LocalDate ld1 = new LocalDate( dt1.withZone( zone ) );
    // LocalDate determination depends on the time zone.
    // So be sure the date-time values are adjusted to the same time zone.
    LocalDate ld2 = new LocalDate( dt2.withZone( zone ) );
    return ld1.equals( ld2 );
}

文字列表現

もう1つの方法は、各日時の日付部分のストリング表現を作成してからストリングを比較することです。

繰り返しますが、割り当てられたタイムゾーンは非常に重要です。

DateTimeFormatter formatter = ISODateTimeFormat.date();  // Static method.
String s1 = formatter.print( dateTime1 );
String s2 = formatter.print( dateTime2.withZone( dt1.getZone() )  );
Boolean match = s1.equals( s2 );
return match;

一定の期間

一般的な解決策は、期間を定義してから、その期間にターゲットが含まれているかどうかを確認することです。このサンプルコードはJoda-Time 2.4にあります。 "深夜"関連のクラスは非推奨です。代わりにwithTimeAtStartOfDayメソッドを使用してください。 Joda-Timeは、時間間隔をさまざまな方法で表すための3つのクラスを提供します。間隔、期間、および期間です。

スパンの始まりが包括的で終わりが排他的な「ハーフオープン」アプローチを使用します。

ターゲットのタイムゾーンは、間隔のタイムゾーンとは異なる場合があります。

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime target = new DateTime( 2012, 3, 4, 5, 6, 7, timeZone );
DateTime start = DateTime.now( timeZone ).withTimeAtStartOfDay();
DateTime stop = start.plusDays( 1 ).withTimeAtStartOfDay();
Interval interval = new Interval( start, stop );
boolean containsTarget = interval.contains( target );

Java.time

Java 8以降には Java.time フレームワークが付属しています。 JSR 310によって定義され、ThreeTen-Extraプロジェクトによって拡張されたJoda-Timeに触発されました。 チュートリアル を参照してください。

Joda-Timeのメーカーは、都合がよくなったらすぐにJava.timeに移行するように指示しています。その間、Joda-Timeは活発に維持されているプロジェクトとして続いています。しかし、今後の作業はJoda-TimeではなくJava.timeとThreeTen-Extraでのみ行われることを期待しています。

一言で言えばJava.timeを要約すると…InstantはUTCのタイムライン上の瞬間です。タイムゾーン(ZoneId)を適用してZonedDateTimeオブジェクトを取得します。タイムラインから外れるには、日付と時刻のあいまいな不明確な考えを得るために、 "local"クラスを使用します:LocalDateTimeLocalDateLocalTime

このアンサーのJoda-Timeセクションで説明されている論理はJava.timeに適用されます。

古いJava.util.Dateクラスには、Java.timeに変換するための新しい toInstant メソッドがあります。

Instant instant = yourJavaUtilDate.toInstant(); // Convert into Java.time type.

日付を決定するにはタイムゾーンが必要です。

ZoneId zoneId = ZoneId.of( "America/Montreal" );

そのタイムゾーンオブジェクトをInstantに適用してZonedDateTimeを取得します。その結果、日付を比較することが目的であるため、日付のみの値(LocalDate)を抽出します(時間、分などではありません)。

ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate1 = LocalDate.from( zdt1 );

比較に必要な2番目のJava.util.Dateオブジェクトに対しても同じことを行います。代わりに現在の瞬間を使用します。

ZonedDateTime zdt2 = ZonedDateTime.now( zoneId );
LocalDate localDate2 = LocalDate.from( zdt2 );

同じ日付値をテストするには、特別な isEqual メソッドを使用してください。

Boolean sameDate = localDate1.isEqual( localDate2 );
18
Basil Bourque

ここで見られるように日付をJava 8 Java.time.LocalDate に変換してください

LocalDate localDate1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate localDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

// compare dates
assertTrue("Not on the same day", localDate1.equals(localDate2));
6
Istvan
private boolean isSameDay(Date date1, Date date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);
        boolean sameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
        boolean sameMonth = calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
        boolean sameDay = calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH);
        return (sameDay && sameMonth && sameYear);
    }
5
evya

Androidユーザーのために:

DateUtils.isToday(dateMilliseconds)を使って、与えられた日付が当日かどうかをチェックすることができます。

APIリファレンス: https://developer.Android.com/reference/Android/text/format/DateUtils.html#isToday(long)

4
Hemant Kaushik

Java 8

プロジェクトでJava 8を使用していてJava.sql.Timestampを比較している場合は、LocalDateクラスを使用できます。

sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate());

もしあなたがJava.util.Dateを使っているのなら、曖昧さが少ないIstvanの答えを見てください。

4
amanteaux

binil Thomasソリューションに加えて

public static boolean isOnSameDay(Timestamp... dates) {
    SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
    String date1 = fmt.format(dates[0]);
    for (Timestamp date : dates) {
        if (!fmt.format(date).equals(date1)) {
            return false;
        }
    }
    return true;
}

使用法

    isOnSameDay(date1,date2,date3 ...);
//or 
    isOnSameDay(mydates);
1

Kotlin開発者にとって、これはフォーマットされた文字列アプローチを比較することによるバージョンです:

val sdf = SimpleDateFormat("yyMMdd")
if (sdf.format(date1) == sdf.format(date2)) {
    // same day
}

それは最善の方法ではありませんが、短くてうまくいきます。

0
Micer
public static boolean validSearchRange(String start, String end){
    SimpleDateFormat dateFormat = new SimpleDateFormat(clientDateFormat);
    try {
        Date start_date = dateFormat.parse(start);
        Date end_date = dateFormat.parse(end);
        return !start_date.after(end_date);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return false;
}
0
jadeoti