如何在 Java 中比较日期?[复制]

How to compare dates in Java? [duplicate]

提问人:ant 提问时间:4/7/2010 最后编辑:flotothemoonant 更新时间:4/18/2023 访问量:1178727

问:

如何在 Java 中比较两者之间的日期?

例:

date1 是 date2 是今天
date3 是
22-02-201007-04-201025-12-2010

date3永远大于今天,永远是今天。如何验证今天的日期是否介于 date1 和日期 3 之间?date1date2

Java 日期 比较

评论


答:

684赞 Bart Kiers 4/7/2010 #1

Datebeforeafter 方法,可以按如下方式相互比较

if(todayDate.after(historyDate) && todayDate.before(futureDate)) {
    // In between
}

对于包容性比较:

if(!historyDate.after(todayDate) && !futureDate.before(todayDate)) {
    /* historyDate <= todayDate <= futureDate */ 
}

您也可以尝试一下 Joda-Time,但请注意:

Joda-Time 是 Java SE 8 之前 Java 的事实上的标准日期和时间库。现在要求用户迁移到 java.timeJSR-310)。

向后移植可用于 Java 6 和 7 以及 Android。

评论

8赞 Daniel Hári 12/3/2015
这是包容性的,还是边界的排他性?
1赞 Mifmif 5/10/2016
@DanielHári不,它不包括在内。您可以使用第一条评论中建议的解决方案,或使用 CompareTo()>=0 。
0赞 Daniel Hári 5/10/2016
正常通常“左包,右包”,这就是为什么我认为这应该准确指定。使用“左独占,右独占”边框,您可以轻松地指定 fe: a month interval: [2016/04/01, 2016/05/01],这就是为什么这是正常现象,并在许多用例中用作默认值。
1赞 Basil Bourque 2/23/2018
仅供参考,麻烦的旧日期时间类(如java.util.Date)现在是遗留的,被Java 8和Java 9内置的java.time类所取代。请参阅 Oracle 教程
0赞 Bart Kiers 2/23/2018
@BasilBourque是的,没错,因此对 Joda 和 Java 8 的评论,Java 8 现在是标准版本(与我写这个答案的时间相反)。当然,请随意编辑此答案并添加更多最新的示例代码!;)(编辑:啊,我看到你自己已经用上述例子提供了答案)java.time
147赞 Chandra Sekar 4/7/2010 #2

使用 compareTo

date1.compareTo(date2);

评论

0赞 Giancarlo Ventura Granados 1/12/2016
与日期、字节、长整型、整数完美配合......
1赞 Syed 8/15/2018
有时它不起作用。我多次使用 in main 方法来检查相等性。大多数时候它说平等,但不是所有时候。
0赞 Chandra Sekar 8/16/2018
@Syed 你能分享你的代码吗?
0赞 Syed 8/17/2018
@ChandraSekarS,尝试通过采用相同的日期作为主方法代码执行并查看输出。有时,它给出 0,有时给出 1。
23赞 sam 4/7/2010 #3

比较两个日期:

  Date today = new Date();                   
  Date myDate = new Date(today.getYear(),today.getMonth()-1,today.getDay());
  System.out.println("My Date is"+myDate);    
  System.out.println("Today Date is"+today);
  if (today.compareTo(myDate)<0)
      System.out.println("Today Date is Lesser than my Date");
  else if (today.compareTo(myDate)>0)
      System.out.println("Today Date is Greater than my date"); 
  else
      System.out.println("Both Dates are equal"); 

评论

6赞 Dr. No 11/3/2011
我认为“new Date(today.getYear(),today.getMonth()-1,today.getDay());”它已被弃用。download.oracle.com/javase/6/docs/api/java/util/Date.html
0赞 Lii 3/23/2015
@Muath:虽然我不是 100% 确定,但我认为这是因为 中的月份成分是零索引的。Date
0赞 Sachith Wickramaarachchi 12/25/2016
我认为其他部分不起作用:)
5赞 Everyone 4/7/2010 #4

使用 getTime() 获取日期的数值,然后使用返回的值进行比较。

0赞 Brownsoo Han 11/27/2013 #5

此代码确定今天是某个持续时间..基于 KOREA 区域设置

    Calendar cstart = Calendar.getInstance(Locale.KOREA);
    cstart.clear();
    cstart.set(startyear, startmonth, startday);


    Calendar cend = Calendar.getInstance(Locale.KOREA);
    cend.clear();
    cend.set(endyear, endmonth, endday);

    Calendar c = Calendar.getInstance(Locale.KOREA);

    if(c.after(cstart) && c.before(cend)) {
        // today is in startyear/startmonth/startday ~ endyear/endmonth/endday
    }
131赞 Sunil Kumar Sahoo 1/13/2014 #6

