2016-09-13 1 views
2

Возможно ли получить правильное обозначение TZ после конвертирующая колонка типа timestamptz?Получить TZ аббревиатуру для данной метки времени и названия TZ

То, что я после этого, соф примеру, для отображения "2016-06-16 16: 00: 00-04" в "США/Тихого океана" часовой пояс с целевой TZ сокращениях. я могу получить это легко:

06/16/2016 01:00 pm 

Но я не могу получить следующее:

06/16/2016 01:00 pm PDT 

После преобразования timestamptz становится timestamp without timezone и to_char спецификатор 'TZ' становится бессмысленным ...

Здесь пример того, что я пробовал:

SELECT 
    scheduled_dt                   AS scheduled_dt 
    , to_char(scheduled_dt, 'TZ')               AS scheduled_dt_orig_tz 
    -- correct value, but missing TZ 
    , timezone('US/Pacific', scheduled_dt)             AS schedules_dt_converted_tz 
    , to_char(timezone('US/Pacific', scheduled_dt), 'MM/DD/YYYY HH:MI pm')     AS scheduled_dt_converted_tz_localized 
    -- after conversion TZ is lost 
    , to_char(timezone('US/Pacific', scheduled_dt), 'MM/DD/YYYY HH:MI pm TZ')    AS scheduled_dt_converted_tz_localized_missing_tz 
    -- with cast, wrong TZ is displayed 
    , to_char(timezone('US/Pacific', scheduled_dt)::timestamptz, 'MM/DD/YYYY HH:MI pm TZ') AS scheduled_dt_converted_tz_localized_wrong_tz 
FROM orders 
LIMIT 5 

и пример вывода:

"scheduled_dt","scheduled_dt_orig_tz","schedules_dt_converted_tz","scheduled_dt_converted_tz_localized","scheduled_dt_converted_tz_localized_missing_tz","scheduled_dt_converted_tz_localized_wrong_tz" 
"2016-06-16 16:00:00-04","EDT","2016-06-16 13:00:00","06/16/2016 01:00 pm","06/16/2016 01:00 pm ","06/16/2016 01:00 pm EDT" 
"2014-07-15 08:00:00-04","EDT","2014-07-15 05:00:00","07/15/2014 05:00 am","07/15/2014 05:00 am ","07/15/2014 05:00 am EDT" 
"2012-11-27 10:15:00-05","EST","2012-11-27 07:15:00","11/27/2012 07:15 am","11/27/2012 07:15 am ","11/27/2012 07:15 am EST" 
"2011-03-02 08:30:00-05","EST","2011-03-02 05:30:00","03/02/2011 05:30 am","03/02/2011 05:30 am ","03/02/2011 05:30 am EST" 
"2016-02-12 14:23:09-05","EST","2016-02-12 11:23:09","02/12/2016 11:23 am","02/12/2016 11:23 am ","02/12/2016 11:23 am EST" 

ответ

4

Нет, потому что timestamptz (ака timestamp with time zone) isn't really a timestamp with a time zone, с точки зрения того, что хранится ... вы обеспечивают метку времени и часового пояса, и внутренне это просто хранится в виде UTC стоимость.

Похоже, что в основном вы должны хранить целевой часовой пояс в отдельном поле вместе с меткой времени.

+1

Я хранение целевой TZ с полным именем, хранящийся в присоединении к таблице (warehouse_locations), так что я могу скрытой каждую строку. То, что мне не хватает, это «текстовая библиотека.», Которая может форматировать временную метку с коротким названием TZ с учетом DST .... Поэтому я могу получить «PDT» или «PST» на основе конкретной даты и часового пояса. ... Я уже делаю это в коде, но задавался вопросом, можно ли сделать это непосредственно в PG – zam6ak

+0

@ zam6ak: я бы лично избегал делать это в базе данных, даже если бы мог. Я передал бы его независимо от того, что код говорит с базой данных *, как временная метка и отдельный часовой пояс * и там строковое форматирование. Вы, как правило, находитесь в гораздо лучшем положении для форматирования с богатой информацией о культуре и т. Д. –

+0

Я абсолютно согласен. Однако объем данных в моем случае значителен (500K и более строк). Поэтому я пытался избежать шага «перевода» (по существу, цикла в коде, где каждый столбец временной метки преобразуется) ради получения скорости ... – zam6ak

3

Вы не можете извлечь часовой пояс (имя или аббревиатуру) из timestamp или timestamptz, потому что его просто нет. Подробное описание:

Поскольку вы храните целевой TZ с полным именем, вы может извлечь соответствующий часовой пояс аббревиатуру из вида системы pg_timezone_names (который основан на внутренней функции pg_timezone_names()).

SELECT abbrev 
FROM pg_timezone_names 
WHERE name = 'US/Pacific'; 

abbrev 
-------- 
PDT 

Однако, per documentation:

Отображаемая информация вычисляется на основе текущего значения CURRENT_TIMESTAMP.

Это означает, что вы получите PDT летом и PST в зимний период, на основе текущего времени, не на основе временной метки вы хотите отобразить.

Не решение, которое вам нужно, извините.

function definition of pg_timezone_names in the PostgreSQL source code может дать вам идеи о том, как реализовать свою собственную функцию C.

Связанные:

+0

При ближайшем рассмотрении это не то решение, которое вам нужно, извините. Вам нужна функция, которая берет имя часового пояса и временную метку, чтобы получить соответствующее сокращение времени часового пояса ... –

+0

Исправить. Я должен сделать это в коде ... И ваш ответ, и ответ Джона верны и полны дополнительной действительно полезной информации. Поскольку Джон ответил первым, надеюсь, вы не возражаете, если я отвечу на его ответ. – zam6ak

+0

@ zam6ak: Конечно, все зависит от вас, на что отвечать. –