Во-первых, осознайте, что если ваши временные метки уже находятся в местном времени данного смещения, вам нужно вычесть это смещение, чтобы преобразовать обратно в UTC. В первом приведенном вами примере 2011-06-22 11:00:00 -0700
эквивалентно 2011-06-22 18:00:00 UTC
.
Однако вместо того, чтобы пытаться самостоятельно складывать или вычитать эти значения, вы должны позволить AT TIME ZONE
сделает всю работу за вас. Он создаст timestamptz
, который находится в предоставленном вами смещении, затем вы можете снова использовать его для преобразования в UTC.
(Обратите внимание, что вместо этого вы можете использовать функцию CONVERT_TIMEZONE
, но это понимает только Redshift, где AT TIME ZONE
также работает с обычным PostgreSQL.)
Однако у вас есть смещения часовых поясов, которые у вас не в формате, понятном для этих функций. См. примечания по использованию часовых поясов. Итак, прежде чем мы попытаемся преобразовать, давайте переведем ваши строки смещения в понятный формат.
Мы хотим, чтобы -0700
стал +07:00
. Двоеточие является обязательным, а знак должен быть перевернут, поскольку он будет интерпретироваться в формате часового пояса в стиле POSIX. В этом формате положительные значения лежат запад от GMT вместо обычных соглашений, определенных в ISO 8601.
concat(translate(substring(original_timezone_offset, 1, 3), '-+', '+-'),':',substring(original_timezone_offset, 4, 2))
Затем мы будем использовать это с AT TIME ZONE
для преобразования:
(original_timezone AT TIME ZONE <the above mess>) AT TIME ZONE 'UTC' AS utc_timestamp
Собираем все вместе ...
WITH t as (
SELECT '2011-06-22 11:00:00.000000'::timestamp as original_timestamp, '-0700' as original_timezone_offset
UNION ALL
SELECT '2014-11-29 17:00:00.000000'::timestamp,'-0800'
UNION ALL
SELECT '2014-12-02 22:00:00.000000'::timestamp,'+0900'
)
SELECT
original_timestamp,
original_timezone_offset,
concat(translate(substring(original_timezone_offset, 1, 3), '-+', '+-'),':',substring(original_timezone_offset, 4, 2)) as modified_timezone_offset,
(original_timestamp AT TIME ZONE concat(translate(substring(original_timezone_offset, 1, 3), '-+', '+-'),':',substring(original_timezone_offset, 4, 2))) AT TIME ZONE 'UTC' AS utc_timestamptz
FROM t
Выход:
2011-06-22 11:00:00 -0700 +07:00 2011-06-22 18:00:00
2014-11-29 17:00:00 -0800 +08:00 2014-11-30 01:00:00
2014-12-02 22:00:00 +0900 -09:00 2014-12-02 13:00:00
SQL Fiddle здесь.
person
Matt Johnson-Pint
schedule
15.03.2019