以下是最常见的比较方法(我的偏好是方法 1):dates

方法 1:使用 Date.before()、Date.after() 和 Date.equals()

if (date1.after(date2)) {
    System.out.println("Date1 is after Date2");
}

if (date1.before(date2)) {
    System.out.println("Date1 is before Date2");
}

if (date1.equals(date2)) {
    System.out.println("Date1 is equal Date2");
}

方法 2:Date.compareTo()

if (date1.compareTo(date2) > 0) {
    System.out.println("Date1 is after Date2");
} else if (date1.compareTo(date2) < 0) {
    System.out.println("Date1 is before Date2");
} else {
    System.out.println("Date1 is equal to Date2");
}

方法 3:Calendar.before()、Calendar.after() 和 Calendar.equals()

Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(date1);
cal2.setTime(date2);

if (cal1.after(cal2)) {
    System.out.println("Date1 is after Date2");
}

if (cal1.before(cal2)) {
    System.out.println("Date1 is before Date2");
}

if (cal1.equals(cal2)) {
    System.out.println("Date1 is equal Date2");
}

评论

0赞 Basil Bourque 2/23/2018
仅供参考,麻烦的旧日期时间类,如java.util.Date,java.util.Calendar,现在是遗留的,被Java 8和Java 9内置的java.time类所取代。请参阅 Oracle 教程java.text.SimpleDateFormat
0赞 Sapthaka 1/10/2023
compareTo 方法可能会产生零星的问题。最好使用另一种方式
43赞 Basil Bourque 1/29/2014 #7

TL的;博士

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) ) ;
Boolean isBetween = 
    ( ! today.isBefore( localDate1 ) )  // “not-before” is short for “is-equal-to or later-than”.
    &&
    today.isBefore( localDate3 ) ; 

或者,更好的是,如果您将 ThreeTen-Extra 库添加到您的项目中。

LocalDateRange.of(
    LocalDate.of( … ) ,
    LocalDate.of( … )
).contains(
    LocalDate.now()
)

半开放的方法,其中开始是包容的,而结束是排他性的。

格式选择不当

顺便说一句,对于日期或日期时间值的文本表示形式来说,这是一个错误的格式选择。尽可能坚持使用标准 ISO 8601 格式。ISO 8601 格式是明确的,在人类文化中是可以理解的,并且易于机器解析。

对于仅日期值,标准格式为 YYYY-MM-DD。请注意,这种格式在按字母顺序排序时具有按时间顺序排列的好处。

LocalDate

LocalDate 类表示一个仅日期值,没有一天中的时间,也没有时区。

时区对于确定日期至关重要。对于任何给定时刻,日期在全球范围内因区域而异。例如,法国巴黎午夜过后几分钟是新的一天,而在魁北克省蒙特利尔仍然是“昨天”。

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );

Table of all date-time types in Java, both modern and legacy

DateTimeFormatter

由于您的输入字符串是非标准格式,因此我们必须定义要匹配的格式模式。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu" );

使用它来分析输入字符串。

LocalDate start = LocalDate.parse( "22-02-2010" , f );
LocalDate stop = LocalDate.parse( "25-12-2010" , f );

在日期时间工作中,通常最好通过半开放方法定义时间跨度,其中开头是包含的,而结尾是排他性的。因此,我们想知道今天是否与开始时间相同或晚于开始时间,也比停止时间晚。“与开始相同或晚于开始”的更简短的说法是“不在开始之前”。

Boolean intervalContainsToday = ( ! today.isBefore( start ) ) && today.isBefore( stop ) ;

请参阅 gstackoverflow 的答案,其中显示了可以调用的比较方法列表。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧日期时间类,如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 中搜索许多示例和解释。规范是 JSR 310

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。Hibernate 5 和 JPA 2.2 支持 java.timejava.sql.*

从哪里获取 java.time 类?

ThreeTen-Extra 项目使用其他类扩展了 java.time。这个项目是未来可能添加java.time的试验场。您可以在这里找到一些有用的类,例如 IntervalYearWeekYearQuarter


更新:下面的“Joda-Time”部分作为历史完好无损。Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

Joda-Time(约达时间)

对于捆绑的 java.util.Date 和 java.util.Calendar 类,其他答案是正确的。但这些课程是出了名的麻烦。以下是一些使用 Joda-Time 2.3 库的示例代码。

如果您真的想要一个没有任何时间部分和时区的日期,请使用 Joda-Time 中的 LocalDate 类。该类提供了比较方法,包括 (与 Java Comparators 一起使用)、、 和 。compareToisBeforeisAfterisEqual

输入。。。

String string1 = "22-02-2010";
String string2 = "07-04-2010";
String string3 = "25-12-2010";

定义一个描述输入字符串的格式化程序...

