在我的计划中,我在ParseException
期间间歇性地SimpleDateFormat.parse
。{/ p>
我编写了一个apache storm bolt,因为我正在解析输入日期"2018-02-26 18:13:32 UTC"
。
每个输入日期都不会抛出此异常。此外,我已在错误日志中打印输入日期。视觉上输入日期格式没有问题。
但我得到ParseException
的间歇输入。
我怀疑是因为它是并发环境。
以下是代码段:
utcDateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss 'UTC'");
答案 0 :(得分:4)
我怀疑是因为它是并发环境。
实际上,这是最可能的原因,因为SimpleDateFormat
不是线程安全的。在此处查看问题分析以及如何解决问题:https://www.javaspecialists.eu/archive/Issue172.html
除此之外," UTC"是一个重要的信息(它表明,日期是UTC),因此您不能将其视为文字(内部引号)。您创建的格式化程序忽略日期为UTC(因为内部引用它被视为"某些文本" ,而不是"因为& #39;在UTC" ),所以它实际上使用的是JVM默认时区(不一定是UTC)。
要正确解析 UTC ,您必须使用z
模式:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
Date date = sdf.parse("2018-02-26 18:13:32 UTC");
但是如果您使用的是Java 8或更高版本,请使用新的日期API:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// parse date and time
.appendPattern("yyyy-MM-dd HH:mm:ss ")
// parse UTC
.appendOffset("+HH:MM", "UTC")
// create the formatter
.toFormatter();
OffsetDateTime odt = OffsetDateTime.parse("2018-02-26 18:13:32 UTC", fmt);
起初看起来似乎更复杂,但是这个新API提供了许多不同的日期时间类型以及更多解析和格式化它们的选项。
更重要的是:它的线程安全。
正如评论中所建议的,你也可以这样做:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzz");
ZonedDateTime zdt = ZonedDateTime.parse("2018-02-26 18:13:32 UTC", fmt);
如果您仍然需要使用java.util.Date
,则转换起来很容易:
Date javaUtilDate = Date.from(zdt.toInstant());
OffsetDateTime
类也有toInstant()
方法,因此两者都可以转换为Date
。
答案 1 :(得分:1)
SimpleDateFormat
不是线程安全的,你真的可以在并发环境中获得ParseException
。
有关详细信息,请参阅here。
对于Java 8,您可以使用线程安全的DateTimeFormatter
。