我正在使用最新的Zend框架与PostgreSQL数据库进行通信。我的一些数据库表具有now()字段,该字段添加当前时间戳。但是,不同请求的数据库连接时区可能不同。
是否可以按每个连接设置PostgreSQL数据库的时区?我知道您可以向Zend_Db实例传递驱动程序选项,因此我认为其中有诀窍。
是否可以按每个连接设置PostgreSQL数据库的时区?我知道您可以向Zend_Db实例传递驱动程序选项,因此我认为其中有诀窍。
首先,考虑使用数据类型timestamptz
(带有时区的时间戳)而不是timestamp
(不带时区的时间戳)。这样用户的时区就不重要了。now()
返回timestamptz
,你的问题源于将其强制转换为timestamp
。请参见:
timestamp
类型!"如果您的连接是通过可以绑定到时区的数据库角色(登录名)进行的,则PostgreSQL提供了一个简单的解决方案:
ALTER ROLE my_role SET TIMEZONE = '+1';
这个角色发起的每个连接都会自动以其预设时区运行(除非另有指示)。
请注意,引用手册:
这仅在登录时发生;执行
SET ROLE
或SET SESSION AUTHORIZATION
不会导致设置新的配置值。
您可能希望使用时区名称而不是纯偏移量来遵循夏令时规则和其他本地时间的政治操纵。更多信息:
或者,您可以为登录创建一个查找表,其中存储各自的时区(这可能还具有其他用途):
CREATE TABLE usertime(
username text PRIMARY KEY -- careful, "user" is a reserved word
, timezone text -- ... but "timezone" is not
);
INSERT INTO usertime VALUES
('postgres', '+4')
, ('my_role' , '+3')
;
编写一个小的SQL函数:
CREATE FUNCTION f_user_ts()
RETURNS timestamp
LANGUAGE sql STABLE AS
$func$
SELECT now() AT TIME ZONE u.timezone
FROM usertime u
WHERE u.username = current_user
$func$;
SELECT f_user_ts();
有关AT TIME ZONE
结构的详细信息,请参阅精细手册。这两种语法变体都是有效的:
SET TIME ZONE TO 'UTC';
SET TIMEZONE TO 'UTC';
now() AT TIMEZONE foo;
SELECT now() AT TIME ZONE foo;
foo
是一个 text
变量(或者像上面的函数一样的列),保存着时区偏移,缩写或名称。你也可以直接提供一个字符串字面量。
CREATE USER
触发器(https://www.postgresql.org/docs/9.3/event-trigger-matrix.html)。这可能会很有用,也许将来会支持。 - Kind ContributorSET TIMEZONE TO 'X'
。 - Kind Contributor这只是一个猜测,但如果您设置使用的角色的时区会怎样呢?
ALTER ROLE my_db_user IN DATABASE my_database
SET "TimeZone" TO 'UTC';
@date( 'c' )
。这里有一个关于该主题的相关答案。 - Fabien Snauwaert