返回 Java 代码中 SimpleDateFormat 的 NumberFormatException。

huangapple go评论79阅读模式
英文:

Returning NumberFormatException form SimpleDateFormat in Java code

问题

我已在常量文件中将一个SimpleDateFormat对象声明为静态字段,如下所示:

Constants.java

public static final SimpleDateFormat GENERAL_TZ_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");

在我的类文件中,我的实现如下:

String fDate = getTextValue(empNo, "firstDate");
if (null != fDate && !fDate.isEmpty()) {
    try {
        Date date = (Date)(Constants.GENERAL_TZ_FORMATTER).parse(fDate);
        issue.setDate(date.getTime());
    } catch (ParseException e) {
        logUtil.error(LOG, e+ "date : " + date);
    }
}

错误信息:

Exception while importing data. package name.SecureException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)

我的问题是,在某些情况下,这会抛出一个NumberFormatException(非常罕见的情况),因此我一直在思考,大多数情况下都解释说这种情况可能是由于SimpleDateFormat不是线程安全的。如果是这种情况,我不清楚在没有使用多个线程的多线程环境中运行此代码,是否会使输入传递给DateFormat.parse()的是空字符串?

Java的SimpleDateFormat不是线程安全的文章

我已经尝试解决这个问题,但是很难重现这个问题,我想知道你对此的看法,这将帮助我找到一个更好的解决方案。非常感谢您的建议。
谢谢。

英文:

I have declared a SimpleDateFormat object as a static field inside the constant file as follows,

Constants.java

public static final SimpleDateFormat GENERAL_TZ_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");

and inside my class file my implementation like this.

String fDate = getTextValue(empNo, "firstDate");
if (null != fDate && !fDate.isEmpty()) {
    try {
        Date date = (Date)(Constants.GENERAL_TZ_FORMATTER).parse(fDate);
        issue.setDate(date.getTime());
    } catch (ParseException e) {
        logUtil.error(LOG, e+ "date : " + date);
    }
}

Error :

Exception while importing data. package name.SecureException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)

My problem is, in some cases, this throws a NumberFormatException (a very rare situation), so I've been wondering about that an I did a diagnosis, and most of them are explaining this case might happen due to that SimpleDateFormat is not thread-safe. If this is the case, I'm not clear how this code running in a multiple thread environment without using multiple threads, would it make the input to DateFormat.parse() an empty string?

Java's SimpleDateFormat is not thread-safe article

I have tried to solve this problem, but It's really hard to recreate this issue, I like to know your ideas about this and it will help me to find a better solution. Really appreciate your suggestions.
Thank you.

答案1

得分: 3

如您帖子下方的评论已经提到的,您不应该使用 SimpleDateFormat

您可能已经遇到了 SimpleDateFormat 导致问题的情况。然而,这不是唯一的原因。这个 Stackoverflow 帖子解释了为什么 它如此令人头疼。同样帖子中的一个原因提到 SimpleDateFormat 不是线程安全的。线程安全是指当多个进程作用于格式化程序时,即利用格式化程序格式化日期,并且由于干扰而不会发生错误、不准确或未定义的结果。

您在 Callicoder 上的文章链接 很好地解释了为什么 SimpleDateFormat 会引起问题。帖子中提到了与您遇到的相同的异常:

> > java.lang.NumberFormatException: For input string: "" >

简而言之,当线程使用格式化程序时会发生干扰,因为格式化程序没有同步。这意味着 SimpleDateFormat 类不强制要求一个线程必须等待,直到另一个线程完成修改其内部状态。使用的三个类是 SimpleDateFormatDateFormatFieldPosition

返回 Java 代码中 SimpleDateFormat 的 NumberFormatException。 这里是有问题代码的实际情况

使用 java.time

您需要迁移到较新的 Java 8 日期和时间 API,位于 java.time 包中。它们是绝对线程安全的,因为它们是不可变的。在您的情况下,使用 java.time.format.DateTimeFormatter

public static final DateTimeFormatter GENERAL_TZ_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
ZonedDateTime zdt = ZonedDateTime.parse(fDate, GENERAL_TZ_FORMATTER);
Instant instant = zdt.toInstant();

// Your setDate should really accept an Instant:
issue.setDate(instant);
// If that's REALLY not possible, then you can convert it to an integer
// value equal to the number of milliseconds since 1 January 1970, midnight
//issue.setDate(instant.toEpochMilli());
英文:

Well, as the comment below your post already mentioned, you shouldn't use SimpleDateFormat anyway.

You have probably stumbled upon such case where SimpleDateFormat is troublesome. This is not the only reason, however. This Stackoverflow post explains why it is so troublesome. One of the reasons in that very same post mention SimpleDateFormat not being thread-safe. Thread-safety is that when multiple processes act upon the formatter, that is, leverage the formatter to format a date, and that no incorrect, inaccurate or undefined results occur because of interference.

Your link to the article on Callicoder explains pretty well why SimpleDateFormat cause trouble. The post mentions the same exception as you got:

>
> java.lang.NumberFormatException: For input string: ""
>

In short, the threads interfere when they use the formatter, because the formatter is not synchronized. That means that the SimpleDateFormat class does not enforce that one thread must wait until some other thread has finished with modifying its internal state. Three of the used classes are SimpleDateFormat, DateFormat and FieldPosition.

返回 Java 代码中 SimpleDateFormat 的 NumberFormatException。 Here's erroneous code in action.

Use java.time

You need to move to the newer Java 8 Date and Time API, available in the java.time package. They're absolutely thread-safe because of their immutable nature. In your case, use java.time.format.DateTimeFormatter:

public static final DateTimeFormatter GENERAL_TZ_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
ZonedDateTime zdt = ZonedDateTime.parse(fDate, GENERAL_TZ_FORMATTER);
Instant instant = zdt.toInstant();

// Your setDate should really accept an Instant:
issue.setDate(instant);
// If that's REALLY not possible, then you can convert it to an integer
// value equal to the number of milliseconds since 1 January 1970, midnight
//issue.setDate(instant.toEpochMilli());

huangapple
  • 本文由 发表于 2020年8月20日 16:04:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/63500822.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定