Spark 2.4.0 - невозможно проанализировать строку ISO8601 в TimestampType, сохраняя мс - PullRequest
0 голосов
/ 09 февраля 2019

При попытке преобразовать строки ISO8601 с информацией о часовом поясе в TimestampType с использованием приведения (TimestampType) принимаются только строки с форматом часового пояса +01: 00.Если часовой пояс определен в соответствии со стандартом ISO8601 +0100 (без двоеточия), анализ завершается неудачно и возвращает ноль.Мне нужно преобразовать строку в TimestampType при сохранении части ms.

2019-02-05T14:06:31.556+0100    Returns null
2019-02-05T14:06:31.556+01:00   Returns a correctly parsed TimestampType

Я попытался использовать функции to_timestamp () и unix_timestamp (). Cast (TimestampType).К сожалению, они усекают секцию ms метки времени, которую мне нужно сохранить.Кроме того, вам необходимо применить их к новому столбцу, и вы не сможете выполнить замену атрибута на месте в сложном типе (что возможно, если я сделаю свойство ApiReceived TimestampType в схеме для функции from_json).

df
.select($"body".cast(StringType))
.select(from_json($"body", schema).as("Payload"))
.select($"Payload.Metadata.ApiReceived".as("Time"))
.withColumn("NewTime", to_timestamp($"Time", "yyyy-MM-dd'T'HH:mm:ss.SSSZ"))
.withColumn("NewTime2", unix_timestamp($"Time", "yyyy-MM-dd'T'HH:mm:ss.SSSZ").cast(TimestampType))
.withColumn("NewTime3", $"Time".cast(TimestampType))

Тип вывода указанного выше DataFrame

df:org.apache.spark.sql.DataFrame
  Time:string
  NewTime:timestamp
  NewTime2:timestamp
  NewTime3:timestamp

И выходные значения

Time        2019-02-05T14:06:31.556+0100
NewTime     2019-02-05 13:06:31
NewTime2    2019-02-05 13:06:31
NewTime3    null

Есть ли способ заставить Spark обрабатывать преобразование, не прибегая к UDF: s?

Обновление

После более тщательного исследования я обнаружил, что анализ даты и времени в Sparks несколько противоречив.:)

val df = Seq(
  //Extended format
  ("2019-02-05T14:06:31.556+01:00"),
  ("2019-02-05T14:06:31.556+01"),
  ("2019-02-05T14:06:31.556"),
  //Basic Format
  ("20190205T140631556+0100"),
  ("20190205T140631556+01"),
  ("20190205T140631556"),
  //Mixed extended with basic
  ("2019-02-05T14:06:31.556+0100"),
  ("20190205T140631556+01:00")
).toDF

val formatStrings = Seq(
  ("yyyy-MM-dd'T'HH:mm:ss.SSSZ"),
  ("yyyy-MM-dd'T'HH:mm:ss.SSSX"),
  ("yyyyMMdd'T'HHmmssSSSZ"),
  ("yyyyMMdd'T'HHmmssSSSX")
)

val format = formatStrings(0)

val df2 = df
.select($"value".as("Time"))
.withColumn("NewTime3", $"Time".cast(TimestampType))
.withColumn("NewTime", to_timestamp($"Time", format))
.withColumn("NewTime2", unix_timestamp($"Time", format).cast(TimestampType))
.withColumn("NewTime4", date_format($"Time", format))

display(df2)

Если вы запустите эти кадры данных и сравните вывод, это несколько уныло.Наиболее приемлемым formatString является второй SSSX

. Единственный разумный способ справиться с этим - UDF, обеспечивающий соответствие всех строк ISO8601 стандарту, который понимает функция, которую вы планируете использовать.

Все еще, не нашли способа сохранить миллисекундную часть в обоих форматах.

2019-02-05T14:06:31.556+01:00 and
2019-02-05T14:06:31.556+0100

Обновление 2

https://issues.apache.org/jira/browse/SPARK-17545?jql=project%20%3D%20SPARK%20AND%20text%20~%20iso8601

Видимо этоНЕ соответствует стандарту ISO8601 для смешивания основных и расширенных форм.Строка «2019-02-05T14: 06: 31.556 + 0100» не в стандартном формате.Тем не менее, это кажется правильным в соответствии с RFC822.

Если я правильно понимаю билет JIRA, стандартный синтаксический анализ (т. Е. Приведение () к строковому столбцу) обрабатывает только правильно отформатированные строки ISO8601, а не RFC822 или другие крайние случаи (т.е. смешивание расширенных и основных форматов).Если у вас есть крайний случай, вы должны предоставить строку формата и использовать другой метод синтаксического анализа.

У меня нет доступа к стандарту ISO8601: 2004, поэтому я не могу проверить, но есть ли комментарий в JIRAправильно интернет нуждается в обновлении.Многие веб-страницы сопоставляют RFC822 и ISO8601 и перечисляют «2019-02-05T14: 06: 31.556 + 0100» в качестве допустимой строки ISO8601.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...