PostgreSQL默认时区

164

我安装了PostgreSQL 9,但它显示的时间比服务器时间早1小时。

运行Select NOW()命令显示:2011-07-12 11:51:50.453842+00

服务器日期显示为:Tue Jul 12 12:51:40 BST 2011

时区显示为:phppgadmin TimeZone Etc/GMT0

我已经尝试进入postgresql.conf并设置

timezone = GMT

然后重新启动,但没有变化。

有任何想法吗?我以为它只会使用服务器时区,但显然不是?!

解决方案:我之前设置为GMT,但是还是比实际时间早了一个小时。在搜索后,发现需要将其设置为Europe/London。这可以考虑到英国夏令时的+1小时,而GMT则不包括!


在进行任何更改之前,检查当前时区值总是一个好习惯。这里有一些提示:https://dev59.com/EF4c5IYBdhLWcg3wMnz1#28218103 - Hartley Brody
10个回答

179

时区是一个会话参数。因此,您可以更改当前会话的时区。

请参阅文档

set timezone TO 'GMT';
或者更贴近SQL标准,使用SET TIME ZONE命令。需要注意的是,上面的代码使用单词"timezone",而SQL标准使用了两个单词"TIME ZONE"。
SET TIME ZONE 'UTC';

官方文档已经解释了区别:

SET TIME ZONE 扩展了SQL标准中定义的语法。标准只允许使用数字时区偏移量,而PostgreSQL允许更灵活的时区规范。所有其他 SET 功能都是PostgreSQL的扩展。


5
我尝试过设置那个,但好像没有起作用。而且那样的话只会在当前会话中生效。我希望永久地更改它,使所有数据库都生效。我在phpMyAdmin中轻松地完成了这个操作,但似乎找不到在PostgreSQL中实现的方法。 - Blu Towers
5
"yup 'set timezone To ..' 只会为当前会话设置时区,如果您在Postgresql.conf中更改了时区配置参数,则应该会更改所有数据库的时区。" - Muhammad Usama
7
我已经尝试通过在postgresql.conf中更改时区为GMT,看起来运行良好。 - Muhammad Usama
更标准(符合SQL规范)的写法是将“TIME ZONE”拆成两个单词:SET TIME ZONE 'UTC';。请参阅文档 - Basil Bourque

164

请选择一个时区

SELECT * FROM pg_timezone_names;

并按照下面给出的示例 set

ALTER DATABASE postgres SET timezone TO 'Europe/Berlin';

在上面的语句中,用你的数据库名称替换 postgres


9
完成后需要重新启动PostgreSQL服务。 - Joey Pinto
36
@JoeyPinto不正确,只需要执行SELECT pg_reload_conf();就足够了 :) - Alphaaa
7
我使用我的数据库名称运行了这个语句,SELECT pg_reload_conf() 返回了 true,但是 now()select current_setting('TIMEZONE') 仍然返回 'America/New_York' 的值。这是因为我不是超级用户吗? - Noumenon
2
@Prempopatia 或许是一个新手问题:您尝试刷新pgadmin本身了吗? - Alex Rizvi
2
@Noumenon 对我来说,关闭并重新打开pgadmin有帮助。 - user2678868
显示剩余5条评论

74

经过检验,Muhammad Usama所提供的被采纳的答案是正确的。

配置参数名称

该回答演示了如何设置Postgres特定的配置参数,具体方法如下:

SET timezone TO 'UTC';

...其中timezone不是SQL命令,而是配置参数的名称。

参见此文档

标准SQL命令

或者,您可以使用SQL规范定义的SQL命令:SET TIME ZONE。在这种语法中,一对单词TIME ZONE替换了“timezone”(实际SQL命令与参数名称之间的区别),并且没有“TO”。

SET TIME ZONE 'UTC';

这两个命令具有相同的效果,都是为当前会话设置值。要使更改永久生效,请参见此兄弟答案

请查看此文档

时区名称

您可以指定适当的时区名称。其中大多数是以大陆/地区表示。

SET TIME ZONE 'Africa/Casablanca';

...或者...

SET TIME ZONE 'America/Montreal';

避免使用3或4个字母的缩写,例如ESTIST,因为它们既不标准化也不唯一。请参阅维基百科中的时区名称列表

获取当前时区

要查看会话的当前时区,请尝试以下任一语句。从技术上讲,我们正在调用SHOW命令以显示运行时参数。

SHOW timezone ;

…或者…

SHOW time zone ;

美国/太平洋时区


16
好的,我会尽力进行翻译。以下是需要翻译的内容:bonus point for being the only answer to provide the SHOW part如果你能提供“SHOW”部分的答案将获得额外加分。 - Ariel Allon
2
明白,Ariel Allon -- 而且,对于下一个想要将该时区选择为变量的人... SELECT current_setting('TIMEZONE') - Wellspring
请注意,本答案是关于为当前会话设置时区,这与数据库的默认时区不同。此外,不同的列可能也有不同的时区,甚至是带时区的时间戳列中的每个时间戳。 - Mikko Rantalainen
@MikkoRantalainen 不,不正确,Postgres不会保存任何可能随输入提供的时区信息。任何这样的时区信息都用于调整为UTC(偏移量为零)。调整后,Postgres 丢弃该时区信息。类型为TIMESTAMP WITH TIME ZONE的每个列中的所有值都在UTC中,具有零偏移量。如果要保留每个输入的原始时区,则必须将其保存到附加列中。 - Basil Bourque
如果 show timezone; 或者 show time zone; 可以正常工作,那么 SET TIMEZONE… 是无法正常工作的,只有 SET TIME ZONE 'Europe/Paris'; 可以正常工作。 - undefined
显示剩余2条评论

