我试图在一个特定时区的特定时间获取当前日期,然后在Postgres中将其转换为UTC
我能够做到这一点,但它看起来超级怪异(看看最后)
让我们深入了解一下:
首先,我们要选择时区:Atlantic/Cape_Verde
,因为它是UTC - 1,没有夏令时(因此更容易调试)
现在我们把它分成几部分
1.获取时区中的当前日期
1.设置该时区的时间
1.转换为UTC
我们假设现在是06/06/23 20:00
(UTC)
1.获取时区当前日期:
-- 06/06/23
SELECT date(now() at time zone 'Atlantic/Cape_Verde');
2.设置该时区的时间:
-- 2023-06-06 03:00:00
SELECT date(now() at time zone 'Atlantic/Cape_Verde') + time '03:00';
3.转换为UTC:
出于某种原因,将其转换为UTC,我需要这样做:
-- 2023-06-06 04:00:00+00
SELECT (date(timezone('Atlantic/Cape_Verde', now())) + time '03:00') at time zone 'Atlantic/Cape_Verde'
为什么为了转换为UTC,我需要转换为我使用的时区??
1条答案
按热度按时间blmhpbnm1#
Postgres有两种时间戳类型:
2023-06-06 00:00:01+01
是带有时区的时间戳。如果你想始终知道那是哪一天,或者是哪一个月,等等,那么你必须告诉Postgres你想要计算的时区,因为这个历史时刻可能是一个时区/地点的周二,而另一个时区/地点的周一。2023-06-06 00:00:01
是没有时区的时间戳。没有上下文,我们不知道它代表了什么历史时刻,因为不同的地方在不同的历史时刻有一个时间2023-06-06 00:00:01,但我们可以可靠地说这一天是2023-06-06,这是一个星期二。令人困惑的是,这两种类型都没有与时区一起存储。
now()
返回一个带有时区的时间戳,这意味着在你将其转换为日期之前,你必须告诉Postgres你想要哪个时区的日期,因此:now() at time zone'Atlantic/Cape_Verde'
给出了佛得角的当前时间,没有时区1.要将时间戳截断为日期,可以使用
date_trunc('day', timestamp_without_time_zone)
,因此是date_trunc('day', now() at time zone'Atlantic/Cape_Verde')
1.现在你得到了一个无时区的时间戳,它显示了佛得角的日期;你告诉Postgres该时间戳的相关时区应该是Cape Verde。因此,
date_trunc('day', now() at time zone'Atlantic/Cape_Verde') at time zone'Atlantic/Cape_Verde'
。现在你有一个时间戳,它表示佛得角一天开始的时刻,但由于它是一个带有时区的时间戳,Postgres将在会话的配置时区中将其作为带有时区的时间戳返回给你1.如果你把它保存为带有时区的时间戳,你就完成了!如果你需要一个没有时区的时间戳,它对应于UTC时区中的那个时刻,你必须告诉Postgres给予你相应的UTC时间:
date_trunc('day', now() at time zone'Atlantic/Cape_Verde') at time zone'Atlantic/Cape_Verde' at time zone'Z'
有关
at time stamp
构造的更多信息,请阅读原始文档您可以通过以下方式简化此操作:
1.将时区传递到
date_trunc
,即date_trunc('day', now(),'Atlantic/Cape_Verde');
(参见文档),它将返回带有时区的时间戳,所以1.之后,你只需要告诉Postgres你想要UTC时间。您可以通过以下方式执行此操作:
date_trunc('day', now(),'Atlantic/Cape_Verde') at time zone'Z'