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

时间:2016-09-03 20:33:14

标签: postgresql datetime time timezone postgresql-9.4

让这个问题成为一个调度应用程序。用户在其时区中指定的最短时间("上午8点"在" America / New_York"中),之后他们愿意接受约会。 (我们对最长时间也有类似的约束)

鉴于传入的约会请求(例如,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

earliest_start_timelatest_stop_time属于time without time zone; timezone是Olson tz字符串)

由于时区偏移会导致数天翻身,因此存在各种奇怪的行为。我对这一点感到非常困惑和朦胧。

1 个答案:

答案 0 :(得分:2)

为了使下面的代码更具可读性,假设占位符$1包含timestamp with time zone类型的值。然后,以下查询将查找当时可用的所有用户:

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这是一个timestamp with time zone,我们只保留日期部分按类型转换为date。然后我们取earliest_start_time这是一个时间并将其与前一个日期相结合,我们得到的时间戳没有时区信息(尚未)。然后我们指定将其转换为timestamp with time zone的时区。我们对latest_stop_time做同样的事情。现在我们已经找到了这两个timestamp with time zone值,我们可以将它们与具有相同类型的$1进行比较。

这会产生模糊时间戳的问题(即从DST到标准时间的过渡),但你无法避免这种情况。如果您只在典型的营业时间使用它,那可能没问题。