Java中奇怪的日期解析错误

6

在Java中解析大量日期时,我偶尔会遇到这个奇怪的错误:

java.lang.NumberFormatException: For input string: ".201144E4.201144E4"
    at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1250)
    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:1793)
    at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
    at java.text.DateFormat.parse(DateFormat.java:355)
    at gameloop.tf2tradebot.user.UserManager.getUser(UserManager.java:102)
    at gameloop.tradebot2.bot.weaponbot1.Weaponbot1.onMessageReceived(Weaponbot1.java:269)
    at gameloop.api.steam.chat.ChatEvent.run(ChatEvent.java:49)
    at java.lang.Thread.run(Thread.java:745)

在这种情况下,日期是:
2014-12-13 06:56:27

日期格式为:
private static final DateFormat STANDARD_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);

我的代码:

Date firstSeenDate = null;
try
{
    firstSeenDate = STANDARD_DATE_FORMAT.parse(firstSeen);
}
catch(Exception pe)
{
    pe.printStackTrace();
    logger.outputError(4001, "Error parsing first seen date. Shutting down...");
    logger.outputError(4001, "First seen date : \'" + firstSeen + "\'");
    CH405BotServer.shutdown(logger.getCallerName(), "an error in parsing first seen date");
}
user.setFirstSeen(firstSeenDate);

源数据:

isadmin = false
firstseen = 2014-12-13 06:56:27
lastseen = 2014-12-13 06:56:27
numtrades = 0

编辑: 错误日志中的字符串看起来完全正常:

(ERROR 4001) Error parsing first seen date. Shutting down...
(ERROR 4001) Last seen date : '2014-12-13 06:56:27'

我需要帮助解决这个问题。


4
看起来你只是得到了错误的数据 - 你正在尝试解析一个值为".201144E45.201144E4"的数据,这显然不是 yyyy-MM-dd HH:mm:ss 格式的日期/时间。不幸的是,你没有告诉我们数据从哪里来。 - Jon Skeet
5
多个线程似乎在竞争使用同一实例并破坏其内部状态,这是真的吗? - jmj
3
可以的,尝试将 DateFormat 移到局部变量,然后再试一次。 - jmj
1
【来自文档】(https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html):“日期格式不同步。建议为每个线程创建单独的格式实例。如果多个线程同时访问格式,则必须在外部进行同步。”(虽然很神秘,但“解析”可能会导致内部损坏...?) - Boann
3
如果您使用的是Java 8,标准格式化程序是线程安全的 - Ray Toal
显示剩余14条评论
1个回答

5
我怀疑这是由竞争条件引起的,SimpleDateFormat不是线程安全的,如果多个线程尝试使用同一个实例将日期从字符串解析为日期,则可能会搞乱该实例的内部状态。我建议使用本地变量(警告:创建此实例很昂贵),因此如果您认为它太频繁,可以使用{{link1:FastDateFormat}}(线程安全的SimpleDateFormat实现),或者按照@Ray的建议切换到Java8

plus1,谢谢你,我有一种不好的感觉,这个 bug 是由一个更大的问题引起的。 - Hele

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接