Как вы можете получить дату и время UTC из Postgresql с помощью Npgsql

#c# #postgresql #datetime #npgsql

#c# #postgresql #дата и время #npgsql

Вопрос:

Я использую тип столбца «временная метка с часовым поясом» и устанавливаю свои даты и время следующим образом:

 INSERT INTO mytable(col1)
VALUES(timestamp with time zone '2020-07-16 17:45:00.000000 00');
  

Всякий раз, когда я пытаюсь получить свои даты и время, они преобразуются в «локальный» вид.

Это не то, что я хочу, оно установлено как дата и время UTC, и я хочу вернуть его как UTC, я не хочу, чтобы он преобразовывался в local, входя в базу данных, и не возвращался обратно… это делает невозможным переход к UTC, не вызывая двусмысленности.

Я попытался установить переменную среды «PGTZ»; Я также выполнил следующий sql при открытии соединения:

 Connection.ExecuteAsync( "SET TIMEZONE TO 'UTC'" );
  

Кажется, что ничего из того, что я пробовал, не работает, и, похоже, это сделано специально в соответствии с различными сообщениями, такими как:
https://github.com/npgsql/npgsql/issues/347

Мне это кажется совершенно неправильным, но я надеюсь, что кто-нибудь может указать мне на обходной путь для этого.

Я использую .net5 / asp.net и Dapper (не EFCore) и Npgsql версии 4.1.5.

Ответ №1:

Postgresql timestamptz фактически не сохраняет часовой пояс, он просто сохраняет значения как в UTC. Это означает '2020-07-16 17:45:00.000000 00' , что при вводе не будет преобразовано в UTC. Без указанного часового пояса он будет повернут от TimeZone настройки до UTC . При извлечении, однако, он будет использовать TimeZone настройку для возврата к этому часовому поясу. Я подозреваю, что ваша настройка не выполняется в том же сеансе, в котором выполняется извлечение метки времени. Я бы попробовал что-то вроде SELECT timestamp_fld AT TIME ZONE 'UTC'

Ответ №2:

Это действительно разработано и соответствует PostgreSQL при запросе значений timestamptz в обычных текстовых запросах. Если вы используете запуск psql или pgadmin и выбираете столбец timestamptz, вы увидите локальную временную метку, основанную на вашем TimeZone параметре сеанса.

Как упоминалось @adrian-klaver, timestamptz не предназначен для хранения часового пояса в базе данных — речь идет о применении преобразований часовых поясов при чтении и записи значений временных меток в базу данных на основе TimeZone параметра. Если вы не хотите никаких таких преобразований, подумайте о переходе на временную метку (без часового пояса) и о том, чтобы все временные метки были как UTC по соглашению.

Комментарии:

1. Спасибо @Shay, я читал, что если вы хотите сохранить значения UTC, вы должны использовать timestamp with time zone , но я не учел это, поскольку я контролирую вещи с помощью кода, тогда я могу убедиться, что его utc, прежде чем устанавливать значение. Я должен сказать, что из всех баз данных postgres кажется чрезмерно сложным в этом отношении и склонным к ошибкам, поэтому спасибо за разъяснение

2. Я согласен, что PG немного сбивает с толку (хотя FWIW, похоже, просто очень точно соответствует стандарту SQL). Возможно, вы захотите прочитать этот мой комментарий к timestamp с часовым поясом и без него; Я бы действительно рекомендовал использовать «UTC по соглашению»