Спарк формат даты выпуска - PullRequest
1 голос
/ 11 марта 2020

Я наблюдал странное поведение при форматировании даты искры. На самом деле мне нужно конвертировать дату yy в yyyy. После преобразования даты это должно быть 20yy в дату

Я пробовал, как показано ниже, после 2040 года это не удалось.

import org.apache.spark.sql.functions._
val df=   Seq(("06/03/35"),("07/24/40"), ("11/15/43"), ("12/15/12"), ("11/15/20"), ("12/12/22")).toDF("Date")

df.withColumn("newdate", from_unixtime(unix_timestamp($"Date", "mm/dd/yy"), "mm/dd/yyyy")).show

+--------+----------+
|    Date|   newdate|
+--------+----------+
| 06/3/35|06/03/2035|
|07/24/40|07/24/2040|
|11/15/43|11/15/1943|  // Here year appended with 19
|12/15/12|12/15/2012|
|11/15/20|11/15/2020|
|12/12/22|12/12/2022|
+--------+----------+

Почему такое поведение, есть ли какая-либо функция полезности даты, которую я могу использовать напрямую, не добавляя 20 к строковой дате

1 Ответ

2 голосов
/ 11 марта 2020

Разбор строк 2-di git year подлежит некоторой относительной интерпретации, которая задокументирована в SimpleDateFormat документах :

Для анализа с сокращенным шаблоном года ("y" или "yy"), SimpleDateFormat должен интерпретировать сокращенный год относительно некоторого столетия. Это достигается путем корректировки дат в пределах 80 лет до и 20 лет после времени создания экземпляра SimpleDateFormat. Например, используя шаблон «MM / dd / yy» и экземпляр SimpleDateFormat, созданный 1 января 1997 г., строка «01/11/12» будет интерпретироваться как 11 января 2012 г., а строка «05/04 / 64 "будет интерпретироваться как 4 мая 1964 года.

Таким образом, 2043 на расстоянии более 20 лет анализатор использует 1943, как описано.

Вот один подход, который использует UDF, который явно вызывает set2DigitYearStart для SimpleDateFormat объекта перед синтаксическим анализом даты (в качестве примера я выбрал 1980):

def parseDate(date: String, pattern: String): Date = {

    val format = new SimpleDateFormat(pattern);
    val cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, 1980)
    val beginning = cal.getTime();

    format.set2DigitYearStart(beginning)

    return new Date(format.parse(date).getTime);
}

И затем:

val custom_to_date = udf(parseDate _);
df.withColumn("newdate", custom_to_date($"Date", lit("mm/dd/yy"))).show(false)
+--------+----------+
|Date    |newdate   |
+--------+----------+
|06/03/35|2035-01-03|
|07/24/40|2040-01-24|
|11/15/43|2043-01-15|
|12/15/12|2012-01-15|
|11/15/20|2020-01-15|
|12/12/22|2022-01-12|
+--------+----------+

Зная ваши данные, вы будете знать, какое значение выбрать для параметра set2DigitYearStart()

...