LoginSignup
5
4

More than 5 years have passed since last update.

JDK別のjava.util.Dateの同日比較について

Posted at

前提

 標準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はそこまで時間が掛からないようだ。

DateCompare1.java
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されたものである場合、日付以下の時分秒ミリ秒まで保持しているため、日付の同一性チェックには向かない。

DateCompare2.java
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の方がそれっぽくね?と思い書いたのが下記。
 悪くないがコードが長く。パッと見「これ何してんの?」感が強い。
 高速。

DateCompare3.java
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

まず遅い。
そして文字列にする過程があることで、「日付を文字列化する」ことが必要であると誤認させてしまい、誤ったリファクタリングを誘発する恐れがある。

DateCompare4.java
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よりは速いという結果。
そして文字列にする過程があることで、「日付を文字列化する」ことが必要であると誤認させてしまい、誤ったリファクタリングを誘発する恐れがある。

DateCompare5.java
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」はテスト用に実装させて検証を簡易的にしていただけなので実行には要らないものです。

5
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4