考虑一个简单的DB Schema:
Table XYZ:
filter_datetime: DateTime field (With Timezone enabled)
现在,如果我想找到filter_datetime
在"星期一"上发生的所有XYZ行,如果我忽略时区则可以这样做。
但是,如果我不想忽略时区信息,如何查询?
另外,特别针对我的情况,我可以确保filter_datetime
具有相同的时区。但是,一旦填充了表,用户应该能够根据不同的时区进行查询并获得正确的结果。 (那是UTC + 6:00的用户在尝试获取星期一行时会有不同的行,而不是在UTC-6:00中有时区的用户)
奖金(我真的不需要接受答案):是否有可能通过Django ORM?
答案 0 :(得分:0)
样品:
t=# create table xyz(filter_datetime timestamptz);
CREATE TABLE
t=# insert into xyz select generate_series('2018-02-04'::timestamptz,'2018-02-14'::timestamptz,'4 hour'::interval);
INSERT 0 61
选择(如果你不想忽视TZ - 只是不要忽视它):
t=# set TimeZone to 'UTC-6:00';
SET
t=# select ctid,filter_datetime at time zone 'UTC' utc, filter_datetime,to_char(filter_datetime,'Day'), extract(dow from filter_datetime)
from xyz
where extract(dow from filter_datetime) = 1
order by 1;
ctid | utc | filter_datetime | to_char | date_part
--------+---------------------+------------------------+-----------+-----------
(0,6) | 2018-02-04 20:00:00 | 2018-02-05 02:00:00+06 | Monday | 1
(0,7) | 2018-02-05 00:00:00 | 2018-02-05 06:00:00+06 | Monday | 1
(0,8) | 2018-02-05 04:00:00 | 2018-02-05 10:00:00+06 | Monday | 1
(0,9) | 2018-02-05 08:00:00 | 2018-02-05 14:00:00+06 | Monday | 1
(0,10) | 2018-02-05 12:00:00 | 2018-02-05 18:00:00+06 | Monday | 1
(0,11) | 2018-02-05 16:00:00 | 2018-02-05 22:00:00+06 | Monday | 1
(0,48) | 2018-02-11 20:00:00 | 2018-02-12 02:00:00+06 | Monday | 1
(0,49) | 2018-02-12 00:00:00 | 2018-02-12 06:00:00+06 | Monday | 1
(0,50) | 2018-02-12 04:00:00 | 2018-02-12 10:00:00+06 | Monday | 1
(0,51) | 2018-02-12 08:00:00 | 2018-02-12 14:00:00+06 | Monday | 1
(0,52) | 2018-02-12 12:00:00 | 2018-02-12 18:00:00+06 | Monday | 1
(0,53) | 2018-02-12 16:00:00 | 2018-02-12 22:00:00+06 | Monday | 1
(12 rows)
t=# set TimeZone to 'UTC+6:00';
SET
t=# select ctid,filter_datetime at time zone 'UTC' utc, filter_datetime,to_char(filter_datetime,'Day'), extract(dow from filter_datetime)
from xyz
where extract(dow from filter_datetime) = 1
order by 1;
ctid | utc | filter_datetime | to_char | date_part
--------+---------------------+------------------------+-----------+-----------
(0,9) | 2018-02-05 08:00:00 | 2018-02-05 02:00:00-06 | Monday | 1
(0,10) | 2018-02-05 12:00:00 | 2018-02-05 06:00:00-06 | Monday | 1
(0,11) | 2018-02-05 16:00:00 | 2018-02-05 10:00:00-06 | Monday | 1
(0,12) | 2018-02-05 20:00:00 | 2018-02-05 14:00:00-06 | Monday | 1
(0,13) | 2018-02-06 00:00:00 | 2018-02-05 18:00:00-06 | Monday | 1
(0,14) | 2018-02-06 04:00:00 | 2018-02-05 22:00:00-06 | Monday | 1
(0,51) | 2018-02-12 08:00:00 | 2018-02-12 02:00:00-06 | Monday | 1
(0,52) | 2018-02-12 12:00:00 | 2018-02-12 06:00:00-06 | Monday | 1
(0,53) | 2018-02-12 16:00:00 | 2018-02-12 10:00:00-06 | Monday | 1
(0,54) | 2018-02-12 20:00:00 | 2018-02-12 14:00:00-06 | Monday | 1
(0,55) | 2018-02-13 00:00:00 | 2018-02-12 18:00:00-06 | Monday | 1
(0,56) | 2018-02-13 04:00:00 | 2018-02-12 22:00:00-06 | Monday | 1
(12 rows)
如您所见,具有不同TimeZone的客户端会将不同的行视为星期一。这是因为timestamptz
将时间保留在UTC中 - 而不是在客户端时区。返回客户端时转换它。
https://www.postgresql.org/docs/current/static/datatype-datetime.html
对于带时区的时间戳,内部存储的值始终为 UTC(通用协调时间,传统上称为格林威治标准 时间,GMT)。具有指定显式时区的输入值是 使用该时区的适当偏移量转换为UTC。如果 在输入字符串中没有声明时区,则假定它是 在系统的TimeZone参数指示的时区中,是 使用时区的偏移量转换为UTC。
https://www.postgresql.org/docs/current/static/functions-formatting.html