获得“动态”时区之间的等效时间

时间:2012-09-18 11:32:00

标签: php web-services postgresql

我有一个表providers,它有三列(包含更多列但在这种情况下不重要):

  • starttime,您可以与他联系的开始时间。
  • endtime,最后一小时,您可以与他联系。
  • region_id,提供商所在的区域。在美国:加利福尼亚州,德克萨斯州等。在英国:英格兰,苏格兰等

starttimeendtime是没有时区列的时间,但是,“间接”,它们的值具有提供者所在区域的时区。例如:

starttime | endtime  | region_id (time zone of region) | "real" st | "real" et
----------|----------|---------------------------------|-----------|-----------
 03:00:00 | 17:00:00 |     1     (EGT => -1)           | 02:00:00  | 16:00:00

通常我需要获取时间范围在当前服务器时间内的供应商列表(考虑时区转换)。问题是时区不是“恒定的”,即它们可能在夏季变化。然而,这种变化对于该区域非常具体,并且不总是同时进行:EGT< => EGST,ART< => ARST等。

问题是:

1。是否有必要使用网络服务频繁更新区域内的时区?有没有人知道可以提供服务的网络服务?

2。有没有更好的方法来解决这个问题?

提前致谢。

更新

我将举一个例子来澄清我想要得到的东西。在表providers中,我找到了这些记录:

idproviders | starttime | endtime  | region_id
------------|-----------|----------|-----------
      1     |  03:00:00 | 17:00:00 |   23 (Texas)
      2     |  04:00:00 | 18:00:00 |   23 (Texas)

如果我在1月份执行查询,请输入以下信息:

  • 服务器时间(UTC偏移)= 0小时
  • 德克萨斯州提供商(UTC偏移)= +1小时
  • 服务器时间= 02:00:00

我应该得到以下结果: idproviders = 1

如果我在六月份执行查询,请输入以下信息:

  • 服务器时间(UTC偏移)= 0小时
  • 德克萨斯州提供商(UTC偏移)= +2小时(他们的当地时间没有变化,但他们的时区已经改变)
  • 服务器时间= 02:00:00

我应该得到以下结果: idproviders = 1和2

2 个答案:

答案 0 :(得分:2)

您还没有任何有关您的"地区的详细信息"记录除了他们有身份证明之外。

但是,您可以在timezone varchar NOT NULL表中添加一列regions(我假设您有一个)。您需要为每个地区分配一个time zone name。这可能不是一项简单的任务。

执行此操作后,您可以使用以下查询找到哪些提供商在营业时间内:

SELECT p.* FROM providers AS p LEFT JOIN regions AS r ON (r.id = p.region_id)
WHERE (now() AT TIME ZONE r.timezone)::time BETWEEN p.start_timestamp AND p.end_timestamp;

now() AT TIME ZONE r.timezone会将当前服务器时间转换为分配给该区域的时区。

示例设置:您的服务器位于伦敦,您的提供商位于巴拿马 示例案例1:您的服务器时间是2012-01-01 18:00:00。 '2012-01-01 18:00:00' AT TIME ZONE 'America/Panama'将返回2012-01-01 13:00:00,即巴拿马当前时间,您可以与提供商start_timestampend_timestamp进行比较。
示例案例2:您的服务器时间是2012-08-01 18:00:00并且您观察到夏令时。然而,巴拿马观察DST,因为它接近赤道并且日长度没有显着变化。尽管如此,'2012-08-01 18:00:00' AT TIME ZONE 'America/Panama'将在巴拿马返回正确的当前时间2012-08-01 12:00:00,因为Postgres知道您8月份的时间是DST,而巴拿马的时间不是。

我不知道如何让它更清楚。

答案 1 :(得分:1)

如果你只有一个time(而不是timestamp)和一个像“德克萨斯”这样的地区,那么你开始时运气不好。是否应该是夏令时的信息不存在。你不可能知道。

即使您只使用timestamptz组件,也要将该字段设为timestamp with time zonetime)。因此,只要有人输入一个值,就会在内部将其转换为UTC时间戳(自动将DST考虑在内)并且您拥有明确的信息。该值将根据当前时区设置自动显示(适用于所有人),适合所有人。测试时,您可以简单地将它投射到时间:

SELECT start_timestamp::time

它为您提供等效的 local time(根据您当前的时区设置)。让一切变得非常轻松 更多解释PostgreSQL如何处理this related answer中的时间戳。