gpt4 book ai didi

java - 使用 SimpleDateFormat.parse() 解析日期时出现 NumberFormatException

转载 作者:IT老高 更新时间:2023-10-28 20:32:35 27 4
gpt4 key购买 nike

有一个函数可以创建一个只有时间的 Date目的。 (为什么需要这个是一个很长的故事,在这种情况下是无关紧要的,但我需要与 XML 世界中的一些东西进行比较,其中 TIME(即仅时间)是一个有效的概念)。

private static final SimpleDateFormat DF_TIMEONLY = new SimpleDateFormat("HH:mm:ss.SSSZ");    

public static Date getCurrentTimeOnly() {

String onlyTimeStr = DF_TIMEONLY.format(new Date()); // line #5
Date onlyTimeDt = null;
try {
onlyTimeDt = DF_TIMEONLY.parse(onlyTimeStr); // line #8
} catch (ParseException ex) {
// can never happen (you would think!)
}
return onlyTimeDt;
}

可能至少还有其他几种方法可以在 Java 中创建仅时间日期(或者更准确地说,日期部分是 1970-01-01),但我的问题实际上与此无关。

我的问题是,这段代码在生产环境中运行了很长时间后,开始在第 8 行随机抛出 NumberFormatException。从技术上讲,我会说这应该是不可能的,对吧?

这是来自上述代码的随机 NumberFormatExceptions 的摘录:

java.lang.NumberFormatException: multiple points
java.lang.NumberFormatException: For input string: ".11331133EE22"
java.lang.NumberFormatException: For input string: "880044E.3880044"
java.lang.NumberFormatException: For input string: "880044E.3880044E3"

首先我希望我们能同意,正式地这应该是不可能的?该代码使用相同的格式 (DF_TIMEONLY) 作为输出然后输入。如果您不同意这应该是不可能的,请告诉我。

我无法在独立环境中重现该问题。当JVM运行很长时间(> 1周)时,问题似乎就来了。我找不到问题的模式,即夏令时/冬令时、上午/下午等。错误是零星的,这意味着前一分钟会抛出 NumberFormatException,下一分钟会正常运行。

我怀疑 JVM 甚至 CPU 中的某处存在某种算术故障。上述异常表明涉及 float ,但我看不出它们来自哪里。据我所知,Java 的 Date 对象是一个 long 的包装器,它保存了自纪元以来的毫秒数。

我猜发生了什么是在第 5 行创建了一个意外的字符串 onlyTimeStr 所以问题真的出在这里而不是在第 8 行。

这是一个完整的堆栈跟踪示例:

java.lang.NumberFormatException: For input string: "880044E.3880044E3"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1241)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2086)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at org.mannmann.zip.Tanker.getCurrentTimeOnly(Tanker.java:746)

环境:Java 7

最佳答案

可能的原因是 SimpleDateFormat 不是线程安全的,并且您从多个线程中引用它。虽然极其难以证明(并且几乎同样难以测试),但有一些证据表明情况确实如此:

  1. .11331133EE22 - 注意一切是如何翻倍的
  2. 880044E.3880044E3 - 此处相同

您可能至少有两个线程交错。 E 把我扔了,我以为它试图处理科学记数法(1E10 等),但它可能是 时区 的一部分。

谢天谢地,(格式化)基本修复很简单:

private static final String FORMAT_STRING = "HH:mm:ss.SSSZ";    

public static Date getCurrentTimeOnly() {

SimpleDateFormat formatter = new SimpleDateFormat(FORMAT_STRING);

String onlyTimeStr = formatter.format(new Date());
return formatter.parse(onlyTimeStr);
}

您还可以在这里做一些其他事情,但有几点需要注意:

1 - 如果时区是 UTC(或任何没有 DST),这很简单

public static Date getCurrentTimeOnly() {

Date time = new Date();

time.setTime(time.getTime() % (24 * 60 * 60 * 1000));

return time;
}

2 - 您将无法测试此方法,因为您无法安全地暂停时钟(您可以更改时区/语言环境)。为了更好地处理 Java 中的日期/时间,请使用 JodaTime 之类的内容。 .请注意,LocalTime 没有附加时区,但 Date 仅返回 整数小时 的偏移量(并且有 zones not on the hour );为了安全起见,您需要返回一个 Calendar (带有完整时区),或者只返回没有它的东西:

// This method is now more testable.  Note this is only safe for non-DST zones
public static Calendar getCurrentTimeOnly() {

Calendar cal = new Calendar();

// DateTimeUtils is part of JodaTime, and is a class allowing you to pause time!
cal.setTimeInMillis(DateTimeUtils.currentTimeMillis() % (24 * 60 * 60 * 1000));

return cal;
}

关于java - 使用 SimpleDateFormat.parse() 解析日期时出现 NumberFormatException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21017502/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com