Почему from_utc_timstamp не выдает ошибку при передаче неверно сформированной строки часового пояса в Spark? - PullRequest
1 голос
/ 17 июня 2020

При вызове функции from_utc_timestamp в Spark 2.4.3 ошибка не выдается, если я передаю неверную строку часового пояса. Вместо этого он просто по умолчанию использует UT C, что противоречит моим ожиданиям и, вероятно, приведет к незаметным ошибкам для go. Это намеренно или ошибка в Spark?

См. Пример ниже:

scala> val df =  Seq(("2020-01-01 00:00:00")).toDF("date")
df: org.apache.spark.sql.DataFrame = [date: string]

scala> df.show()

// Not a real timezone obviously. Just gets treated like UTC.
scala> df.withColumn("est", from_utc_timestamp(col("date"), "not_a_real_timezone")).show()
+-------------------+-------------------+
|               date|                est|
+-------------------+-------------------+
|2020-01-01 00:00:00|2020-01-01 00:00:00|
+-------------------+-------------------+

// Typo in EST5PDT, so still not a real timezone. Also defaults to UTC, which makes it
// very easy to miss this mistake.
scala> df.withColumn("est", from_utc_timestamp(col("date"), "EST5PDT")).show()
+-------------------+-------------------+
|               date|                est|
+-------------------+-------------------+
|2020-01-01 00:00:00|2020-01-01 00:00:00|
+-------------------+-------------------+

// EST8EDT is a real timezone, so this works as expected.
scala> df.withColumn("est", from_utc_timestamp(col("date"), "EST5EDT")).show()
+-------------------+-------------------+
|               date|                est|
+-------------------+-------------------+
|2020-01-01 00:00:00|2019-12-31 19:00:00|
+-------------------+-------------------+

Ответы [ 2 ]

1 голос
/ 17 июня 2020

from_utc_timestamp вызывает DateTimeUtils.fromUTCTime .

def fromUTCTime(time: SQLTimestamp, timeZone: String): SQLTimestamp = {
  convertTz(time, TimeZoneGMT, getTimeZone(timeZone))
}

Чтобы преобразовать строку часового пояса в объект TimeZone , функция вызывает getTimeZone , и здесь вызывается JDK's TimeZone.getTimeZone для преобразовать строку часового пояса в фактический объект часового пояса. В Javado c этого метода указано, что метод возвращает

указанный часовой пояс или зону GMT, если данный идентификатор не может быть понят

В вашем случае of EST5PDT часовой пояс для этой строки не найден, поэтому возвращаемое значение - GMT. В результате SQLTimestamp преобразуется из GMT в GMT, что означает, что он остается неизменным.

1 голос
/ 17 июня 2020

from_utc_timestamp использует DateTimeUtils из org.apache.spark.sql.catalyst.util. Чтобы получить часовой пояс, они используют метод getTimeZone. Этот метод обычно не вызывает проблем.

  • Это может быть вещь JVM, где JVM пытается избежать зависимости от языкового стандарта, кодировки и часового пояса системы по умолчанию
  • Это может быть проблема Spark, которая должна быть зарегистрирована в Jira

Но, глядя на код других людей, у них действительно есть настройка проверки сначала:

import java.util.TimeZone

...

if (!TimeZone.getAvailableIDs().contains(tz)) {
  throw new IllegalStateException(s"The setting '$tz' is not recognized as known time zone")
}

EDIT1: Только что выяснилось, что это «особенность». Он находится в руководстве по миграции для 3.0.0

. В Spark версии 2.4 и более ранние идентификаторы недопустимых часовых поясов игнорируются и заменяются часовым поясом GMT, например, в функции from_utc_timestamp. Начиная с Spark 3.0, такие идентификаторы часовых поясов отклоняются, и Spark выдает исключение java .time.DateTimeException.

https://spark.apache.org/docs/3.0.0-preview/sql-migration-guide.html

...