【问题标题】:Spark SQL weekofyear functionSpark SQL weekofyear 函数
【发布时间】:2018-02-28 07:11:01
【问题描述】:

我正在使用 spark sql 的 weekofyear 函数来计算给定日期的周数。

我正在使用以下代码,

test("udf - week number of the year") {
    val spark = SparkSession.builder().master("local").appName("udf - week number of the year").getOrCreate()
    import spark.implicits._

    val data1 = Seq("20220101", "20220102", "20220103", "20220104", "20220105", "20220106", "20220107", "20220108", "20220109", "20220110", "20220111", "20220112")
    data1.toDF("day").createOrReplaceTempView("tbl_day")
    spark.sql("select day, to_date(day, 'yyyyMMdd') as date, weekofyear(to_date(day, 'yyyyMMdd')) as week_num from tbl_day").show(truncate = false)

    /*
          +--------+----------+--------+
      |day     |date      |week_num|
      +--------+----------+--------+
      |20220101|2022-01-01|52      |
      |20220102|2022-01-02|52      |
      |20220103|2022-01-03|1       |
      |20220104|2022-01-04|1       |
      |20220105|2022-01-05|1       |
      |20220106|2022-01-06|1       |
      |20220107|2022-01-07|1       |
      |20220108|2022-01-08|1       |
      |20220109|2022-01-09|1       |
      |20220110|2022-01-10|2       |
      |20220111|2022-01-11|2       |
      |20220112|2022-01-12|2       |
      +--------+----------+--------+
     */
    spark.stop
  }

惊讶地发现20220101的周数是52,但它是2022的第一天,所以应该是1。

我唆使weekofyear的源代码发现:

它使用以下代码来创建日历实例,以便它给出上面的结果

  @transient private lazy val c = {
    val c = Calendar.getInstance(DateTimeUtils.getTimeZone("UTC"))
    c.setFirstDayOfWeek(Calendar.MONDAY)
    c.setMinimalDaysInFirstWeek(4)
    c
  }

我会问为什么 spark sql 会这样对待一年中的​​前几天。

作为比较,

  1. 我使用以下 oracle sql 来获取给我1的周数

    从对偶中选择 to_number(to_char(to_date('01/01/2022','MM/DD/YYYY'),'WW'))

  2. 在hive中,结果和spark sql一样。

【问题讨论】:

    标签: apache-spark


    【解决方案1】:

    我将在这里发布我的发现:

    Spark SQL 和 Hive 遵循 ISO-8601 标准来计算给定日期一年中的周数。

    需要注意的一点:Spark SQL 内部使用java.util.Calendar API 来完成工作,java 8' java.time API 已经原生支持 ISO-8601 标准,使用 java.time API,我们不必做这个把戏(c.setMinimalDaysInFirstWeek(4))

    【讨论】:

    • 这个方法有没有办法改变年和周的开始日期。
    • 我不这么认为。要改变行为,必须编写一个新的 UDF。
    • @Tom 我正在尝试使用 date_format(dt_col, 'W') 从时间戳中获取月份中的一周,但默认周从 Sun 开始,有什么方法可以更改它以开始而是在星期一?我在火花 2.4
    【解决方案2】:

    在 Spark 3.0 上,您可以使用 EXTRACT 函数。几个例子:

    > SELECT extract(YEAR FROM TIMESTAMP '2019-08-12 01:00:00.123456');
     2019
    > SELECT extract(week FROM timestamp'2019-08-12 01:00:00.123456');
     33
    > SELECT extract(doy FROM DATE'2019-08-12');
     224
    > SELECT extract(SECONDS FROM timestamp'2019-10-01 00:00:01.000001');
     1.000001
    > SELECT extract(days FROM interval 1 year 10 months 5 days);
     5
    > SELECT extract(seconds FROM interval 5 hours 30 seconds 1 milliseconds 1 microseconds);
     30.001001
    

    文档here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-19
      • 2021-12-07
      • 2017-04-30
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 2016-05-15
      • 1970-01-01
      相关资源
      最近更新 更多