По принцип това, което искате, е:
$ select starts_at AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific' from schedules where id = 40
Получих решението от тази статия е по-долу, което е направо ЗЛАТО!!! Обяснява много ясно този нетривиален проблем, прочетете го, ако искате да разберете по-добре управлението на pstgrsql TZ.
Изразяване на PostgreSQL времеви марки без зони в местно време
Ето какво става. Първо трябва да знаете, че „часовата зона PST е 8 часа след часовата зона по UTC, така че например 1 януари 2014 г., 16:30 PST (сряда, 01 януари 2014 16:00:30 -0800) е еквивалентна на 2 януари 2014 г., 00:30 AM UTC (чт, 2 януари 2014 г. 00:00:30 +0000). По всяко време след 16:00 в PST преминава към следващия ден, интерпретиран като UTC.
Също така, както Erwin Brandstetter спомена по-горе, postresql има два типа тип данни за времеви печати, един с часова зона и един без. Ако вашите времеви печати включват часова зона, тогава просто:
$ select starts_at AT TIME ZONE 'US/Pacific' from schedules where id = 40
ще работи. Ако обаче клеймото ви за време е без часова зона, изпълнението на горната команда няма да работи и ПЪРВО трябва да преобразувате своето времево клеймо без часова зона в часова зона, а именно UTC часова зона, и САМО СЛЕД това да го преобразувате в желания от вас 'PST' или 'US/ Pacific“ (които са същите до някои проблеми с лятното часово време. Мисля, че трябва да се справите и с едното).
Позволете ми да демонстрирам с пример, когато създавам времева марка без часови зони. Да приемем за удобство, че нашата местна часова зона наистина е „PST“ (ако не беше, тогава става малко по-сложно, което е ненужно за целите на това обяснение).
Кажете, че имам:
$ select timestamp '2014-01-2 00:30:00' AS a, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AS b, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AT TIME ZONE 'PST' AS c, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d
Това ще даде:
"a"=>"2014-01-02 00:30:00" (This is the timezoneless timestamp)
"b"=>"2014-01-02 00:30:00+00" (This is the UTC TZ timestamp, note that up to a timezone, it is equivalent to the timezoneless one)
"c"=>"2014-01-01 16:30:00" (This is the correct 'PST' TZ conversion of the UTC timezone, if you read the documentation postgresql will not print the actual TZ for this conversion)
"d"=>"2014-01-02 08:30:00+00"
Последното клеймо за време е причината за цялото объркване по отношение на преобразуването на времевата марка без часови зони от UTC в 'PST' в postgresql. Когато пишем:
timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d
Взимаме клеймо за време без часови зони и се опитваме да го преобразуваме в 'PST TZ (непряко предполагаме, че postgresql ще разбере, че искаме да преобразува времевата марка от UTC TZ, но postresql има свои собствени планове!). На практика това, което postgresql прави, е, че взема клеймото за време без часови зони ('2014-01-2 00:30:00) и го третира така, сякаш ВЕЧЕ БИЛО 'PST' TZ timestamp (т.е.:2014-01-2 00:30 :00 -0800) и го преобразува в UTC часова зона!!! Така че всъщност го избутва с 8 часа напред вместо назад! Така получаваме (2014-01-02 08:30:00+00).
Както и да е, това последно (неинтуитивно) поведение е причината за цялото объркване. Прочетете статията, ако искате по-задълбочено обяснение, всъщност получих резултати, които са малко по-различни от тези в последната част, но общата идея е същата.