【问题标题】:Why am I getting a ParseException when using SimpleDateFormat to format a date and then parse it?为什么在使用 SimpleDateFormat 格式化日期然后对其进行解析时出现 ParseException?
【发布时间】:2010-06-03 15:52:24
【问题描述】:

我一直在调试一些现有代码,这些代码在我的系统上单元测试失败,但在同事的系统上却没有。根本原因是 SimpleDateFormat 在解析应该可解析的日期时抛出 ParseExceptions 。我创建了一个单元测试来演示在我的系统上失败的代码:

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

import junit.framework.TestCase;

public class FormatsTest extends TestCase {

    public void testParse() throws ParseException {
        DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS Z");
        formatter.setTimeZone(TimeZone.getDefault());
        formatter.setLenient(false);

        formatter.parse(formatter.format(new Date()));
    }
}

此测试在我的系统上引发 ParseException,但在其他系统上成功运行。

java.text.ParseException: Unparseable date: "20100603100243.118 -0600"
    at java.text.DateFormat.parse(DateFormat.java:352)
    at FormatsTest.testParse(FormatsTest.java:16)

我发现我可以setLenient(true) 并且测试会成功。 setLenient(false) 是该测试模拟的生产代码中使用的,所以我不想更改它。

【问题讨论】:

  • 我不确定,但您也可以查看 TimeZone 吗?我觉得TimeZone可以基于系统吧?
  • 我已在原始帖子中更新了我的测试类和堆栈跟踪,以删除与我发现错误的应用程序相关的命名。代码已从我的编辑器复制并粘贴到浏览器;唯一的编辑是按照 Stack Overflow 的要求将代码缩进四个空格。堆栈跟踪也是如此,尽管我删除了测试运行工具中调用的堆栈跟踪行。如果您想查看它们,我可以添加它们。
  • 您使用什么版本的 JDK 来编译以及您在什么版本的 JRE 上运行这些。这很可能是问题所在。
  • @Fuzzy 我不这么认为。 format.parse(format.format(new Date())) 怎么可能在运行的 JRE 中抛出 ParseException?
  • 我正在使用 Rational Application Developer 7 来编译和运行测试。我正在开发的项目针对 WebSphere 6.1,因此我在与之关联的 IBM JRE 中运行测试:IBM J9 VM(构建 2.3,J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32 j9vmwi3223-20060504(启用 JIT) . 这是团队其他人用来运行相同测试的同一个 JRE,并且在其他机器上测试成功。我只是尝试使用 Sun Java 6 JRE (1.6.0_20) 运行测试,然后测试运行成功。我不知道该怎么做。

标签: java simpledateformat


【解决方案1】:

--- 在响应表明​​开发人员正在使用 IBM 的 J9 1.5.0 Java 虚拟机后编辑---

IBM 的 J9 JVM 似乎在 DateFormat 的解析例程中存在一些错误和不兼容性,SimpleDateFormat 很可能继承了它,因为它是 DateFormat 的子类。一些证据支持 IBM 的 J9 的运行方式与您可能期望的其他 JVM(如 Sun 的 HotSpot JVM)的运行方式不同 here

请注意,这些错误和不兼容性在 J9 JVM 中甚至不一致,换句话说,IBM J9 格式化逻辑实际上可能会生成与 IBM J9 解析逻辑不兼容的格式化时间。

似乎与 IBM 的 J9 JVM 相关的人倾向于通过不使用 DateFormat.parse(...)(或 SimpleDateFormat.parse(...))来解决 JVM 中的错误。相反,他们倾向于使用 java.util.regex.Matcher 手动解析字段。

也许 J9 JVM 的更高版本解决了这个问题,也许没有。

--- 原帖如下---

搞笑,同样的代码修改为:

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

public class FormatsTest {

 public void testParse() throws ParseException {
  DateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss.SSS Z");
  formatter.setTimeZone(TimeZone.getDefault());
  formatter.setLenient(false);
  System.out.println(formatter.format(new Date()));

  formatter.parse(formatter.format(new Date()));
 }

 public static void main(String[] args) throws Exception {
   FormatsTest test = new FormatsTest();
   test.testParse();
 }

}

在我的系统上运行良好。我敢打赌,这是在你的环境中的东西。您正在一个 JVM 主要版本上编译代码并在另一个版本上运行它(这可能会导致一些问题,因为库可能已过时),或者您正在运行它的系统可能会奇怪地报告时区信息。

最后,您可能需要考虑是否正在使用 JVM 的早期版本。有时错误确实会蔓延到各个版本中,并且会在以后的版本中得到修复。您能否修改您的问题以包含您系统的“java -version”信息?

无论哪种方式,这两者都只是有根据的猜测。代码应该按照编写的方式工作。

【讨论】:

  • java version "1.6.0_17" OpenJDK Runtime Environment (IcedTea 1.7.1) (fedora-37.b17.fc12-x86_64) OpenJDK 64-Bit Server VM (build 14.0-b16, mixed mode)
  • 我得到:20100603101026.294 -0600 线程“main”中的异常 java.text.ParseException:无法解析的日期:java.text.DateFormat.parse(DateFormat.java:352) 处的“20100603101026.294 -0600” FormatsTest.testParse(FormatsTest.java:15) at FormatsTest.main(FormatsTest.java:20) 使用:java 版本“1.5.0”Java(TM) 2 运行时环境,标准版(构建 pwi32dev-20060511( SR2)) IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32 j9vmwi3223-2006050 4 (JIT enabled) J9VM - 20060501_06428_lHdSMR JIT - 20060428_1800_r8 GC - 20060501_AA) J9VM - 20060501_06428_lHdSMR JIT - 20060428_1800_r8 GC - 20060501_AA1a2CL ->
  • 我认为这与您的生产环境的配置相同?
  • 原始帖子已编辑,问题可能不在编译器方面,而是在标准 java 库的 IBM J9 版本中的 java.util.DateFormat 类中。
  • 顺便说一句,我同意代码应该按照编写的方式运行,实际上在我运行过它的其他计算机上按照编写的方式运行。
【解决方案2】:

这应该是 IBM 的 J9 VM 中关于 SimpleDateFormat 类的错误。

This post 显示类似问题,并表示应该在 v6 上修复。

您可以找到多个版本的更改列表here

我看到有一个与 DateFormat 相关的数字。因此,您可能应该向 IBM 提出错误报告或其他东西,让他们为您提供补丁。

【讨论】:

  • 顺便说一句,关于那些其他计算机,它们是否使用与您相同的配置? (可能有人在他们的计算机上安装了 Sun 的 JDK,这就是它运行良好的原因)
  • 我查了一下,有些人的 IBM JVM 比我更新,但他们都在使用 IBM JVM。我会尝试升级,看看是否能解决问题。
【解决方案3】:

检查您的计算机和远程计算机的 LANG 环境变量。

日期是根据语言环境解析的,所以“Jul”只有在 LANG 设置为英语时才作为 7 月起作用,否则会引发 ParseException。

您可以通过运行export LANG="en_US.UTF-8" 进行快速测试,然后运行您的程序。

您还可以使用以下方法以编程方式设置语言环境: DateFormat.getDateInstance(int, java.util.Locale)

【讨论】:

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