Використання поточного часу в UTC як значення за замовчуванням у PostgreSQL


172

У мене є стовпець цього TIMESTAMP WITHOUT TIME ZONEтипу, і я хотів би мати за замовчуванням поточний час у UTC. Отримати поточний час у UTC легко:

postgres=# select now() at time zone 'utc';
          timezone          
----------------------------
 2013-05-17 12:52:51.337466
(1 row)

Як використовується поточна мітка часу для стовпця:

postgres=# create temporary table test(id int, ts timestamp without time zone default current_timestamp);
CREATE TABLE
postgres=# insert into test values (1) returning ts;
             ts             
----------------------------
 2013-05-17 14:54:33.072725
(1 row)

Але для цього використовується місцевий час. При спробі змусити це до UTC призводить до синтаксичної помилки:

postgres=# create temporary table test(id int, ts timestamp without time zone default now() at time zone 'utc');
ERROR:  syntax error at or near "at"
LINE 1: ...int, ts timestamp without time zone default now() at time zo...

Відповіді:


297

Функція навіть не потрібна. Просто поставте дужки навколо виразу за замовчуванням:

create temporary table test(
    id int, 
    ts timestamp without time zone default (now() at time zone 'utc')
);

2
Я бачу функціонал, як now_utc () справді світить при написанні запитів
misaxi

Це навіть працює, коли час повертається на годину - зараз () повертає часову позначку, яка знає зміщення від UTC.
Клей Ленхарт

1
FWIW, працює цей запит в PostgreSQL 11.5: ALTER TABLE testcase_result ADD COLUMN date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE "UTC") NOT NULL;зазнає невдачі з: ERROR: column "UTC" does not exist. Переконайтеся, що 'utc'це все мало.
code_dredd

2
Виправлення: 'utc'рядок також повинен бути одноцитованим, а не подвійним.
code_dredd


26

Оберніть його у функції:

create function now_utc() returns timestamp as $$
  select now() at time zone 'utc';
$$ language sql;

create temporary table test(
  id int,
  ts timestamp without time zone default now_utc()
);

16

А як на рахунок

now()::timestamp

Якщо у вашій іншій часовій марці немає часового поясу, то цей склад буде давати відповідний тип "часова мітка без часового поясу" для поточного часу.

Я хотів би почитати, що інші думають про цей варіант. Я досі не вірю в своє розуміння цього "часового поясу" без ".

EDIT: Додайте тут коментар Майкла Екоки, оскільки він уточнює важливий момент:

Caveat. Питання полягає у створенні часової позначки за замовчуванням у UTC для стовпця часової позначки, який, можливо, не зберігає часовий пояс (можливо, тому, що немає необхідності зберігати часовий пояс, якщо ви знаєте, що всі ваші часові позначки поділяються однаково). Вашим рішенням є створення локальної часової позначки (яка для більшості людей не обов'язково буде встановлена ​​на UTC) та збереження її як наївної часової позначки (такої, яка не визначає її часовий пояс).


Це цікавий трюк, але він може призвести до плутанини, якщо ви не знаєте про цю поведінку. Прийнята відповідь є чітко зрозумілою щодо потрібної дії та результату. Те саме з функцією, але я тримаюсь подалі від функцій у БД ....
Франк V

в моєму варіанті він генерує місцевий час у db
VelikiiNehochuha

Caveat. Питання полягає у створенні часової позначки за замовчуванням у UTC для стовпця часової позначки, який, можливо, не зберігає часовий пояс (можливо, тому, що немає необхідності зберігати часовий пояс, якщо ви знаєте, що всі ваші часові позначки поділяються однаково). Вашим рішенням є створення локальної часової позначки (яка для більшості людей не обов'язково встановлюватиметься UTC) та зберігати її як наївну часову позначку (таку, яка не визначає її часовий пояс).
Майкл Екока

@MichaelEkoka Я додав ваш коментар у відповідь - будь ласка, відправте його та відредагуйте, якщо хочете. Ви це пояснюєте дуже чітко. Дякую!
Рісадінья

Попередження : позначка часу з полем часового поясу НЕ зберігає часовий пояс, всупереч розумному припущенню. Дивіться посилання нижче та шукайте сторінку за UTC. На вході часова марка з часовим поясом перетворює вхідне значення в utc і зберігає значення, що не містять ІНФОРМАЦІЇ ЗВОРОТНОЇ ЗОНИ АБО ВИМОГИ . На виході збережене значення utc перетворюється в локальний час, використовуючи часовий пояс клієнта, якщо він є. Цей тип стосується конверсії значення у момент запиту. Ви повинні перевірити це, зберігаючи в одному часовому поясі та вибравши інший. postgresql.org/docs/11/datatype-datetime.html
Том

7

Це 2 еквівалентні рішення:

(В наступному коді, ви повинні замінити 'UTC'на зони і now()для тимчасової мітки )

  1. timestamp AT TIME ZONE zone - Відповідає стандарту SQL
  2. timezone(zone, timestamp) - напевно, читабельніший

Часовий пояс функції (зона, часова марка) еквівалентний часовій мітці, що відповідає конструкції, у зоні TIME ZONE.


Пояснення:

  • зону можна вказати або як текстовий рядок (наприклад, 'UTC'), або як інтервал (наприклад, INTERVAL '-08:00') - ось список усіх доступних часових поясів
  • мітка часу може бути будь-яким значенням типу часової мітки
  • now()повертає значення типу часової позначки (саме те, що нам потрібно) із доданим часовим поясом бази даних за замовчуванням (наприклад 2018-11-11T12:07:22.3+05:00).
  • timezone('UTC', now())перетворює наш поточний час (типу часової позначки з часовим поясом ) в еквівалент без часового періоду в UTC.
    Наприклад, SELECT timestamp with time zone '2020-03-16 15:00:00-05' AT TIME ZONE 'UTC'повернеться 2020-03-16T20:00:00Z.

Документи: часовий пояс ()


1
Дякуємо за узагальнення цих речей. Я використовував малу версію, at timezone 'utc'і це не працювало з моєю установкою PostgreSQL. Використовуючи великі літери вирішено питання
Geradlus_RU

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.