sql – 在Postgres中计算DST,选择计划的项目

我有一个Postgres表的闹钟(不是真的,但这是类似的,更容易解释).警报由用户设置,分辨率为1小时,用户可以来自许多不同的时区.警报每天都在重复.我想可靠地获取在一天的特定时间内应该消失的闹钟,而且我在夏令时问题.我该怎么做最好的方法

Alfred and Lotta both live in Stockholm (+1 hour from UTC,but +2h
when it’s DST).
Sharon lives in Singapore (+8 hours from UTC,no
DST)

During winter,Alfred sets an alarm for 4 AM. The alarm should go off
at 4 AM local time,all year.
During summer,Lotta sets an alarm
for 5 AM. Again,it should go off at 5 AM all year round.
Meanwhile,Sharon has set an alarm for 11 AM.

All of these can be stored in the database as 03:00 UTC.

If I query the database in the winter for alarms that should go off at
03:00 UTC,I want Alfred’s and Sharon’s alarms. Singapore is Now +7h
from Sweden,so 11 AM in Singapore is 4 AM in Sweden. Lotta’s alarm
should not go off for another hour.

Conversely,if I query the database in the summer for alarms that
should go off at 03:00 UTC,I want Lotta’s and Sharon’s alarms.
Singapore is +6h from Sweden Now,so 11 AM in Singapore is 5 AM in
Sweden Now. sven’s alarm went off an hour ago.

如何存储这个,并查询数据库

如果需要,我可以更改db模式.目前,我们根本不调整DST,实际上只有一个“小时”的整数字段(看起来很笨,时间域会更好).

看来我需要存储UTC时间和时区信息,但我不知道如何最好地在Postgres中实现这一点.我发现Postgres有一些时区的概念,但是我没有时区字段类型.此外,我想我需要在sql中进行一些计算,以确定如何根据时区数据和创建日期来偏移选择中的UTC时间.我对sql不是很好

我想在Postgres中解决这个问题,因为可能会有很多“警报”,我想避免将所有这些都提取Ruby中并将其过滤掉的性能问题. (是的,这是一个Rails应用程序.)

解决方法

将时间戳与时区(timestamptz)用于计算.
报警时间可以是[无时区].
但是您必须为每一行显式保存时区.

不要使用时区与时区这是一个逻辑破碎的类型,其使用不鼓励Postgresql. I quote the manual here

The type time with time zone is defined by the sql standard,but the
deFinition exhibits properties which lead to questionable usefulness.
In most cases,a combination of date,time,timestamp without time
zone,and timestamp with time zone should provide a complete range of
date/time functionality required by any application.

演示设置:

CREATE TABLE alarm(name text,t time,tz text);
INSERT INTO alarm VALUES
 ('Alfred','04:00','Europe/Stockholm') -- Alfred sets an alarm for 4 AM.,('Lotta','05:00','Europe/Stockholm') -- Lotta sets an alarm for 5 AM.,('Sharon','11:00','Asia/Singapore');  -- Sharon has set an alarm for 11 AM.

它必须是时区名称(而不是缩写)来解释DST.
考虑this related question的信息.

获取匹配的“today”警报:

SELECT *
FROM   alarm
WHERE  (('2012-07-01'::date + t) AT TIME ZONE tz AT TIME ZONE 'UTC')::time
       = '03:00'::time

>(‘2012-7-1’:: date t)…组合时间戳[没有时区]
也可以现在():: date t为“今天”.
> AT WITH TIME ZONE tz …在保存的时区放置时间戳,导致timestamptz.
> AT WITH TIME ZONE’UTC’…获取UTC时间戳
> :: time …最简单的方法提取时间组件.

这里可以查询time zone names

SELECT *
FROM   pg_timezone_names
WHERE  name ~~* '%sing%'
LIMIT  10

SQL Fiddle展示夏/冬.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...