【问题标题】:Comparing date strings in Java [duplicate]比较Java中的日期字符串[重复]
【发布时间】:2012-05-15 22:18:17
【问题描述】:

所以我使用dateString1.compareTo(dateString2),它根据每个字符的Unicode 值与字符串进行字典比较,并返回一个int。这是一个代码示例。

String dateString1 = "05-12-2012";
String dateString2 = "05-13-2012";
if (dateString1.compareTo(dateString2) <=0){
   System.out.println("dateString1 is an earlier date than dateString2");
}

这是在 Java 中比较日期的错误方法吗?

在我的测试中,我没有遇到意外结果的情况。如果我不需要的话,我真的不想从字符串中创建一个 Date 对象,因为我在一个长时间运行的循环中执行此操作。

忍者编辑 从下面的答案中可以看出,如果日期为 yyyyMMdd 格式,则将日期作为字符串进行比较没有任何问题,但如果是任何其他格式,则显然会导致错误。

在我的实际代码中,我的日期字符串实际上是yyyyMMdd 格式。 (我在上面给出的示例中输入了错误的格式。)所以现在,我将保持代码不变,并添加几行 cmets 来证明我的决定。

但我现在发现,像这样比较字符串是非常有限的,如果 dba 决定在以后更改日期格式,我会遇到错误,我认为这不会发生。

【问题讨论】:

标签: java date


【解决方案1】:

在 Java 中使用字符串处理日期并不总是最好的选择。例如,当它是 年时,二月会多出一天。因为字符串可能看似正确,所以执行转换更为合适。 Java 验证日期是否正确。

您可以使用SimpleDateFormat 类将字符串转换为日期。

public static void main(String[] args) throws ParseException {
    String dateString1 = "05-12-2012";
    String dateString2 = "05-13-2012";

    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date date1 = format.parse(dateString1);
    Date date2 = format.parse(dateString2);

    if (date1.compareTo(date2) <= 0) {
        System.out.println("dateString1 is an earlier date than dateString2");
    }
}

找出哪些参数允许检查Customizing Formats (The Java™ Tutorials > Internationalization > Formatting)

【讨论】:

  • 是的,打印dateString1 is an earlier date than dateString2。代码有问题吗?
  • 日期字符串与 SimpleDateFormat 构造函数的格式不同。
  • 我没有注意到。感谢您的提示。
  • 我喜欢你的回答,有一个赞成票,但我仍然看不出不转换为日期对象会如何使我的代码在闰年失败。我将按字典顺序比较的是“02-29-2014”和“02-28-2014”。它仍然通过字符串比较返回正确的值。
  • 比较字符串只有在正确的情况下才有效。使用Date 可以确保这一点。
【解决方案2】:

我建议您做正确的事情 (as described here) 并转换为正确的 Date 对象进行比较。如果以及何时实际影响您的应用程序(它可能不会),请担心性能影响。

【讨论】:

  • 除了 2017 年(及以后),转为 LocalDateDate 在 2012 年是一个不错的选择,现在已经过时了)。
【解决方案3】:

这很糟糕,因为现在你无法处理一年的变化。

如果您想这样做,您可能希望将日期格式化为YYYY-MM-DD,这样新的一年就不会破坏它。

【讨论】:

  • 任何建议将日期作为字符串进行比较的方法都值得一击! :)
  • YYYYMMDD 可以作为字符串进行比较。
【解决方案4】:

使用字母规则来处理日期排序是不好的,主要是因为您遇到了根据字母和数字系统对事物进行不同排序的问题

字母表

01-02-2011 comes before
01-1-2011 (because 0 in the date field is before 1 in the other date field)

对于数制

01, 02, 2011 comes after
01, 1, 2011  because all fields are being compared like numbers

Date 对象扩展了数字比较以了解哪些字段在比较中具有优先权,因此您不会得到一个较早月份将日期“放在”另一个实际发生在后一个月但较早年份的日期。

如果您对日期格式有严格的控制,您可以对齐日期,使其也遵循字母规则;但是,如果您不小心注入了格式错误的日期,这样做可能会使您的整个程序以奇怪的方式失败。

这样做的典型方式是(不推荐,请使用非字符串日期比较)

YYYYMMDD
(year)(month)(day) all zero-padded.

最后一种技术主要是因为您最终会在野外看到它,并且应该认清它的本质:尝试在没有适当日期库的情况下处理日期(也称为聪明的 hack)。

【讨论】:

  • 谢谢。你能给最后一部分提供参考吗?这个案例对我很有效,但我只是想确保逻辑得到充分证明
【解决方案5】:

如前所述,通常使用日期时间对象而不是字符串更好。

java.time

其他答案使用旧的过时日期时间类,这些类已被证明设计不佳、令人困惑且麻烦。它们缺少一个类来真正表示没有时间和时区的纯日期值。

改为使用 Java 8 及更高版本中内置的 java.time 框架。见Oracle Tutorial。大部分 java.time 功能在 ThreeTen-Backport 中向后移植到 Java 6 和 7,并在 ThreeTenABP 中进一步适应 Android。

String input = "05-12-2012";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MM-dd-yyyy" );
LocalDate ld = LocalDate.parse( input , formatter );

LocalDate 实现了compareTo。另外,你可以调用方法equals、isBefore、isAfter。

Boolean isEarlier = ld.isBefore( someOtherLocalDate );

【讨论】:

    【解决方案6】:

    如果您只对每个日期进行一次读取,那么 YYYYMMDD(而不是您所做的 MMDDYYYY)可能是最佳解决方案。但是,当您打算多次处理每个日期时(例如,您正在对它们进行排序),那么肯定最好将它们更改为可以比字符串更快地进行比较的对象(例如日期)

    【讨论】:

      猜你喜欢
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 2011-09-14
      • 2012-10-19
      相关资源
      最近更新 更多