关于如何以字符串格式比较 2 个日期的任何想法?

Any ideas on how I could compare 2 dates in string format?

关于如何以字符串格式比较 2 个日期的任何想法:

String1 = "Wed May 18 00:00:00 CDT 2011"
String2= "May. 18, 2011"

我尝试将 String1 转换为 String2 的日期格式,但不是很成功。

我尝试使用模式 "EEE mmm dd HH:mm:ss z yyyy"

String1 转换为日期
public String formatDateTime(Date date, String pattern) {  
    SimpleDateFormat formatter = new SimpleDateFormat(pattern);  
    String dateString = formatter.format(date);  
    return dateString;  
}

此解决方案可行,但是,您需要注意计算机 运行 所在的时区。如果第二个日期是在美国东部时间生成的,则第二个日期没有时区会导致问题。

String d1 = "Wed May 18 00:00:00 CDT 2011";
String d2 = "May. 18, 2011";

SimpleDateFormat d1Formatter = new SimpleDateFormat("E MMMM dd HH:mm:ss z yyyy");
SimpleDateFormat d2Formatter = new SimpleDateFormat("MMMM. dd, yyyy");

Date date1 = d1Formatter.parse(d1);
Date date2 = d2Formatter.parse(d2);

date1.equals(date2);

请注意,我使用的所有模式都来自 documentation。我建议创建一个单元测试并测试不同组合的作用。

@Test
public void test_date_experimentation() {
    SimpleDateFormat d1Formatter = new SimpleDateFormat("E MMMM dd HH:mm:ss z yyyy");

    // Print the current time in the specified format.
    System.out.println(d1Formatter.format(Date.from(Instant.now())));
}

要将 String 转换为 Date,您应该使用 parse 方法。但是您使用的是 format 方法,它的作用恰恰相反(它将 Date 转换为 String)。

要检查 2 个 String 是否对应于同一日期,您必须为每个 SimpleDateFormat 解析它们。但有两个细节需要牢记:

  • 请注意,月份和星期几是英文的,因此您应该使用 java.util.Locale 来指明您要使用的语言。如果您不指定,它将使用系统默认值,并且不保证始终为英文。

    即使是这样,此配置也可以在不通知的情况下更改,即使在运行时也是如此,因此最好明确使用特定的配置。

  • 第一个 String 有时区信息:CDT - 我假设它是美国的 中部夏令时 (尽管it could also be Cuba Daylight Time)。但是第二个 String 没有任何时区信息,所以我假设它与第一个 String.

    处于同一时区

    如果我不指定它,将使用系统的默认值,如果不是 CDT,它可能会给你不同的结果。与发生在语言环境中的情况类似,即使在运行时也可以更改默认设置,恕不另行通知,因此最好指定您使用的是哪一个。

String s1 = "Wed May 18 00:00:00 CDT 2011";
String s2 = "May. 18, 2011";
// use English locale for month and day of week
SimpleDateFormat sdf1 = new SimpleDateFormat("E MMMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
SimpleDateFormat sdf2 = new SimpleDateFormat("MMMM. dd, yyyy", Locale.ENGLISH);
// set timezone, because String 2 has no timezone information
sdf2.setTimeZone(TimeZone.getTimeZone("America/Chicago"));

// parse the dates
Date date1 = sdf1.parse(s1);
Date date2 = sdf2.parse(s2);
// compare them
boolean areDatesEqual = date1.equals(date2);

变量 areDatesEqual 的值将是 true(日期相同)。

请注意,我使用 America/Chicago 作为时区名称。如果我使用 CDTTimeZone class 无法识别它并给出不正确的结果。

最好使用 IANA timezones names(格式总是 Region/City,如 America/ChicagoEurope/London)。 避免使用 3 个字母的缩写(如 CDTPST),因为它们是 ambiguous and not standard.

more than one timezone that uses CDT,所以您必须选择最适合您系统的那个。 您可以通过调用 TimeZone.getAvailableIDs().

获取可用时区的列表

Java新Date/TimeAPI

旧的 classes(DateCalendarSimpleDateFormat)有 lots of problems and design issues,它们正在被新的 APIs.

如果您使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.

如果您使用 Java <= 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it ).

下面的代码适用于两者。 唯一的区别是包名称(在 Java 8 中是 java.time,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但是 classes和方法名称是一样的。

由于您只比较日期 (day/month/year),因此最好只使用这些字段而忽略其余字段(hour/minute/second 和时区信息)。为此,您可以使用 LocalDateDateTimeFormatter:

String s1 = "Wed May 18 00:00:00 CDT 2011";
String s2 = "May. 18, 2011";
// use English locale for month and day of week
DateTimeFormatter fmt1 = DateTimeFormatter.ofPattern("E MMMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
DateTimeFormatter fmt2 = DateTimeFormatter.ofPattern("MMMM. dd, yyyy", Locale.ENGLISH);
// parse the strings
LocalDate d1 = LocalDate.parse(s1, fmt1);
LocalDate d2 = LocalDate.parse(s2, fmt2);
// compare the dates
boolean areDatesEqual = d1.equals(d2);

因为 LocalDate 只有天、小时和分钟(没有 hours/minutes/seconds 也没有时区信息),你不需要关心在格式化程序中设置时区——尽管关心保留英语语言环境。

结果也将是true