64
为了在Postgres 9.1中实现时区更改,您需要执行以下步骤: 1.- 在/usr/share/postgresql/9.1/的"timezones"文件夹中查找适当的文件,在我的情况下是"America.txt",在其中查找最接近您时区的位置并复制左列的首字母。
例如:如果您在"纽约"或"巴拿马",则应该是"EST":
#  - EST: Eastern Standard Time (Australia)
EST    -18000    # Eastern Standard Time (America)
                 #     (America/New_York)
                 #     (America/Panama)

2.- 取消注释您的postgresql.conf文件中的"timezone"行,并按照所示设置您的时区:

#intervalstyle = 'postgres'
#timezone = '(defaults to server environment setting)'
timezone = 'EST'
#timezone_abbreviations = 'EST'     # Select the set of available time zone
                                        # abbreviations.  Currently, there are
                                        #   Default
                                        #   Australia

3.- 重新启动Postgres


6
这实际上是正确答案,因为它将 TZ 更改设置为 PGSQL 中每个进程的默认值,而不仅仅是当前用户。 - jfreak53
23
建议您完全避免使用那些只有3或4个字母的代码。它们既不是标准化的,也不是唯一的。相反,请使用正确的时区名称(大陆/城市或地区)。以您自己提供的例子为例,巴拿马全年采用-05:00的偏移量,而纽约在夏令时(DST)调整一个小时。时区不仅包括偏移量,还包括过去、现在和未来的一系列规则和异常情况,如夏令时。因此,请说清楚:America/PanamaAmerica/New_YorkEurope/LondonUTC(或Zulu)。 - Basil Bourque
3
根据PostGRE文档,您可以通过执行SELECT * FROM pg_timezone_names来查看内部视图以获取特定数据库中已识别的时区列表,这样做可能更安全,因为第三方网站不一定像您自己的数据库实例那样及时更新或过时。 - Seldom 'Where's Monica' Needy
2
不需要重启PostgreSQL,您可以运行select pg_reload_conf() - ANeves
我找到了一些笔记:如果你在配置文件中注释掉所有时区行,它会默认使用GMT而不是系统时间。如果你将时区设置为“主机”,它似乎也无法匹配系统时间。因此,像“America/Phoenix”这样的明确时区加上重启就可以完美解决问题,使用维基百科的时区列表即可。 - blissweb
显示剩余3条评论

12
除了之前的答案,如果你使用工具pgAdmin III,你可以按以下方式设置时区:
  1. 通过 Tools > Server Configuration > postgresql.conf 打开Postgres配置文件
  2. 查找timezone条目并双击打开
  3. 更改值
  4. 重新加载服务器以应用配置更改(可以通过顶部的播放按钮或服务进行)

在pgAdmin III中的Postgres配置


根据我的经验,使用pgAdmin工具更改配置后,PostgreSQL服务很容易出现错误。因此,我更喜欢编辑位于“C:\ Program Files \ PostgreSQL \(版本)\ data”中的postgresql.conf原始文件,而不是使用pgAdmin进行配置。 - 1_bug

8

需要注意的是许多第三方客户端拥有自己的时区设置,可能会与Postgres服务器和/或会话设置重叠。

例如,如果您使用的是“IntelliJ IDEA 2017.3”(或DataGrips),则应将时区定义为:

'DB源属性'-> '高级'选项卡-> 'VM选项':-Duser.timezone = UTC + 06:00

否则,无论您在任何地方设置了什么,您都会看到'UTC'。


所以这需要与夏令时/冬令时更改保持同步吗? - Cpt. Senkfuss
2
@Cpt.Senkfuss,我相信类似-Duser.timezone=Australia/Tasmania这样的设置也可以解决夏令时和冬令时的问题。 - ARA1307
这是一个救命的技巧。我已经尝试了3个小时,试图理解问题出在哪里 :) 顺便说一下,我尝试了完整的时区名称,它可以工作。对我来说,它是-Duser.timezone=Europe/Istanbul。 - Olgun Kaya

6

对于希望永久更改Windows 10/11的用户,该文件位于:

C:\Program Files\PostgreSQL\<your-postgres-version>\data\postgresql.conf

对我来说,具体而言是:
C:\Program Files\PostgreSQL\14\data\postgresql.conf

然后在您的文本编辑器中使用ctrl-f查找timezone,并将以下行重置为您喜欢的时区(名称可以通过运行SELECT * FROM pg_timezone_names找到):

log_timezone = 'UTC'

并且

timezone = 'UTC'

在您的数据库GUI或CLI中运行以下查询以重新加载配置文件。
select pg_reload_conf()

通过运行以下命令确认永久更改:

show timezone

1
相同的技巧在Linux系统中对我也起作用。我是在版本12上完成的。 - Aupr

1
也许与问题无关,但我需要使用CST,将系统时区设置为所需的tz(美国/...),然后在postgresql配置文件中将时区值设置为“localtime”,这样就可以正常工作了,current_time打印正确的时间(在Ubuntu 16上的Postgresql 9.5)。

0

如果您设置正在使用的角色的时区会怎样呢?

ALTER ROLE my_db_user IN DATABASE my_database
    SET "TimeZone" TO 'UTC';

这个有用吗?


0
对于Postgres 14+的解决方案: 在postgresql.conf文件中, timezone = 'Europe/Budapest'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接