0

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

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

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

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)

如果我在一月份执行查询,则使用以下信息:

  • 服务器时间(UTC 偏移量)= 0 小时
  • 德州供应商(UTC 偏移量)= +1 小时
  • 服务器时间 = 02:00:00

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

如果我在 6 月执行查询,使用以下信息:

  • 服务器时间(UTC 偏移量)= 0 小时
  • 德州供应商(UTC 偏移量)= +2 小时(他们的本地时间没有改变,但他们的时区改变了)
  • 服务器时间 = 02:00:00

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

4

2 回答 2

2

您没有提供有关“区域”记录的任何详细信息,除了它们具有 ID 的事实。

不过,您可以在表中添加一列timezone varchar NOT NULLregions我假设您有一个)。您需要为您拥有的每个区域分配一个时区名称。这可能不是一项简单的任务。

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

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_timestamp和进行比较end_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,而巴拿马的时间没有。

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

于 2012-09-18T11:59:09.320 回答
1

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

将该字段设为timestamp with time zone( timestamptz),即使您只打算使用该time组件。因此,每当有人输入一个值时,它都会在内部转换为 UTC 时间戳(自动考虑 DST),并且您可以获得明确的信息。该值将根据当前时区设置自动显示(适用于世界各地的每个人),并且适合每个人。测试时,您可以简单地将其转换为时间:

SELECT start_timestamp::time

这为您提供了等效的本地 time(根据您当前的时区设置)。让一切变得非常容易。
更多解释 PostgreSQL 如何在这个相关答案中处理时间戳。

于 2012-09-18T13:32:37.680 回答