Postgresql 确定UTC时间戳是否在时区的时间范围内?

Postgresql 确定UTC时间戳是否在时区的时间范围内?,postgresql,datetime,time,timezone,postgresql-9.4,Postgresql,Datetime,Time,Timezone,Postgresql 9.4,让我们把这个问题框架化为一个调度应用程序。用户在其时区中指定一个最短时间(“美国/纽约”中的“上午8点”),之后他们愿意接受预约。(我们对最长时间也有类似的限制) 给定传入的预约请求(例如,对于UTC时间的2016-09-07 03:00:00),我们需要确定哪些用户可以接受预约 如何确定UTC时间戳是否在两个时区调整时间之间? 我的方法是将传入的时间戳转换为用户的时区,提取时间部分并将其与时间约束进行比较: SELECT * FROM users u WHERE ('2016-09-07

让我们把这个问题框架化为一个调度应用程序。用户在其时区中指定一个最短时间(“美国/纽约”中的“上午8点”),之后他们愿意接受预约。(我们对最长时间也有类似的限制)

给定传入的预约请求(例如,对于UTC时间的
2016-09-07 03:00:00
),我们需要确定哪些用户可以接受预约

如何确定UTC时间戳是否在两个时区调整时间之间?

我的方法是将传入的时间戳转换为用户的时区,提取时间部分并将其与时间约束进行比较:

SELECT * FROM users u WHERE
   ('2016-09-07 03:00:00' AT TIME ZONE u.timezone)::time >= u.earliest_start_time AND
   ('2016-09-07 03:00:00' AT TIME ZONE u.timezone)::time <= u.latest_stop_time
从用户u中选择*
('2016-09-07 03:00:00'在时区u.timezone)::TIME>=u.earlime\u start\u TIME和

('2016-09-07 03:00:00'AT TIME ZONE u.timezone)::TIME为了使下面的代码更可读,假设占位符
$1
包含一个带有时区的
时间戳类型的值。然后,以下查询将查找当时可用的所有用户:

SELECT * FROM users u WHERE
    $1 BETWEEN
      ($1::date || ' ' || u.earliest_start_time)::timestamp without time zone AT TIME ZONE u.timezone
    AND
      ($1::date || ' ' || u.latest_stop_time)::timestamp without time zone AT TIME ZONE u.timezone;
说明:我们使用
$1
,这是一个带有时区的
时间戳
,通过将日期部分转换为
日期
,我们只保留日期部分。然后我们取
最早开始时间
这是一个时间,并将其与之前的日期相结合,得到没有时区信息的完整时间戳。然后我们指定时区,将其转换为带有时区的
时间戳。我们对
最新的停车时间
也这样做。现在我们已经找到了带有时区值的2个
时间戳,我们可以将它们与具有相同类型的
$1
进行比较


这会有时间戳不明确的问题(即从DST到标准时间的转换),但您无法避免。如果您仅在典型的营业时间使用它,则可能没有问题。

要使下面的代码更具可读性,请假设占位符
$1
包含带时区的
时间戳类型的值。然后,以下查询将查找当时可用的所有用户:

SELECT * FROM users u WHERE
    $1 BETWEEN
      ($1::date || ' ' || u.earliest_start_time)::timestamp without time zone AT TIME ZONE u.timezone
    AND
      ($1::date || ' ' || u.latest_stop_time)::timestamp without time zone AT TIME ZONE u.timezone;
说明:我们使用
$1
,这是一个带有时区的
时间戳
,通过将日期部分转换为
日期
,我们只保留日期部分。然后我们取
最早开始时间
这是一个时间,并将其与之前的日期相结合,得到没有时区信息的完整时间戳。然后我们指定时区,将其转换为带有时区的
时间戳。我们对
最新的停车时间
也这样做。现在我们已经找到了带有时区值的2个
时间戳,我们可以将它们与具有相同类型的
$1
进行比较


这会有时间戳不明确的问题(即从DST到标准时间的转换),但您无法避免。如果您只在典型的营业时间使用它,它可能还可以。

您不必这样做,因为本地时间戳可能不明确。例如,假设您的用户给您一个本地范围,该范围在纽约时间2016-11-06T01:30结束。现在,2016-11-05T21:45是之前还是之后?这是在11月6日纽约第一次发生的凌晨1:30之后,但在第二次发生的凌晨1:30之前。。。基本上,您需要知道用户给出的“1:30am”是第一次出现还是第二次出现。。。另一种情况是,用户说的是凌晨1:30,但被跳过了……最早开始时间和最晚停止时间的类型是什么?它是包含日期信息还是只是一天中的某个时间?啊。我想我明白了。考虑到我有一个最小和最大的限制,我必须在查询中以某种方式编码我的意思是通过夜晚的范围?@redneb just time。更新了问题。那么,这些预约开始时间是针对特定日期,还是(或多或少,t.b.d)定期,比如每个工作日9点到5点,还是每周三4点到6点?如果是后者,那么你不应该只比较时间,而是比较完整的日期;因此,请为该日期和开始/停止时间(考虑用户时区)创建UTC时间戳,然后根据该时间戳进行比较。您不必这样做,因为本地时间戳可能不明确。例如,假设您的用户给您一个本地范围,该范围在纽约时间2016-11-06T01:30结束。现在,2016-11-05T21:45是之前还是之后?这是在11月6日纽约第一次发生的凌晨1:30之后,但在第二次发生的凌晨1:30之前。。。基本上,您需要知道用户给出的“1:30am”是第一次出现还是第二次出现。。。另一种情况是,用户说的是凌晨1:30,但被跳过了……最早开始时间和最晚停止时间的类型是什么?它是包含日期信息还是只是一天中的某个时间?啊。我想我明白了。考虑到我有一个最小和最大的限制,我必须在查询中以某种方式编码我的意思是通过夜晚的范围?@redneb just time。更新了问题。那么,这些预约开始时间是针对特定日期,还是(或多或少,t.b.d)定期,比如每个工作日9点到5点,还是每周三4点到6点?如果是后者,那么你不应该只比较时间,而是比较完整的日期;因此,为该日期和开始/停止时间(考虑用户时区)创建UTC时间戳,然后根据该时间戳进行比较。