前提
標準APIのみの利用を想定。
結論
・JDK1.1以前は、java.sql.Dateで再度new後、toString()で比較
日付以下の時刻は比較しないため、純粋な同日比較ではJDK1.2以降も高速。
・JDK1.2以降は、java.util.Date#compareTo(Date)で比較
ただし、ミリ秒ベースの比較であるため、受け渡されるDateにミリ秒が含まれている場合は、同日の比較には使えないため、やはりjava.sql.Dateを利用。Dateの日付以外の項目が一致する状況であれば最高速。
・いずれにしてもDateFormat、SimpleDateFormatはアカン
そもそも日付を比較するのに文字列化するのがアカン。
遅い。誤った方向のリファクタリングを呼び起こすリスクもある。
速度検証結果サマリ
実装方法 | 処理時間 (100万回実行) 単位:ミリ |
---|---|
1. java.sql.Date#toString | 299 |
2. java.util.Date#compareTo | 16 |
3. java.util.Calendar | 423 |
4. java.text.DateFormat | 1716 |
5. java.text.SimpleDateFormat | 1266 |
検証結果
1. java.sql.Date#toString
最終形。java.sql.Date#toString()はyyyy/mm/dd形式の文字列を高速に返却してくれる。
また標準APIであるためライブラリの導入も不要。コードも簡潔。
java.sql.Dateのnewはそこまで時間が掛からないようだ。
import java.util.Date;
public class DateCompare1 implements DateCompareInterface {
public boolean isSameDate(Date date1, Date date2) {
// JDK1.0~
java.sql.Date sqlDate1 = new java.sql.Date(date1.getTime());
java.sql.Date sqlDate2 = new java.sql.Date(date2.getTime());
return sqlDate1.toString().equals(sqlDate2.toString());
}
}
2. java.util.Date#compareTo
結果を返すだけなら超高速。
大本のDateが純粋にnewされたものである場合、日付以下の時分秒ミリ秒まで保持しているため、日付の同一性チェックには向かない。
import java.util.Date;
public class DateCompare2 implements DateCompareInterface {
@Override
public boolean isSameDate(Date date1, Date date2) {
// JDK1.2~
int ret = date1.compareTo(date2);
return ret == 0;
}
}
3. java.util.Calendar
Calendarの方がそれっぽくね?と思い書いたのが下記。
悪くないがコードが長く。パッと見「これ何してんの?」感が強い。
高速。
import java.util.Calendar;
import java.util.Date;
public class DateCompare3 implements DateCompareInterface {
public boolean isSameDate(Date date1, Date date2) {
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date1);
int date1yyyy = cal1.get(Calendar.YEAR);
int date1mm = cal1.get(Calendar.MONTH);
int date1dd = cal1.get(Calendar.DAY_OF_MONTH);
cal1.setTime(date2);
int date2yyyy = cal1.get(Calendar.YEAR);
int date2mm = cal1.get(Calendar.MONTH);
int date2dd = cal1.get(Calendar.DAY_OF_MONTH);
if (date1yyyy != date2yyyy)
return false;
if (date1mm != date2mm)
return false;
if (date1dd == date2dd)
return true;
return false;
}
}
4. java.text.DateFormat
まず遅い。
そして文字列にする過程があることで、「日付を文字列化する」ことが必要であると誤認させてしまい、誤ったリファクタリングを誘発する恐れがある。
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
public class DateCompare4 implements DateCompareInterface {
public boolean isSameDate(Date date1, Date date2) {
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.JAPAN);
String strDate1 = df.format(date1);
String strDate2 = df.format(date2);
return strDate1.equals(strDate2);
}
}
5.java.text.SimpleDateFormat
まず遅い。
が意外にもDateFormatよりは速いという結果。
そして文字列にする過程があることで、「日付を文字列化する」ことが必要であると誤認させてしまい、誤ったリファクタリングを誘発する恐れがある。
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateCompare5 implements DateCompareInterface {
public boolean isSameDate(Date date1, Date date2) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String strDate1 = sdf.format(date1);
String strDate2 = sdf.format(date2);
return strDate1.equals(strDate2);
}
}
補足
・各クラスが実装しているインタフェース「DateCompareInteface」はテスト用に実装させて検証を簡易的にしていただけなので実行には要らないものです。