将String解析为java.util.Date

时间:2018-05-17 14:15:42

标签: java string parsing datetime date-conversion

我试图转换输入日期字符串" 2018-09-31"到目前为止。我期待它是" 2018-09-30"或者至少" 2018-09-30T00:00:00Z"。但令人惊讶的是,事实证明它是不同的。有人可以解释为什么这样吗?以及如何才能使输入日期匹配?

import org.apache.commons.lang3.time.FastDateFormat;

private static final FastDateFormat dateOnlyFormat = FastDateFormat.getInstance("yyyy-MM-dd");

@Test
public void getSQLDateWithOnlyDate() {
    java.util.Date date = null;
    try {
        String dateString = "2018-09-31";
        date = dateOnlyFormat.parse(dateString);
        System.out.println("input date : " + dateString);
        System.out.println("date.toInstant() : " + date.toInstant());
        System.out.println("date.toString() : " + date.toString());
    } catch (ParseException e) {
        e.printStackTrace();
    }

}

输出

input date : 2018-09-31
date.toInstant() : 2018-09-30T14:00:00Z
date.toString() : Mon Oct 01 00:00:00 AEST 2018

1 个答案:

答案 0 :(得分:2)

出了什么问题?

OH GOD SPIDERS已经在评论中解释了其中的一些内容。九月有30天。您的格式化程序推断:9月31日是指9月30日之后的那一天,即10月1日。

但是时间14:00:00?这是一个时区问题。未通知的格式化程序使用JVM的时区设置。例如,这可能是澳大利亚/悉尼,至少你的Date将其呈现为AEST,我将其视为澳大利亚东部标准时间。因此,您的字符串将被解析为10月1日00:00:00,距离UTC +10:00。这与9月30日14:00:00 UTC的时间点相同。由于Instant.toString()以UTC为单位呈现时间点(由Z后缀表示),因此您获得2018-09-30T14:00:00Z

修复它

当他们试图在你的程序上玩耍时,我建议你真的想反对。我知道你只想约会,而不是一天中的某个时间。

    String dateString = "2018-09-31";

    try {
        LocalDate.parse(dateString);
    } catch (DateTimeParseException dtpe) {
        System.out.println(dtpe);
    }

打印:

  

java.time.format.DateTimeParseException:文字'2018-09-31'不能   被解析:无效日期'9月31日'

如果你确实想要你观察到的外推行为:

    DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE
            .withResolverStyle(ResolverStyle.LENIENT);
    System.out.println(LocalDate.parse(dateString, dateFormatter));
  

2018年10月1日

你说过你曾预料到2018-09-30,但我知道没有直截了当的方式给你这个。我的第一个建议是你再想一想,问你是否真的需要这个。

在我的代码中,我使用的是java.time,即现代Java日期和时间API。我推荐它。 LocalDate是一个没有时间的日期。在我看来,这两者都很适合您的要求,从一开始就可以防止您的时区问题。

您的方法名称getSQLDateWithOnlyDate可能暗示您打算将您的日期用于SQL数据库? LocalDate(和其他java.time类型)的一个优点是,您可以直接将其传递给PreparedStatement的{​​{1}}方法,只要您至少使用Java 8和至少JDBC 4.2。您的JPA实现也应该乐于接受setObject对象。

链接: Oracle tutorial: Date Time解释如何使用LocalDate