DateTimeFormatter formatter = DateTimeFormat.forPattern( "dd-MM-yyyy" );

使用格式化程序将字符串解析为 LocalDate 对象...

LocalDate localDate1 = formatter.parseLocalDate( string1 );
LocalDate localDate2 = formatter.parseLocalDate( string2 );
LocalDate localDate3 = formatter.parseLocalDate( string3 );

boolean is1After2 = localDate1.isAfter( localDate2 );
boolean is2Before3 = localDate2.isBefore( localDate3 );

转储到控制台...

System.out.println( "Dates: " + localDate1 + " " + localDate2 + " " + localDate3 );
System.out.println( "is1After2 " + is1After2 );
System.out.println( "is2Before3 " + is2Before3 );

运行时...

Dates: 2010-02-22 2010-04-07 2010-12-25
is1After2 false
is2Before3 true

因此,请查看第二个是否介于其他两个之间(仅此而已,这意味着不等于任何一个端点)......

boolean is2Between1And3 = ( ( localDate2.isAfter( localDate1 ) ) && ( localDate2.isBefore( localDate3 ) ) );

使用时间跨度

如果您正在处理时间跨度,我建议您在 Joda-Time 中探索类:持续时间间隔周期。诸如 和 的方法使比较变得容易。overlapcontains

对于文本表示,请查看 ISO 8601 标准的:


  • 持续时间 格式:PnYnMnDTnHnMnS
    示例:P3Y6M4DT12H30M5S
    (表示“三年六个月四天,十二小时三十分五秒”)

  • 间隔格式:开始/结束
    示例:2007-03-01T13:00:00Z/2008-05-11T15:30:00Z

Joda-Time 类可以处理这两种格式的字符串,既可以作为输入(解析)也可以作为输出(生成字符串)。

Joda-Time 使用 Half-Open 方法进行比较,其中跨度的开头是包含的,而结尾是排他性的。这种方法对于处理时间跨度来说是一种明智的方法。搜索 StackOverflow 了解更多信息。

评论

0赞 hc_dev 11/18/2022
很好的练习技巧,提到谓词“在时间跨度内”的(右)半开区间方法。
11赞 Salman A 5/15/2015 #8

您可以使用 Date.getTime(),它:

返回自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数 由此 Date 对象表示。

这意味着您可以像比较数字一样比较它们:

if (date1.getTime() <= date.getTime() && date.getTime() <= date2.getTime()) {
    /*
     * date is between date1 and date2 (both inclusive)
     */
}

/*
 * when date1 = 2015-01-01 and date2 = 2015-01-10 then
 * returns true for:
 * 2015-01-01
 * 2015-01-01 00:00:01
 * 2015-01-02
 * 2015-01-10
 * returns false for:
 * 2014-12-31 23:59:59
 * 2015-01-10 00:00:01
 * 
 * if one or both dates are exclusive then change <= to <
 */
15赞 gstackoverflow 11/13/2015 #9

Java 8 及更高版本的更新

这些方法存在于 LocalDate、LocalTime 和 LocalDateTime中。

这些类内置于 Java 8 及更高版本中。java.time的大部分功能在ThreeTen-Backport中被反向移植到Java 6和Java 7中,并在ThreeTenABP中进一步适应Android(参见如何使用...)。

评论

0赞 Punithapriya 8/8/2016
如何下载这三个类
1赞 gstackoverflow 8/8/2016
@Punithapriya 这些类存在于 java 8 标准库中。因此,只需下载 java 8
0赞 Punithapriya 8/8/2016
是的,我看过谢谢
8赞 Garambe 11/24/2015 #10

试试这个

public static boolean compareDates(String psDate1, String psDate2) throws ParseException{
        SimpleDateFormat dateFormat = new SimpleDateFormat ("dd/MM/yyyy");
        Date date1 = dateFormat.parse(psDate1);
        Date date2 = dateFormat.parse(psDate2);
        if(date2.after(date1)) {
            return true;
        } else {
            return false;
        }
    }
0赞 Iman Marashi 1/7/2017 #11

这个方法对我有用:

 public static String daysBetween(String day1, String day2) {
    String daysBetween = "";
    SimpleDateFormat myFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    try {
        Date date1 = myFormat.parse(day1);
        Date date2 = myFormat.parse(day2);
        long diff = date2.getTime() - date1.getTime();
        daysBetween = ""+(TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS));
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return daysBetween;
}

评论

0赞 Basil Bourque 1/7/2017
不回答问题。该问题涉及三个日期,而不是两个日期。“如何验证今天的日期是否介于 date1 和日期 3 之间?”此外,此计算返回 24 小时周期数,而不是经过的日历日数。还有另一个问题:此答案使用日期时间值,而问题是关于仅日期值而没有时间的。