启用时区的星期几查询

Day of Week Query with Timezone Enabled

考虑一个简单的数据库模式:

Table XYZ:
    filter_datetime: DateTime field (With Timezone enabled)

现在,如果我想找到所有 filter_datetime 出现在 "Monday" 的 XYZ 行,如果我忽略时区,这是可行的。

但是,如果不想忽略时区信息,该如何查询呢?

此外,特别针对我的情况,我可以确保 filter_datetime 具有相同的时区。但是,一旦 table 被填充,用户应该能够根据不同的时区进行查询并获得正确的结果。 (也就是说,UTC+6:00 的用户在尝试获取星期一行时会有不同的行,而不是 UTC-6:00 时区的用户)

奖金(我真的不需要接受答案):是否可以通过 Django ORM?

样本:

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

select(如果你不想忽略 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)

如您所见,具有不同时区的客户在星期一看到不同的行。这是因为 timestamptz 保持 UTC 时间 - 而不是客户端时区。返回客户端时进行转换。

https://www.postgresql.org/docs/current/static/datatype-datetime.html

For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system's TimeZone parameter, and is converted to UTC using the offset for the timezone zone.

https://www.postgresql.org/docs/current/static/functions-formatting.html