【问题标题】:Convert week to date spark将星期转换为日期火花
【发布时间】:2017-05-05 05:24:11
【问题描述】:

我有一个格式为

的字符串
"5/02/2016" // d/ww/yyyy

我想转换成一种格式

yyyy-mm-dd

我已经尝试了以下

val df = Seq((1L, "5/02/2016"), (2L, "aaa")).toDF("id", "date")
val ts = unix_timestamp($"date", "d/ww/yyyy").cast("timestamp")
df.withColumn("ts", ts).show(2, false)

我明白了

//output
+---+---------+-----------+
|id |date     |ts         |
+---+---------+-----------+
|1  |5/02/2016|2016-01-05 |
|2  |aaa      |null       |
+---+---------+-----------+

当我想要时

//expected
+---+---------+-----------+
|id |date     |ts         |
+---+---------+-----------+
|1  |5/02/2016|2016-01-19 |
|2  |aaa      |null       |
+---+---------+-----------+

【问题讨论】:

  • 你的输出和预期的结果不一样吗?
  • d 是月份中的某天,如果您想要星期几,请使用 u

标签: scala apache-spark apache-spark-sql


【解决方案1】:

转换日期是一项棘手的工作。在这种情况下,闰年会阻止我们将一年中的某一天直接映射到一年中的月份和月份中的某一天。

在 Scala 中,我们可以使用 java.util.GregorianCalendar:

def weekToDate(weekStr: String) = {
  val (day, week, year) = {
    val arr = weekStr.split("/").map(_.toInt)
    (arr(0), arr(1), arr(2))
  }
  val cal = new java.util.GregorianCalendar()
  cal.set(java.util.Calendar.YEAR, year)
  cal.set(java.util.Calendar.DAY_OF_YEAR, 7 * week + day)
  new java.text.SimpleDateFormat("yyyy-MM-dd").format(cal.getTime)
}
weekToDate("5/02/2016") // res0: String = 2016-01-19

// Leap year example
weekToDate("4/08/2016") // res1: String = 2016-02-29
weekToDate("4/08/2017") // res2: String = 2017-03-01

把它们放在一起:

import spark.implicits._
import org.apache.spark.sql.functions.udf

def weekToDate(weekStr: String) = {
  val (day, week, year) = {
    val arr = weekStr.split("/").map(_.toInt)
    (arr(0), arr(1), arr(2))
  }
  val cal = new java.util.GregorianCalendar()
  cal.set(java.util.Calendar.YEAR, year)
  cal.set(java.util.Calendar.DAY_OF_YEAR, 7 * week + day)
  new java.text.SimpleDateFormat("yyyy-MM-dd").format(cal.getTime)
}

val df = Seq((1L, "5/02/2016"), (2L, "4/8/2016")).toDF("id", "date").select("date")

val wfn: String => String = weekToDate(_)
val tsUDF=udf(wfn)
df.withColumn("ts", tsUDF('date)).show(2, false)

+---------+----------+
|date     |ts        |
+---------+----------+
|5/02/2016|2016-01-19|
|4/8/2016 |2016-02-29|
+---------+----------+

【讨论】:

    【解决方案2】:

    正如@puhlen 所指出的,星期几应该是u,而不是d(参见SimpleDateFormat

    val df = Seq((1L, "5/02/2016"), (2L, "aaa")).toDF("id", "date")
    val ts = unix_timestamp($"date", "u/ww/yyyy").cast("timestamp")
    df.withColumn("ts", ts).show(2, false)
    
    +---+---------+---------------------+
    |id |date     |ts                   |
    +---+---------+---------------------+
    |1  |5/02/2016|2016-01-08 00:00:00.0|
    |2  |aaa      |null                 |
    +---+---------+---------------------+
    

    还请注意,您不应期望 5/02/2016 在算术上与 20162 x 7 + 5 相同。您实际上应该查看 2016 年日历,第二周的星期五实际上是 1 月 8 日。

    【讨论】:

      猜你喜欢
      • 2020-12-01
      • 2021-12-19
      • 1970-01-01
      • 2011-01-29
      • 2017-06-05
      • 2014-01-11
      • 1970-01-01
      • 2022-01-27
      • 2015-08-02
      相关资源
      最近更新 更多