Errors
Trino

Trino: How to convert timestamp to date in Presto?

Бывает так: смотришь на timestamp в Trino, а там непонятные цифры. Типа `1506929478589`. Хочется нормальную дату, чтобы глаза не ломать. Или вообще разделить на

Бывает так: смотришь на timestamp в Trino, а там непонятные цифры. Типа 1506929478589. Хочется нормальную дату, чтобы глаза не ломать. Или вообще разделить на дату и время для отчётов.

Тыкаешь в запрос, гуглишь — а ответ проще, чем кажется.

Базовое преобразование

Всё что нужно — это cast. Берёшь колонку с timestamp и превращаешь её в date. Всё.

SELECT
    my_timestamp,
    CAST(my_timestamp AS DATE) as my_date
FROM my_table

Второй вариант — использовать встроенную функцию date(). Работает так же.

SELECT
    my_timestamp,
    DATE(my_timestamp) as my_date
FROM my_table

Оба способа дают одинаковый результат. Разницы нет. Выбирай тот, что больше нравится.

А если timestamp в миллисекундах?

Твои данные 1506929478589 — это как раз UNIX-время в миллисекундах. Trino не поймёт это сразу как timestamp.

Сначала преврати это число в нормальный timestamp. Используй from_unixtime. Но она работает с секундами, поэтому миллисекунды нужно поделить на 1000.

SELECT
    from_unixtime(1506929478589 / 1000) as proper_timestamp

Получишь 2017-10-02 11:31:18.589. А потом уже к этому результату применяй cast или date().

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

SELECT
    CAST(from_unixtime(1506929478589 / 1000) AS DATE) as final_date

Или так, что то же самое:

SELECT
    DATE(from_unixtime(1506929478589 / 1000)) as final_date

На выходе получишь чистую дату: 2017-10-02.

Про таймзоны

В вопросе упомянуто, что время в UTC. Функция from_unixtime возвращает timestamp в часовом поясе сессии.

Если нужно явно указать UTC, используй at_timezone.

SELECT
    DATE(from_unixtime(1506929478589 / 1000) AT TIME ZONE 'UTC')

Но если твоя сессия и так работает с UTC, то всё и так будет правильно. Это просто для строгости.

Что под капотом

Функция date() — это по сути синтаксический сахар для cast(x as date). В плане выполнения разницы нет.

Выбор между ними — дело стиля. В сложных запросах cast может быть нагляднее, особенно когда преобразований много. date() — чуть короче.

Главное помни: если исходные данные — это bigint с миллисекундами, без from_unixtime никуда. Прямое преобразование cast(1506929478589 as date) не сработает.

Итог

Алгоритм простой. У тебя есть число? Сначала делай from_unixtime(millis / 1000). Получил нормальный timestamp? Теперь оборачивай в date() или делай cast(... as date).

Всё это есть в документации по datetime-функциям. Если что-то работает — не трогай. Если не работает — проверяй тип исходных данных и делишь ли ты на 1000.