.Net PostgreSQL NpgsqlBatch。应用“设置时区”来选择查询

问题描述 投票:0回答:1

如何将

SET TIME ZONE
应用到NpgsqlCommand?

尝试 1. CommandText 中的

SET TIME ZONE
,用
;

与选择分开
using var cmd = connection.CreateCommand();
cmd.CommandText = "SET TIME ZONE '+02:00'; select \"t0\".\"start_time\" from \"task\".\"tasks\" \"t0\" where \"t0\".\"number\" = 217";
await connection.OpenAsync();
using var reader = await cmd.ExecuteReaderAsync();

尝试 2.使用

NpgsqlBatch

await connection.OpenAsync();

using var batch = new NpgsqlBatch(connection);
batch.BatchCommands.Add(new NpgsqlBatchCommand("SET TIME ZONE '+02:00'"));
batch.BatchCommands.Add(new NpgsqlBatchCommand("select \"t0\".\"start_time\" from \"task\".\"tasks\" \"t0\" where \"t0\".\"number\" = 217"));
await batch.PrepareAsync();

using var reader = await batch.ExecuteReaderAsync();

start_time
列的类型为
timestamptz

两次尝试都没有成功。据我了解:1次尝试没有成功,因为

SET TIME ZONE
用分号
npgsql
将命令文本分成批次。所以
;
是单独批次的,不适用于
SET TIME ZONE
有关批次的更多信息,请参见 

select

https://www.infoq.com/news/2022/06/Database-Command-Batching/
当我在 PgAdmin 中运行查询时,

npgsql

有效 - 我得到了不同的结果

SET TIME ZONE


c# .net postgresql npgsql
1个回答
0
投票
SET TIME ZONE '+02:00'; select "t0"."start_time" from "task"."tasks" "t0" where "t0"."number" = 217

没有效果是有充分理由的。NpgSQL 将

SET TIME ZONE
作为 DateTime 值返回,其
timestamp with time zone
是 DateTimeKind.UTC。这在
类型映射文档
中进行了解释。 PostgreSQL 本身将 Kind 存储为 UTC 值,没有原始偏移量或时区名称。来自
PostgreSQL 文档

对于带时区的时间戳,内部存储的值始终为 UTC(通用协调时间,传统上称为格林威治标准时间,GMT)。指定了显式时区的输入值将使用该时区的适当偏移量转换为 UTC。如果输入字符串中未指定时区,则假定其处于系统 TimeZone 参数指示的时区,并使用时区的偏移量将其转换为 UTC。

当输出带有时区值的时间戳时,它始终从 UTC 转换为当前时区,并显示为该区域的本地时间。要查看另一个时区的时间,请更改时区或使用 AT TIME ZONE 构造

NpgSQL 返回的值是准确的 - UTC 日期时间。如果应用程序将其视为 UTC 时间,那么这应该不是问题。不幸的是,像
timestamp with timezone

ignore
ToString 属性这样的函数。在这种情况下,一个不错的选择是使用
DateTime.ToLocalTime
将值转换为 C# 中的本地日期,例如: Kind

另一个选项是将值转换为 
while(reader.Read()) { ... var date=reader.GetDateTime(3).ToLocalTime(); ... }

,确保 UTC 和本地永远不会混淆:

DateTimeOffset

另一种选择是使用 
var date=new DateTimeOffset(reader.GetDateTime(3));

让 PostgreSQL 将时间转换为特定时区。但不要使用偏移量,因为这会根据 DST 规则而改变。使用 IANA 时区名称要安全得多,例如:

AT TIME ZONE

© www.soinside.com 2019 - 2024. All rights reserved.