我正在使用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来处理一些文本数据。
知道为什么吗?
答案 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");
优点:
SimpleDateFormat
和Date
课程,并已开始使用现代替代课程。