Преобразование эпохи строки в метку времени строки в Scala

У меня есть столбец ORDER_DATE с отметкой времени эпохи в строке. Как я могу преобразовать этот столбец со строкой типа str = "1536309236032", которая является временем в эпохе, в строку с форматом: 2018-09-07T14:03:56.032Z в Scala?

В настоящее время я использую:

from_unixtime(input.col(ORDER_DATE), "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")

но это неправильно преобразуется в 50668-08-21 01:10:00.000. Здесь он увеличивает год и увеличивает 000 на миллисекунды.

Я не хочу делить на 1000, так как мы хотели бы получить результат в миллисекундах.


person Abhinav Kaushal Keshari    schedule 18.09.2018    source источник
comment
Возможный дубликат https://stackoverflow.com/questions/33475229/convert-epoch-to-datetime-in-scala-spark   -  person darkmatter    schedule 18.09.2018
comment
Я сделал свой вопрос более ясным, и это требование отличается от той ссылки, которую вы упомянули. Можете ли вы помочь мне в этом?   -  person Abhinav Kaushal Keshari    schedule 18.09.2018
comment
Судя по длине вашей входной строки времени, это, вероятно, миллисекунды. Попробуйте: from_unixtime($"epochstr".cast("long")/1000, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")   -  person Leo C    schedule 18.09.2018
comment
Но я также хочу получить результат в миллисекундах. Есть ли способ получить это?   -  person Abhinav Kaushal Keshari    schedule 18.09.2018


Ответы (2)


В документации определение from_unixtime выглядит следующим образом:

Преобразует количество секунд из эпохи unix (1970-01-01 00:00:00 UTC) в строку, представляющую отметку времени этого момента в текущем системном часовом поясе в заданном формате.

Он использует секунды и, следовательно, несовместим с миллисекундами, поэтому результат неверен. Чтобы преобразовать отметку времени эпохи и сохранить информацию о миллисекундах, вы можете использовать concat:

val spark = SparkSession.builder.getOrCreate()
import spark.implicits._

df.withColumn("time", concat(
    from_unixtime($"ORDER_DATE"/1000, "yyyy-MM-dd'T'HH:mm:ss."), 
    $"ORDER_DATE".substr(length($"ORDER_DATE")-2, length($"ORDER_DATE")), 
    lit("Z")))

Это будет работать, поскольку последние 3 цифры в метке времени эпохи совпадают с цифрами в желаемом результате.

person Shaido    schedule 19.09.2018
comment
Можете ли вы также указать способ, чтобы я выполнял это действие только тогда, когда поле в столбце не равно 0, иначе оно оставляет поле пустым? - person Abhinav Kaushal Keshari; 19.09.2018
comment
@AbhinavKaushalKeshari: вы можете использовать when и otherwise, см., например, здесь: stackoverflow.com/questions/37064315/ - person Shaido; 19.09.2018

Я получил идею от @Shaido, и я сделал что-то подобное. Наконец, это решило проблему для меня:

input.withColumn("time",
concat(from_unixtime(input.col("ORDER_DATE")/1000, "yyyy-MM-dd'T'HH:mm:ss"), 
typedLit("."), substring(input.col("ORDER_DATE"), 11, 3), typedLit("Z")))
person Abhinav Kaushal Keshari    schedule 19.09.2018