【问题标题】:Parsing a string to date format in java defaults date to 1 and month to January在java中将字符串解析为日期格式默认日期为1,月份为一月
【发布时间】:2016-01-30 09:18:45
【问题描述】:

我正在尝试接受用户输入的日期格式,例如:“2000 小时,星期四,2015 年 7 月 20 日”。然后我会将其转换为日期格式以对其进行操作。但是从字符串到日期的转换默认月份为一月,日期为 1。这里是代码 sn-p :

    String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, YYYY";
    SimpleDateFormat userDateFormatter = new SimpleDateFormat(userDateFormat);
    String reference_date = "2000 hrs, Thursday, July 20, 2015";

    Date date = null;
    try {
        date = userDateFormatter.parse(reference_date);
    } catch (ParseException e) {
        System.out.println("Date must be in the format " + userDateFormat);
    }

    System.out.println(userDateFormatter.format(date));

以下方法块打印: 2000 小时,星期四,2015 年 1 月 1 日。 有什么线索吗?

【问题讨论】:

  • 年份格式说明符应为y 而不是Y,来自Java Docs,"Y|Week year Year|2009; 09"

标签: java


【解决方案1】:

java.time

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH);
    String referenceDate = "2000 hrs, Monday, July 20, 2015";
    LocalDateTime dateTime = LocalDateTime.parse(referenceDate, userDateTimeFormatter);
    System.out.println(dateTime.format(userDateTimeFormatter));

输出是:

2000 小时,2015 年 7 月 20 日,星期一

answer by Elliott Frisch 是正确的。我正在使用现代 Java 日期和时间 API java.time 提供现代答案。当被问到这个问题时,已经有一年半的时间了。现在它已经四年了,而且很普遍。我还给出了一个明确的语言环境。您的日期时间是英文的,虽然您的默认语言环境可能也是,但如果有一天您在不同语言环境的计算机上运行它,或者您只是更改自己的语言环境设置,那么依赖于它的代码将会中断。

您远不是唯一一个在格式模式字符串中使用不正确大小写错误的人。 Stack Overflow 上一直有人问这个问题。 SimpleDateFormat 以装腔作势而闻名:它给你一个不正确的结果并假装一切都很好,而你真的希望它会通知你有问题,例如抛出异常。

现代 API确实在您向其提供可以检测到的错误输入时抛出异常。例如:

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, YYYY", Locale.ENGLISH);
    String referenceDate = "2000 hrs, Thursday, July 20, 2015";

结果:

java.time.DateTimeException:无法从中获取 LocalDate TemporalAccessor: {MonthOfYear=7, DayOfWeek=4, WeekBasedYear[WeekFields[SUNDAY,1]]=2015, DayOfMonth=20},ISO 已解决 到 java.time.format.Parsed 类型的 20:00

它不是很可读。需要注意的是“WeekBasedYear”。基于周的年份仅对周数有用,所以这里是错误的。 the docs 会告诉你是大写的YYYY 给了你这个。让我们修复:

    DateTimeFormatter userDateTimeFormatter
            = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH);

对于DateTimeFormatter,习惯上使用uuuu 表示年份。 yyyy 在第 0 年之后也可以使用多年。不过,我们还没有完成:

java.time.DateTimeException:发现冲突:字段 DayOfWeek 1 不同 来自 DayOfWeek 4 源自 2015-07-20

现代 API 也拒绝接受不正确的星期几,因此您可以完全验证您的日期(不过,如果您不想要这种验证,有一个技巧可以说服它)。正如 Elliott Frisch 已经说过的,2015 年 7 月 20 日是星期一(一周的第一天),而不是星期四。在我上面的第一个 sn-p 中,我也修复了这个错误,所以它可以工作。

链接:Oracle tutorial: Date Time解释如何使用java.time。

【讨论】:

    【解决方案2】:

    因为您在需要 yyyy 时使用了 YYYY,而 2015 年 7 月 20 日是星期一。你想要类似的东西

    String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, yyyy";
    SimpleDateFormat userDateFormatter = new SimpleDateFormat(
            userDateFormat);
    String reference_date = "2000 hrs, Monday, July 20, 2015";
    

    然后输出

    2000 hrs, Monday, July 20, 2015
    

    然后SimpleDateFormatJavadoc 说(部分)

    Letter    Date or Time Component  Presentation    Examples
    G         Era designator          Text            AD
    y         Year                    Year            1996; 96
    Y         Week year               Year            2009; 09
    

    【讨论】:

      猜你喜欢
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多