SimpleDateFormat.parse生成不一致的结果

时间:2017-07-19 16:25:47

标签: java scala simpledateformat

我正在使用SimpleDateFormat将字符串解析为DateTime,如下面的代码所示。

val formatSrc = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
formatSrc.setLenient(false)
val temp = formatSrc.parse("2017-02-04T09:55:42.000Z")
print(temp)

结果应该是 Sat Feb 04 09:55:42 UTC 2017 但是,我会得到不一致的结果,例如,它可能低于Tue Feb 04 00:00:04 UTC 2200,或Wed Feb 04 09:55:42 UTC 2201,或其他一些东西。 顺便说一下,我使用Scala和Spark来处理一些文本数据。 知道为什么吗?

4 个答案:

答案 0 :(得分:2)

问题是可能是(虽然无法确定)并发问题:SimpleDateFormat不是线程安全的,来自其Javadoc:

  

日期格式未同步。   建议为每个线程创建单独的格式实例。   如果多个线程同时访问格式,则必须同步它   外部。

Spark明显使用多个线程(一般来说,每个分区一个) - 如果这些线程共享相同的SimpleDateFormat实例,那么这将解释您所看到的行为。

要解决此问题 - 请使用其他线程安全格式化程序,或为每个记录/分区创建单独的格式化程序。

答案 1 :(得分:1)

在格式化程序上将时区设置为UTC(GMT),否则尾随" Z"您已经转义(因此错误地将其解释为文字)不能被理解为UTC + 00:

formatSrc.setTimeZone(TimeZone.getTimeZone("GMT"));

注意:如果您想将解析后的结果与方法print(temp)进行比较,那么我担心您只是隐式使用Date - 方法toString()它使用完全不同的格式(在您的默认时区中)。

答案 2 :(得分:0)

我认为Tzach的回答是有道理的。我没有为每个线程创建一个单独的实例。所以它应该是多线程问题,因为Spark显然是多线程的。我用Joda DateTimeFormat替换,这是线程安全的。然后问题解决了。 http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html

答案 3 :(得分:0)

您的日期时间格式完全符合ISO 8601标准。现代Java日期&时间API与ISO 8601一起工作得很好。所以我建议你使用它。

很抱歉,我无法编写Scala代码,因此您必须从Java翻译:

    Instant temp = Instant.parse("2017-02-04T09:55:42.000Z");

优点:

  • 您已跳过过时的SimpleDateFormatDate课程,并已开始使用现代替代课程。
  • 这是一行而不是三行,更清楚地表达你的意图。
  • 解析是线程安全的,所以如果Tzach Zohar猜对了,它就解决了你的问题。