2つのDate
を比較し(例:date1
とdate2
)、2つのDate
が同じ日に共有されている場合はtrue、そうでない場合はfalseになるboolean sameDay
を作成する必要があります。
これどうやってするの?ここには混乱の旋風があるようです...そして、可能な限りJDK以外の他の依存関係を引き込むことは避けたいと思います。
明確にするためにdate1
とdate2
が同じ年月日を共有している場合、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
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
は全体をもっときれいにそしてより簡単にします(タイムゾーンを含む同じ困難が存在するでしょうが)。
どうですか?
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
return fmt.format(date1).equals(fmt.format(date2));
必要に応じて、タイムゾーンをSimpleDateFormatに設定することもできます。
これを行うには、 "Apache commons lang"パッケージを使用します(つまり、 org.Apache.commons.lang.time.DateUtils )。
boolean samedate = DateUtils.isSameDay(date1, date2); //Takes either Calendar or Date objects
日付ごとに ユリウス日数 を計算してからこれらを比較することで、外部依存関係とカレンダー使用によるパフォーマンスへの影響を回避できます。
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;
}
依存関係を追加することに関しては、私は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 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"クラスを使用します:LocalDateTime
、LocalDate
、LocalTime
。
このアンサーの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 );
ここで見られるように日付を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));
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);
}
Androidユーザーのために:
DateUtils.isToday(dateMilliseconds)
を使って、与えられた日付が当日かどうかをチェックすることができます。
APIリファレンス: https://developer.Android.com/reference/Android/text/format/DateUtils.html#isToday(long)
Java 8
プロジェクトでJava 8を使用していてJava.sql.Timestamp
を比較している場合は、LocalDate
クラスを使用できます。
sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate());
もしあなたがJava.util.Date
を使っているのなら、曖昧さが少ないIstvanの答えを見てください。
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);
Kotlin開発者にとって、これはフォーマットされた文字列アプローチを比較することによるバージョンです:
val sdf = SimpleDateFormat("yyMMdd")
if (sdf.format(date1) == sdf.format(date2)) {
// same day
}
それは最善の方法ではありませんが、短くてうまくいきます。
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;
}