Scala Spark中ISO 8601 timestemp字符串的日期差异
我有两个ISO 8601格式的日期时间字符串: 2017-05-30T09:15:06.050298ZScala Spark中ISO 8601 timestemp字符串的日期差异,scala,datetime,apache-spark,timestamp,Scala,Datetime,Apache Spark,Timestamp,我有两个ISO 8601格式的日期时间字符串: 2017-05-30T09:15:06.050298Z 2017-05-30T09:15:06.054939Z 我想要在Spark环境中使用Scala计算上述两个字符串之间的时间差 您可以使用xml日期解析器,因为它必须遵守ISO-8601: val t1 = javax.xml.bind.DatatypeConverter.parseDateTime("2017-05-30T09:15:06.050298Z") val t2 = javax.x
2017-05-30T09:15:06.054939Z
我想要在Spark环境中使用Scala计算上述两个字符串之间的时间差 您可以使用xml日期解析器,因为它必须遵守ISO-8601:
val t1 = javax.xml.bind.DatatypeConverter.parseDateTime("2017-05-30T09:15:06.050298Z")
val t2 = javax.xml.bind.DatatypeConverter.parseDateTime("2017-05-30T09:15:06.054939Z")
val diff = t1.getTimeInMillis - t2.getTimeInMillis
Java 8的LocalDateTime
为纳秒
由于Spark不支持大于秒的日期差,我们需要为毫秒或纳米创建一个UDF
与日期时间相关的导入
以纳秒为单位创建UDF到日期的差异
检查:
通过将当天的ChronoField.NANO\u修改为当天的ChronoField.MICRO\u
在UDF的最后一行中,我们还可以获得微秒级的日期差
现在,在任何DataFrame/DataSet对象上使用UDF
import spark.implicits._ //to use $-notation on columns
// create the dataframe df
val df = ...
val resultDf = df.withColumn("date_diff", date_diff_nano($"dt1", $"dt2"))
这里dt1
和dt2
是df
秒差与Spark SQL的unix\u时间戳
使用Spark SQL预定义函数将日期转换为一天中的秒数(但是JavaSimpleDataFormat
可以支持长达毫秒的解析),然后您就可以这样做了
使用datediff
它接受以下格式的日期时间值
java.sql.Timestamp
java.sql.Date
'YYYY-MM-dd'
'YYYY-MM-dd HH:MM:ss'的字符串格式
正如你在评论中所说,你使用的是Joda Time,这里有一个使用它的答案
你说你在两天之间打电话给。但是两个日期都在同一天,所以结果总是零。要获得毫秒精度的日期差,只需从两个DateTime
对象中减去毫秒值:
import org.joda.time.DateTime
val s1 = "2017-05-30T09:15:06.050298Z"
val s2 = "2017-05-30T09:15:06.054939Z"
val diffInMillis = DateTime.parse(s2).getMillis() - DateTime.parse(s1).getMillis()
diffInMillis
将是4
——第一个日期的秒分数是050298
,第二个是054939
,但joda的DateTime
具有毫秒精度,因此最后3位数字被丢弃。您可以通过执行以下操作进行检查:
println(DateTime.parse(s1))
println(DateTime.parse(s2))
这将输出:
2017-05-30T09:15:06.050Z
2017-05-30T09:15:06.054Z
如您所见,日期之间的差异为4毫秒
新的Java日期/时间API
Joda Time处于维护模式,正在被新的API所取代,因此我不建议使用它启动新项目。甚至在文章中也提到:“请注意,Joda Time被认为是一个基本上“完成”的项目。没有计划进行重大的增强。如果使用Java SE 8,请迁移到Java.Time(JSR-310)。”
如果您有新的java.time
API(JDK>=1.8),您也可以使用它。如果java.time
类不可用(JDK你试过什么吗?你说的spark env是什么意思,你有spark dataframe和rdd吗?是的,我试过几个选项。spark env只是一个可选的。我有一个spark dataframe,我也在检查非dataframe操作。我试过org.joda.time.DateTime,在那里我只能找到天之间的差异。那又怎样那么,你想得到差异吗?例如,我得到的代码输出是:d1:org.joda.time.DateTime=2017-05-30T09:15:06.050Z d2:org.joda.time.DateTime=2017-05-30T09:15:06.054Z days:Int=0如果我在两天之间尝试,那么差异是0。但是我不想要日差,我要的是秒/毫秒差到分d差异(如果有)。您使用的是哪种spark版本?spark SQL unix_时间戳将忽略毫秒部分。它在您链接到的文档中明确说明了这一点。@sradomski:很高兴看到建设性的反馈。我更正了它并添加了其他信息。我们现在放弃了spark毫秒处理,并将时间戳编码为UTC后的毫秒大纪元。
import org.apache.spark.sql.functions.unix_timestamp
val resultDf = df.withColumn("date_diff_sec",
(unix_timestamp($"dt1"), unix_timestamp($"dt2")))
import org.apache.spark.sql.functions.datediff
val resultDf = df.withColumn("date_diff_days", datediff($"dt1", $"dt2"))
import org.joda.time.DateTime
val s1 = "2017-05-30T09:15:06.050298Z"
val s2 = "2017-05-30T09:15:06.054939Z"
val diffInMillis = DateTime.parse(s2).getMillis() - DateTime.parse(s1).getMillis()
println(DateTime.parse(s1))
println(DateTime.parse(s2))
import java.time.Instant
import java.time.temporal.ChronoUnit
val s1 = "2017-05-30T09:15:06.050298Z"
val s2 = "2017-05-30T09:15:06.054939Z"
// difference in nanoseconds
val diffInNanos = ChronoUnit.NANOS.between(Instant.parse(s1), Instant.parse(s2))