【问题标题】:Comparing dates with months as strings将日期与月份作为字符串进行比较
【发布时间】:2021-12-06 09:51:18
【问题描述】:

我正在尝试比较这两个日期:

17 Oct. 2019 (08:23)
19 déc. 2019 (21:15)

月份是法语,主要问题是月份。我是否需要为每种类型的月份添加一个 if 语句,以便我可以在适当的月份切换它?例如:

if (MonthValue.equals("oct."){
    DateValue.replace("oct.","10");
}

或者有没有更简单的解决方案,因为如果第一个值大于第二个值,我需要检查一个表。

编辑: 我的新代码:

String target1 = "17 oct. 2019 (08:23)";
        String target2 = "19 déc. 2019 (21:15)";
        DateFormat df = new SimpleDateFormat("dd MMM. YYYY (kk:mm)", Locale.FRENCH);
        Date result =  df.parse(target1);  
        Date result2 =  df.parse(target2); 
        System.out.println(result);
        System.out.println(result2);
        if(result.compareTo(result2) < 0) {
            System.out.println("true");
        }
        else {
            System.out.println("false");
        }

不工作给出此错误:

java.text.ParseException: Unparseable date: "17 oct. 2019 (08:23)"

【问题讨论】:

  • 需要和String比较吗?你为什么不解析到日期然后比较它。
  • @Popeye 您链接的解决方案虽然使用旧类。强烈建议使用 Java SE 8 中引入的 Date & Time API。
  • 这个字符串真的有大写的Oin Oct.吗?这在我读法语的地方并不常见。
  • 我建议你不要使用SimpleDateFormatDate。这些类设计不佳且早已过时,尤其是前者,尤其是出了名的麻烦。而是使用来自java.time, the modern Java date and time APILocalDateTimeDateTimeFormatter
  • 是的,这就是答案使用@OleV.V.

标签: java date date-comparison


【解决方案1】:

使用带有dd MMM yyyy (HH:mm) 模式的 DateTimeFormatter 来解析这样的日期字符串

String target1 = "17 oct. 2019 (08:23)";
String target2 = "19 déc. 2019 (21:15)";

Locale locale = Locale.FRANCE;
DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder().appendPattern("dd MMM yyyy (HH:mm)")
        .toFormatter(locale);
LocalDateTime dateTime1 = LocalDateTime.parse(target1, dateTimeFormatter);
LocalDateTime dateTime2 = LocalDateTime.parse(target2, dateTimeFormatter);

System.out.println(dateTime1);
System.out.println(dateTime2);
if (dateTime1.compareTo(dateTime2) < 0) {
    System.out.println("true");
} else {
    System.out.println("false");
}

【讨论】:

  • 谢谢它的工作,似乎 .如果我没记错的话,在 MMM 旁边是问题吗?
  • @Yan 是的,重点是月份本身的字符
  • 或者没有构建器:DateTimeFormatter.ofPattern("dd MMM yyyy (HH:mm)", Locale.FRENCH).
  • 主要问题是. 已经被MMM 覆盖,尤其是YYYY 是星期年,yyyy 是正常年份。年变化时,周数可以对应于与实际年份不同的(周)年。
  • @Yan 也是“oct”。而不是“十月”
【解决方案2】:

java.time 和格式模式字符串中的可选部分

与其他人一样,我建议您使用现代 Java 日期和时间 API java.time 来处理日期和时间。我知道如果您的月份名称是五个字母或更短(例如 avril),它们会被完整地写出来,而如果它们是七个字母或更长(例如 juillet),它们是缩写的。以下格式化程序可以在这两种情况下解析:

private static final DateTimeFormatter DATE_FORMATTER
        = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .appendPattern("dd [MMMM][MMM] uuuu (HH:mm)")
                .toFormatter(Locale.FRENCH);    

格式模式字符串中的方括号[] 围绕可选部分。 MMMM 是完整的月份名称。 MMM 是缩写。所以[MMMM][MMM] 的重点是它会成功解析完整的月份名称或缩写,并跳过不起作用的那个。由于您给出了Oct. 用大写O 编写的示例,因此我还指定了解析不应区分大小写。如果这不是必需的,您可以使用这个更简单的格式化程序:

private static final DateTimeFormatter DATE_FORMATTER
        = DateTimeFormatter.ofPattern("dd [MMMM][MMM] uuuu (HH:mm)", Locale.FRENCH);

为了检查所有月份的工作情况,我设置了这些测试数据:

    String[] dateStrings = {
            "17 Oct. 2019 (08:23)",
            "19 déc. 2019 (21:15)",
            "01 avril 2021 (09:40)",
            "08 janv. 2020 (01:18)",
            "28 févr. 2021 (21:41)",
            "03 mars 2020 (22:54)",
            "06 mai 2020 (03:14)",
            "21 juin 2020 (07:15)",
            "18 juil. 2020 (23:06)",
            "06 août 2020 (22:28)",
            "29 sept. 2020 (06:04)",
            "18 nov. 2019 (01:35)"
    };

要解析和比较其中两个,请使用LocalDateTime.parse().isBefore()

    LocalDateTime dateTime1 = LocalDateTime.parse(dateStrings[1], DATE_FORMATTER);
    LocalDateTime dateTime2 = LocalDateTime.parse(dateStrings[2], DATE_FORMATTER);
    if (dateTime1.isBefore(dateTime2)) {
        System.out.format(Locale.FRENCH, "%s is before %s%n", dateTime1, dateTime2);
    }

输出:

2019-12-19T21:15 早于 2021-04-01T09:40

为了比较,您还可以利用LocalDateTime 实现Comparable 的事实。例如,这在对日期和时间进行排序时非常实用。作为一个简单的例子,让我们对解析上述字符串后得到的所有 LocalDateTime 对象进行排序:

    Arrays.stream(dateStrings)
            .map(ds -> LocalDateTime.parse(ds, DATE_FORMATTER))
            .sorted()
            .forEach(System.out::println);
2019-10-17T08:23
2019-11-18T01:35
2019-12-19T21:15
2020-01-08T01:18
2020-03-03T22:54
2020-05-06T03:14
2020-06-21T07:15
2020-07-18T23:06
2020-08-06T22:28
2020-09-29T06:04
2021-02-28T21:41
2021-04-01T09:40

链接: Trail: Date Time (The Java™ Tutorials) 解释如何使用 java.time。

【讨论】:

    【解决方案3】:

    我的建议:

    【讨论】:

    • doesnt work 给出了这个错误 java.text.ParseException: Unparseable date: "17 oct. 2019 (08:23)"
    • @Yan 解析应该工作,正确的语言环境和格式给出(所以它知道月份名称,缩写)。这实际上是两者的最佳解决方案。
    • String 类型中的方法 format(String, Object...) 不适用于参数 (DateTimeFormatter) 输入模式和值后出现此错误
    • @Yan 请用您的尝试更新您的问题
    【解决方案4】:

    我从您的问题中得到的是,您想将月份的名称转换为它们各自的数字。如果是这种情况,那么您应该尝试 switch
    示例:

    switch (MonthValue){
        case jan:
          MonthValue = 1; // Set Month variable to it Numbered Position (type casting might be required)
          break;
        case feb:
          MonthValue = 2;
          break;
        default:
          System.out.println("Somthing...");
    }
    

    【讨论】:

    • 我不想这样做,因为如果它会比较 1000 个值,它就没有效率
    【解决方案5】:

    尝试编码为 UTF8,这样可以避免 DateTimeParseException Exception in thread "main" java.time.format.DateTimeParseException: Text '19 d??c. 2019 (21:15)' could not be parsed at index 3

        public static void main(String args[]) throws Exception {
            String date1 = "17 oct. 2019 (08:23)";
            String date2 = "19 déc. 2019 (21:15)";
            
            DateTimeFormatter longDateTimeFormatter = DateTimeFormatter.ofPattern("dd MMM yyyy (HH:mm)").withLocale(Locale.FRENCH);
            LocalDateTime lclDate1 = LocalDateTime.parse(encodeUTF8(date1), longDateTimeFormatter);
            LocalDateTime lclDate2 = LocalDateTime.parse(encodeUTF8(date2), longDateTimeFormatter);
            if (lclDate1.compareTo(lclDate2) < 0) {
                System.out.println("true");
            }
            else {
                System.out.println("false");
            }
        }
        
        public static String encodeUTF8(String dateStr) {
            byte[] bytes = dateStr.getBytes();
            String utf8EncodStr = new String(bytes, StandardCharsets.UTF_8);
            return utf8EncodStr;
        }
    

    【讨论】:

    • 这是不正确的。您将字符串编码为平台默认的生态编码,然后使用 UTF_8 将字节解码为字符串。奇怪的是你的平台默认是 UTF_8,所以这是一个非操作。
    • 而 UTF-8 将是 Java 18 及更高版本中的 default across platforms
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多