如何获取开始日期和结束日期之间的月数

时间:2018-01-22 06:57:32

标签: scala apache-spark

我想获得两个日期之间的月数,我正在从csv文件中读取开始日期和结束日期。

id          startDate  endDate
100         5/1/2016   5/1/2017
200         5/2/2016   5/1/2017
300         5/2/2016   5/1/2017

我的输出应该如下:

id          startDate  endDate     res
100         5/1/2016   5/1/2017    12
200         5/2/2016   5/1/2017    11
300         5/3/2016   5/1/2017    10

请告诉我代码中的错误,

val data = spark.read.option("header", "true").csv("sample.csv");
val result = data.withColumn("res", withColumn("Months", ChronoUnit.MONTHS.between(startDate ,endDate)).show()

4 个答案:

答案 0 :(得分:1)

以下是如何使用Spark实现的:

import org.apache.spark.sql.functions

import spark.implicits._

val result = data.withColumn(
    "res",
    functions.months_between(
      functions.to_date($"endDate", "M/d/yyyy"),
      functions.to_date($"startDate", "M/d/yyyy")
    )
)

withColumn的第二个参数是Spark的Column类型。您无法将任意Java / Scala表达式传递给它。

请注意,to_date仅在Spark 2.2.0中添加。

如果您使用的是较旧版本的Spark,则可以定义UDF,这是一种自定义函数,可将字符串转换为特定格式的日期:

import java.time.format.DateTimeFormatter
import java.time.LocalDate
import java.sql.Date

val strToDate = functions.udf { 
    val fmt = DateTimeFormatter.ofPattern("M/d/yyyy")
    date: String => 
      Date.valueOf(LocalDate.parse(date, fmt)) 
}

现在,配备strToDate,我们可以将字符串columsn转换为日期并应用months_之间:

val result = data.withColumn(
    "res",
    functions.months_between(
      strToDate($"endDate"),
      strToDate($"startDate")
    )
)

答案 1 :(得分:1)

  1. 将列转换为日期数据类型。
  2. 您可以使用SQL datediff函数。
  3. 语法:

    val dt = sqlcontext.sql("SELECT DATEDIFF(month, start_date, end_date) AS DateDiff from relation")
    

    您可以参考以下日期链接:Datediff

    以下是一个类似的问题:stackoverflow

答案 2 :(得分:0)

您可以使用提供的名为months_between

的spark函数
import org.apache.spark.sql.functions._

val result = data.withColumn("monthsBetween", months_between($"startDate", $"endDate"))

答案 3 :(得分:0)

您的代码的问题只是类型转换。因此,在阅读时,您需要推断您的架构。如果要打印架构,可以注意到所有列都是字符串类型。因此,months_between函数返回null值。

data.printSchema()

root
|-- id: string (nullable = true)
|-- startDate: string (nullable = true)
|-- endDate: string (nullable = true)

您可以使用以下代码:

val data = sqlContext.read
    .option("header", "true")
    .option("dateFormat", "d/M/yyyy")
    .option("inferSchema", "true")
    .csv("sample.csv")

data.printSchema()

root
|-- id: integer (nullable = true)
|-- startDate: timestamp (nullable = true)
|-- endDate: timestamp (nullable = true)
import org.apache.spark.sql.functions
val result = data.withColumn("res", functions.months_between($"endDate", $"startDate"))
    result.show()
+---+--------------------+--------------------+----+
| id|           startDate|             endDate| res|
+---+--------------------+--------------------+----+
|100|2016-01-05 00:00:...|2017-01-05 00:00:...|12.0|
|200|2016-02-05 00:00:...|2017-01-05 00:00:...|11.0|
|300|2016-03-05 00:00:...|2017-01-05 00:00:...|10.0|
+---+--------------------+--------------------+----+