使用 now()::timestamp 函数存储的时间存储错误值

Lal*_*dar 2 postgresql timezone

我将 AWS RDS 用于带有 PGAdmin 的 PostgreSQL 11 数据库。我存储每一行​​的创建日期,now()::timestamp用于存储没有时区的日期和时间。问题是存储的时间永远不是我想要的值 ( UTC+05:30)。

如果我设定的参数timezoneUTC在RDS,然后储存时间的背后是印度时间5:30小时,但如果我设置UTC + 05:30,它存储时间背后要么11小时或1小时以上,这种情况随机随机行。我没有改变任何其他东西,只是这个timezone参数。

我搜索了很多,但没有找到任何类似的答案。

Bas*_*que 9

tl;博士

  • 为数据类型TIMESTAMP WITHOUT TIME ZONE定义列而不是数据类型TIMESTAMP WITH TIME ZONE
  • 将 PgAdmin 中会话的默认时区设置为UTC
  • 要将检索到的 UTC 值调整为 SQL 中的特定时区,请调用AT TIME ZONE 'Asia/Kolkata'. (但最好将区域调整留给您的应用程序代码而不是您的 SQL。)

TIMESTAMP WITHOUT TIME ZONE

存储没有时区的日期和时间。

您在定义列时使用了错误的数据类型

TIMESTAMP WITHOUT TIME ZONE数据类型不能代表一个时刻

这种类型故意缺少时区或 UTC 偏移量的上下文。所以你有一个日期和时间,比如明年 1 月 23 日的中午。但是我们无法知道您是指日本东京的中午,法国图卢兹的中午,还是美国俄亥俄州托莱多的中午,这些时间都相差几个小时。

到达类型为 的列时,将忽略与输入一起传递的任何时区或偏移量信息 TIMESTAMP WITHOUT TIME ZONE

TIMESTAMP WITH TIME ZONE

TIMESTAMP WITH TIME ZONE类型可以跟踪某个时刻,即时间轴上的特定点。

任何与日期和时间一起传递的时区或偏移量信息都用于调整为 UTC。然后丢弃区域/偏移。因此,如果您关心原始区域/偏移量,则需要将其显式存储在额外的列中。

检索TIMESTAMP WITH TIME ZONE值时,该值将始终采用 UTC(零时分秒的偏移量)。但是,请注意带有将某些默认时区或偏移量注入检索值的反特性的工具、中间件或驱动程序。这会产生该区域/偏移量已被存储的错觉,而实际上 Postgres 总是以数据类型的UTC存储TIMESTAMP WITH TIME ZONE

管理员是具有这种不幸反功能的工具之一。我建议始终将会话的默认区域设置为 UTC,以便在存储时查看检索到的值。

调整时区

我建议你学会在 UTC 中以程序员的身份思考和工作。编程中的大部分业务逻辑都应该使用 UTC。调整到仅用于向用户展示或业务逻辑需要的时区。因此,这意味着在大多数情况下,您应该仅在应用程序代码中而不是在 SQL 和数据库管理工具中调整时区。

AT TIME ZONE 功能

但是,如果您坚持使用 SQL 调整时区,请使用该AT TIME ZONE功能。

您提到了比 UTC 早五个半小时的偏移量+05:30。我假设你的意思是在印度的时间。始终更喜欢实时时区名称而不是特定的偏移量。政客经常更改其管辖范围使用的抵消额。因此,对偏移量进行硬编码可能会导致错误的结果。

保持Postgres 安装中的tzdata文件是最新的,然后让 Postgres 确定适合该特定时刻的命名时区的偏移量

… AT TIME ZONE 'Asia/Kolkata' …
Run Code Online (Sandbox Code Playgroud)

各种日期时间数据类型

我为 Java 程序员制作的这个图表在这里也可能有用,以更好地理解 SQL 标准定义的各种数据类型。

Java(旧版和现代版)和标准 SQL 中的日期时间类型表