当前位置: 首页 > 面试题库 >

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

萧伟兆
2023-03-14
问题内容

具有创建仅时间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周)时,似乎出现了问题。我找不到问题的模式,例如夏令时/冬令时,AM /
PM等。错误是零星的,这意味着一分钟它将抛出NumberFormatException,而下一分钟它将运行良好。

我怀疑在JVM甚至CPU的某处都会发生某种算术故障。上述例外情况表明其中涉及浮点数,但我看不到它们的来源。据我所知,Java的Date对象是一个包装器,用于包装long自时代以来的毫秒数。

我猜测正在发生的是onlyTimeStr在第5行中创建了一个意外的字符串,因此问题确实出在这里,而不是在第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仅返回
整数小时
的偏移量(并且存在不在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;
}


 类似资料:
  • 问题内容: 我有两个时间戳,它们以两种不同的格式描述同一时刻。 和。 我用Joda-Time用两个不同的日期格式解析时间戳。最后,我想有两个DateTime对象,它们在同一时刻相同。 DateFormatter提供了几种控制时区和语言环境的方法,但我无法使其正常工作。 这是我想工作的代码: 问题答案: 如果您的默认时间zome是Europe / Berlin,则2010-10-03 18:58:0

  • 我想使用此服务:http://fast-gorge.herokuapp.com/contacts我设置Retrofit解析如下: 其中,我的日期格式为: 然而,当我运行该应用程序时,我进入了failure(reformerror error)方法,并显示消息:reformation。改装错误:com。谷歌。格森。JsonSyntaxException:2014-07-31T07:49:23.000

  • 我需要在Dart中的对象中解析这种日期“Mon,2014年8月11日12:53 pm PDT”。 有一个静态方法,它接受ISO 8601格式的子集,而不是我的情况。 类允许您定义要分析的日期模式。我创建了一个模式“EEE,dd-MMM-yyy-hh:mm-a-zzz”。 使用它,我得到一个读取一个。 看起来解析器不喜欢PM标记的情况(我已经提出了一个问题)。 我试着解决整个管柱上套管的问题。使用字

  • 问题内容: 我正在使用python-dateutil从字符串中解析日期: 我期望的是引发异常,但它返回的是当前日期。如果在提供的字符串中找不到日期,有人可以告诉我如何避免获取当前日期吗? 提前致谢。 问题答案: 请参阅dateutil文档,特别是解析函数(强调我的): 此外,可以使用以下关键字参数: 默认值 如果给出,则它必须是日期时间实例。解析日期中缺少的任何字段都将从该实例复制。 默认值为当前

  • 问题内容: 我的日期格式为dd-mmm-yy或d- mmm-y,其中月份是字母的缩写(例如,09年11月4日或05年12月12日等)。喜欢解析它以产生一个java.util.Date对象。 可以通过利用java.text.DateFormat类来实现吗?还是有另一种简单的方法? 问题答案: 您可能需要使用SimpleDateFormat来解析自定义格式。此文章解释格式的细节。

  • 嗨,我正在尝试以YYYY-MM-DD格式解析日期。我正在尝试这个: 但是我得到了错误,我想这是一个解析错误, 0001-01-01 00:00:00 0000 UTC解析时间“2016-01-1”为“2020-12-30”:无法将“-01-01”解析为“0” 我该如何解析它,或者通过其他示例给出一些提示?蒂亚。