【问题标题】:Java 8 LocalDateTime is parsing invalid dateJava 8 LocalDateTime 正在解析无效日期
【发布时间】:2015-12-25 17:13:05
【问题描述】:

我想在客户端验证日期,所以我编写了以下代码。但是,我没有得到异常,而是得到了 2 月 31 日日期字符串的正确日期对象,这显然是一个无效的日期。

public class Test {

    public static void main(String[] args) {
        String dateFormat = "HH:mm:ss MM/dd/yyyy";
        String dateString = "11:30:59 02/31/2015";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US);
        try {
            LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
            System.out.println(date);
        } catch (Exception e) {
            // Throw invalid date message
        }
    }
}

输出:2015-02-28T11:30:59

有谁知道为什么LocalDateTime 解析这个日期而不是抛出异常。

【问题讨论】:

  • 为什么要等待异常?
  • @AndrewTobilko,大概是因为 2 月 31 日不存在。
  • 但格式化程序不知道这一点。
  • @Satya:是什么让你这么认为?某些东西清楚地知道该日期不存在,因为它正在将其转换为 28 日......
  • @JonSkeet 我很抱歉之前误导了你,问题不在于丢失的毫秒数。这实际上是失踪的时代。它仍然需要DateTimeFormatterBuilder,但默认为 Era,而不是毫秒。如果您想编辑和取消删除您的答案,请随意。

标签: java parsing datetime


【解决方案1】:

你只需要一个严格的ResolverStyle

解析文本字符串分为两个阶段。阶段 1 是根据添加到构建器的字段的基本文本解析。阶段 2 将解析的字段值对解析为日期和/或时间对象。此样式用于控制第 2 阶段(解析)的发生方式。

示例代码 - 其中withResolverStyle(ResolverStyle.STRICT) 是重要更改,同时使用uuuu 而不是yyyy(其中uuuu 是“年份”,“yyyy”是“时代”,因此模棱两可):

import java.time.*;
import java.time.format.*;
import java.util.*;

public class Test {

    public static void main(String[] args) {
        String dateFormat = "HH:mm:ss MM/dd/uuuu";
        String dateString = "11:30:59 02/31/2015";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
            .ofPattern(dateFormat, Locale.US)
            .withResolverStyle(ResolverStyle.STRICT);
        try {
            LocalDateTime date = LocalDateTime.parse(dateString, dateTimeFormatter);
            System.out.println(date);
        } catch (DateTimeParseException e) {
            // Throw invalid date message
            System.out.println("Exception was thrown");
        }
    }
}

【讨论】:

  • 将格式字符串中的 yyyy 更改为 uuuu,这样就不需要搞乱 ERA
【解决方案2】:

Java 8 DateTimeFormatter 使用 yyyy 表示 YEAR_OF_ERA,使用 uuuu 表示 YEAR。您需要按如下方式修改模式字符串:

String dateFormat = "HH:mm:ss MM/dd/uuuu";

DateTimeFormatter 默认使用 SMART 解析器样式,但您希望它使用 STRICT 解析器样式。修改你的 dateTimeFormatter 初始化代码如下:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateFormat, Locale.US)
                                                       .withResolverStyle(ResolverStyle.STRICT);

【讨论】:

    【解决方案3】:

    它没有四舍五入。 2 月从来没有 31 天,不可能使用验证日期/时间对象来表示不存在的一天。

    因此,它采用无效输入并为您提供正确日期的最佳近似值(当年 2 月的最后一个日期)。

    SimpleDateFormat 继承自 DateFormat,它有一个 setLenient(boolean value) 方法。我希望如果你在解析之前调用setLenient(true),它可能会抱怨更多,as detailed in the javadocs

    【讨论】:

      【解决方案4】:
      try {
          SimpleDateFormat df = new java.text.SimpleDateFormat("HH:mm:ss MM/dd/yyyy");
          df.setLenient(false);
          System.out.println(df.parse("11:30:59 02/29/2015"));
      } catch (java.text.ParseException e) {
        System.out.println(e);
      }
      

      我找到了一种解决方案,可以使用DateFormat.setLenient(boolean) 将日期识别为有效日期。如果您尝试解析任何无效日期,则会引发解析异常。

      编辑:

      Java 8,但如果一个月不在112 之间,如果一天超过32,则会引发异常。完全不工作。但一个月它的工作。

      try {
      TemporalAccessor ta = DateTimeFormatter.ofPattern("HH:mm:ss MM/dd/yyyy").parse("11:30:59 02/32/2015");
      } catch (Exception e) {
      System.out.println(e);
      }
      

      输出:

      java.time.format.DateTimeParseException: Text '11:30:59 02/32/2015' could not be
       parsed: Invalid value for DayOfMonth (valid values 1 - 28/31): 32
      

      【讨论】:

      • SimpleDateFormat 不适用于 Java 8 LocalDateTime。我正在寻找 Java8 LocalDateTime 的解决方案
      【解决方案5】:

      LocalDateTime.parse 只会在传入的 String 包含无效字符、天数超过 31 或一个月超过 12 时抛出错误。

      例如,如果您这样修改代码:

      String dateString = "11:30:59 0zz2/31/2015";
      

      给定日期内的无效“zz”字符会引发异常。至于为什么它可以说是“四舍五入”的日期,我不知道。

      来源:https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#parse-java.lang.CharSequence-

      【讨论】:

        猜你喜欢
        • 2016-09-12
        • 1970-01-01
        • 1970-01-01
        • 2020-10-23
        • 2016-04-17
        • 2018-04-06
        • 1970-01-01
        • 2016-04-21
        • 2020-03-12
        相关资源
        最近更新 更多