在 gmt 中生成日期的所有分钟并获取其本地值

Posted

技术标签:

【中文标题】在 gmt 中生成日期的所有分钟并获取其本地值【英文标题】:generate all minute of a date in gmt and get their local value 【发布时间】:2018-07-12 06:48:19 【问题描述】:

我开始相信我所追求的对 postgresql 来说是不可能的:

我想要给定日期的每个 GMT 分钟,并在同一张表中获取它们的本地版本,如 timestamp without time zone

到目前为止,我能够获得 GMT 和一些完全错误的偏移量。 (我无法更改 SET TIME ZONE 'Europe/Paris' 每次尝试注入时区时都会放入 +1h

CREATE TABLE to_do ("id" int, "tz_lib" varchar(16));
CREATE TABLE date_needed ("date_lib" date);

SQL Fiddle

查询 3

insert into t1(id,tz_lib,date_gmt, date_local)
select 
  id,
  tz_lib,
  date_lib + (seq ||'minute')::interval AS date_gmt, 
  (date_lib + (seq ||'minute')::interval) at time zone tz_lib AS date_local
from  date_needed
cross join to_do
cross join generate_series(0,1439) AS seq

Results

| id |           tz_lib |             date_gmt |           date_local |
|----|------------------|----------------------|----------------------|
|  1 | Pacific/Auckland | 2018-01-15T00:00:00Z | 2018-01-14T12:00:00Z |
|  2 |     Europe/Paris | 2018-01-15T00:00:00Z | 2018-01-15T00:00:00Z |
|  3 |   Asia/Hong_Kong | 2018-01-15T00:00:00Z | 2018-01-14T17:00:00Z |
|  1 | Pacific/Auckland | 2018-01-15T00:01:00Z | 2018-01-14T12:01:00Z |
|  2 |     Europe/Paris | 2018-01-15T00:01:00Z | 2018-01-15T00:01:00Z |
|  3 |   Asia/Hong_Kong | 2018-01-15T00:01:00Z | 2018-01-14T17:01:00Z |
|  1 | Pacific/Auckland | 2018-01-15T00:02:00Z | 2018-01-14T12:02:00Z |
|  2 |     Europe/Paris | 2018-01-15T00:02:00Z | 2018-01-15T00:02:00Z |
|  3 |   Asia/Hong_Kong | 2018-01-15T00:02:00Z | 2018-01-14T17:02:00Z |
|  1 | Pacific/Auckland | 2018-01-15T00:03:00Z | 2018-01-14T12:03:00Z |

使用INTERVAL 回答时要小心,因为他们不知道夏令时,并且会在半年内出错(遗憾的是......)



好结果,坏方法:

目前我发现获得例外结果的唯一方法是将服务器时区更改为 GMT 并强制转换 date_local :

但是我不能用这个解决方案来处理我的情况...

查询 1

SET TIME ZONE 'GMT'

insert into t1(id,tz_lib,date_gmt, date_local)
select 
  id,
  tz_lib,
  date_lib + (seq ||'minute')::interval AS date_gmt, 
  (date_lib + (seq ||'minute')::interval)::timestamptz at time zone tz_lib AS date_local
from  date_needed
cross join to_do
cross join generate_series(0,1439) AS seq

结果(和预期结果)

| id |           tz_lib |             date_gmt |           date_local |
|----|------------------|----------------------|----------------------|
|  1 | Pacific/Auckland | 2018-01-15T00:00:00Z | 2018-01-15T13:00:00Z |
|  2 |     Europe/Paris | 2018-01-15T00:00:00Z | 2018-01-15T01:00:00Z |
|  3 |   Asia/Hong_Kong | 2018-01-15T00:00:00Z | 2018-01-15T08:00:00Z |
|  1 | Pacific/Auckland | 2018-01-15T00:01:00Z | 2018-01-15T13:01:00Z |
|  2 |     Europe/Paris | 2018-01-15T00:01:00Z | 2018-01-15T01:01:00Z |
|  3 |   Asia/Hong_Kong | 2018-01-15T00:01:00Z | 2018-01-15T08:01:00Z |
|  1 | Pacific/Auckland | 2018-01-15T00:02:00Z | 2018-01-15T13:02:00Z |
|  2 |     Europe/Paris | 2018-01-15T00:02:00Z | 2018-01-15T01:02:00Z |
|  3 |   Asia/Hong_Kong | 2018-01-15T00:02:00Z | 2018-01-15T08:02:00Z |
|  1 | Pacific/Auckland | 2018-01-15T00:03:00Z | 2018-01-15T13:03:00Z |

【问题讨论】:

这很不清楚。 date_lib 是什么数据类型?运行查询时TimeZone 的设置是什么?您期望的输出是什么? @LaurenzAlbe 检查 sqlfile; date_lib 是一个date 字段,带有'2018-01-15';服务器的时区是'Europe/Paris',正如我在小提琴上设置的那样;预期的输出是最后一个表:每个 GMT 分钟及其对应的本地时间。 sqlfiddle 中的结果看起来正确,因为您的时区设置为 UTC。你有什么问题? @LaurenzAlbe 不是最后一个有效的小提琴,但明确使用了我无法使用的解决方案(将服务器 TZ 更改为 GMT)。第一个:sqlfiddle.com/#!15/8fcca/2 那里你会看到巴黎格林威治标准时间 00:00 给出的本地 00:00 是错误的。 【参考方案1】:

我认为解决方案是在整个过程中使用timestamp without time zone

SELECT to_do.id,
       to_do.tz_lib,
       seq.seq AS date_gmt,
       seq.seq AT TIME ZONE 'UTC' AT TIME ZONE to_do.tz_lib AS date_local
FROM to_do
   CROSS JOIN date_needed
   CROSS JOIN LATERAL
      generate_series(
         date_needed.date_lib::timestamp,
         date_needed.date_lib::timestamp + INTERVAL '1439 minutes',
         INTERVAL '1 minute'
      ) seq;

说明:seq 将传递 UTC 时间戳。通过使用AT TIME ZONE 'UTC',我将其正确转换为timestamp with time zone,并使用第二个AT TIME ZONE,我可以看到当时该时区的时钟显示。

【讨论】:

等等,这似乎有效 o_O ;我很确定我已经尝试过AT TIME ZONE 'UTC' AT TIME ZONE tz_lib 没有任何成功,你能解释一下为什么这个工作吗?我挖掘的越多,我对 pg TZ 处理的理解就越少......(目前+1,我将验证这是否适用于我的真实案例) 我已经添加了解释。 好的,事实上我真的很接近,因为只是在(date_lib + (seq ||'minute')::interval) at time zone 'GMT' at time zone tz_lib AS date_local 中添加 at time zone 'GMT' 给了我很好的结果......在考虑了我的问题之后,我是在当地时间每分钟及其相应的 GMT 之后,但我设法更改您的查询以产生预期的结果,所以请帮我检查一下,非常感谢 ;)

以上是关于在 gmt 中生成日期的所有分钟并获取其本地值的主要内容,如果未能解决你的问题,请参考以下文章

从服务器获取当前日期时间并将其转换为 c# 中的本地时间

获取本地日期和时间 GMT+8

在python中获取给定日期和UTC偏移量的GMT时间

如何在 C# 中拒绝来自客户端的非 UTC/GMT 日期?

用户日期时间设置为 GMT,如何将日期转换为其本地化设置?

如何在 C# 中生成时间和日期并为 mysql 格式化?