【问题标题】:java.text.ParseException: Unparseable date: "1901-01-01 00:00:00"java.text.ParseException:无法解析的日期:“1901-01-01 00:00:00”
【发布时间】:2016-01-28 10:59:13
【问题描述】:

这段代码在 Windows 中可以正常工作,但在 Linux 中会抛出 java.text.ParseException:

DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", new Locale("es", "ES"));
df.setLenient(false);
Date date = df.parse("1901-01-01 00:00:00");
System.out.println(date);

Windows 输出:

Tue Jan 01 00:00:00 CET 1901

Linux 输出:

Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.simontuffs.onejar.Boot.run(Boot.java:340)
        at com.simontuffs.onejar.Boot.main(Boot.java:166)
Caused by: java.text.ParseException: Unparseable date: "1901-01-01 00:00:00"
        at java.text.DateFormat.parse(DateFormat.java:357)
        ...

如果删除df.setLenient(false) 行,Windows 输出相同,Linux 异常消失,但 Linux 输出似乎不正确:

Tue Jan 01 00:14:44 CET 1901

有人知道发生了什么吗?

谢谢

配置:
视窗:Win7 + jdk1.7.0_71
Linux:Ubuntu + jdk1.7.0_60

编辑:正如 anolsi 所说,这是一个夏令时问题。对于日期“2015-03-29 02:00:01”,在 Windows 和 Linux 中会引发解析异常,因为马德里不存在此日期(马德里的时间从凌晨 2:00 更改为凌晨 3:00那天)。所以正确的行为是 Linux 的行为。 Windows JDK 应该抛出异常。

【问题讨论】:

  • Linux 上是 Oracle 还是 OpenJDK?不应该有所作为,但以防万一。
  • 应该不是问题。对我来说很好。
  • 可能是已在 u60 和 u71 之间修复的问题。尝试更新 JDK。
  • Java 是否使用主机操作系统中的任何时区/区域设置数据库(或全部滚入 JDK)?如果是这样,也可能是 Ubuntu 问题。
  • 有趣。我刚刚在我的 Linux 机器上运行了你的代码,它就可以工作了!

标签: java linux simpledateformat java.util.date


【解决方案1】:

这应该与您使用的区域设置/时区定义有关。

您可以在http://www.timeanddate.com/time/change/spain/madrid?year=1901 下查看该时区不存在特定时间,因为 DST(夏令时)。这应该是造成不一致的原因。

例如,如果您尝试改用 1901-02-01 00:00:00,它应该可以正常工作。

EDIT1:允许更改和控制时区的示例。

import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Locale;
import java.util.TimeZone;
import java.util.Date;

public class MainClass
{
  public static void main(String[] args)
  {
    try {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", new Locale("es", "ES"));
        df.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));
        df.setLenient(false);
        Date date = df.parse("1901-01-01 00:00:00");
        System.out.println(date);
    } catch(Exception ex){
        ex.printStackTrace();
    }

  }
}

EDIT2:请查看有关时区和偏移量的好文章:https://stackoverflow.com/tags/timezone/info

【讨论】:

  • 那么 Linux 的行为实际上是正确的吗?
  • 我对此并不满意,我在本地 linux 机器上尝试了相同的代码,它可以工作。你怎么解释?
  • 因为您的 Linux 下的 uimezone 不应该使用马德里时区。我不确定本地是否也会设置时区。
  • @Thilo 这将取决于它如何真正假设时区。问题可能就在那里。但事实上,具体时间并不存在(考虑到西班牙)。这是关于 DST 的常见问题。看起来是正确日期的值,但并不代表任何已知的时间。
  • 因此,为了使这一过程可跨系统重现,可以在某处指定一个明确的时区(马德里的时区)?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-29
  • 1970-01-01
  • 1970-01-01
  • 2012-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多