异常解析字符串到日期

deikduxw  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(577)

我不明白为什么这个代码会失败:

@Test
public void test() {
    final SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMddHHmm");
    try {
        sdf.setLenient(false);
        Date d = sdf.parse("202003290230");
    } catch (ParseException e){
        e.printStackTrace();
    }
}

我有个例外 java.text.ParseException: Unparseable date .
如果我设置 sdf.setLenient(true) 然后它就工作了,但是返回的对象日期中的时间是'03:30',而不是'02:30'。
有人能解释一下这里发生了什么事吗?谢谢。

ztyzrc3y

ztyzrc3y1#

正如上帝蜘蛛在一篇评论中指出的那样,你真正的问题是,由于Spring的到来,时间不存在于你的默认时区中,也就是过渡到夏季时间(dst)。

java.time文件

我建议您在日期和时间工作中使用java.time,即现代的java日期和时间api。短视的答案是:使用 LocalDateTime 来自java.time。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMddHHmm");
    String dateTimeString = "202003290230";
    LocalDateTime ldt = LocalDateTime.parse(dateTimeString, formatter);
    System.out.println(ldt);

输出为:
2020-03-29t02:30
LocalDateTime 是一个没有时区的日期和时间。所以它不会发现时间不存在于你的时区。结果是字符串中的2:30。

检测不存在的时间

似乎你在中欧时区或其他时区,夏季时间从三月的最后一个星期天开始,时钟从凌晨2点转到凌晨3点。所以没有2:30。假设你想知道,你可以:

ZoneId zone = ZoneId.of("Europe/Paris");
    ZonedDateTime zdt = ldt.atZone(zone);
    if (zdt.toLocalDateTime().equals(ldt)) {
        System.out.println("The time " + zdt + " exists");
    } else {
        System.out.println("The time " + ldt + " does not exist in " + zone);
    }

时间2020-03-29t02:30在欧洲/巴黎不存在
java.time也会给你3:30的时间,而不是2:30的时间。所以当你从 ZonedDateTimeLocalDateTime 在这种情况下,我们不再得到相同的时间,我们用它来检测不存在的时间。
我进一步建议你使用 ZonedDateTime 过去的日期和时间,而不是 LocalDateTime .

java 6?

这个项目是用java6和公司不想更新它…
time已经进行了后端口,我已经用backport测试了上面的代码,threeten backport,请参见底部的链接。
在Java8和更高版本以及更新的android设备上(api级别26),现代api是内置的。
在非android的java6和java7中,获得了三个十的backport,即现代类的backport(对于jsr310是三个十)。我不确定最新版本的threeten backport是适用于Java6还是仅适用于Java7(+)。如果这是一个问题,请返回几个版本,并找到一个同样适用于Java6的版本。
在旧的android上,要么使用desugaring,要么使用android版本的threeten backport。它叫3TENABP。在后一种情况下,请确保从导入日期和时间类 org.threeten.bp 有分装的。

不要使用SimpleDataFormat

你尝试使用的日期和时间类, Date 以及 SimpleDateFormat 设计拙劣,过时已久。在您的例子中,它们显示的行为取决于代码中根本不存在的时区,这非常令人困惑。我建议你不要使用这些类。

链接

oracle教程:date time解释如何使用java.time。
java规范请求(jsr)310,其中 java.time 第一次被描述。
三十后港工程 java.time 到Java6和Java7(jsr-310为310)。
通过desugaring提供Java8+API
threetenabp,android版threeten backport
问:如何在android项目中使用threetenabp,有非常透彻的解释。

相关问题