时区感知 postgres 查询为分钟、小时、天创建时间序列

Posted

技术标签:

【中文标题】时区感知 postgres 查询为分钟、小时、天创建时间序列【英文标题】:Timezone aware postgres query create a timeseries for minutes, hours, days 【发布时间】:2016-03-16 13:49:58 【问题描述】:

我很难弄清楚如何处理以下问题:

我们公司正在向社交媒体平台发布帖子。这些帖子一旦成功发布,就会存储在数据库中。

我们希望提供一个仪表板,显示用户在按分钟、小时和天分组的时间段内发布的帖子数量的概览。

我想将结果显示为时间序列图。

这可以正常工作,但是当我在按天进行聚合/分组时必须支持多个时区时,它会变得非常棘手。 (显然午夜前后的帖子属于不同的日子,具体取决于您所在的时区)

我当前的解决方案是使用 rails ActiveRecord 构建 postgres 查询。我面临的问题是我正在努力处理时区转换...... 我也不是特别擅长postgres ... 当前的实现基本上是这样的(我删除了不相关的代码):

Publication.select(                                                                                                                                                         
    %date_trunc('#interval',
      published_at::timestamptz at time zone interval '#time_zone_offset')::timestamptz as time,
      count(published_at))
      .where(%(published_at BETWEEN
          timestamptz '#start_date' AND
          timestamptz '#end_date'))
          .group("1")
          .order('time').limit(LIMIT)

例如:

我在 2016-03-15 10:19:24.219258 发表了一篇文章(这就是它在数据库中的存储方式,因此是 UTC 时间) 我创建以下查询:

SELECT  date_trunc('hour',
      published_at::timestamptz at time zone interval '+01:00')::timestamptz as time,
      count(published_at) FROM "publications" WHERE (published_at BETWEEN
          timestamptz '2016-03-15 10:00:00 +0100' AND
          timestamptz '2016-03-15 12:00:00 +0100') GROUP BY 1 
;

结果:

          time          | count 
------------------------+-------
 2016-03-15 10:00:00+01 |     1
(1 row)

应该是:

时间:“2016-03-15 10:00:00 UTC”或“2016-03-15 11:00:00+01”(我不关心时区表示,但这完全是错误的结果)

有人知道我在这里做错了什么吗?

我遇到的主要问题是我希望能够根据请求查询的用户的时区每天对出版物进行分组/聚合。 我不在乎返回哪个时区,因为前端可以将其转换为用户时区。

我们非常感谢任何反馈、帮助或答案。 非常感谢

【问题讨论】:

您在服务器上配置了什么时区? serverfault.com/questions/554359/… 显示时区:欧洲/维也纳; rails 服务器也配置了维也纳时区 有没有办法在转换到同一时区后存储数据。让生活更轻松? 查询不应依赖于服务器设置的时区。它应该使用用户传递的时区。 数据存储在与postgres服务器相同的时区。 【参考方案1】:

感谢我与devanand 的讨论,一种解决方案是拆分代码并使用问题中使用的查询处理每日间隔。

对于其他时间间隔,我使用以下查询:

    Publication.select(
      %date_trunc('#interval',
      published_at::timestamptz) as time,
      count(published_at))
               .where(%(published_at BETWEEN
          timestamptz '#start_date' AND
          timestamptz '#end_date'))
               .group('1')
               .order('time').limit(LIMIT)

我对解决方案不满意,因为它对我来说更像是一种解决方法

【讨论】:

以上是关于时区感知 postgres 查询为分钟、小时、天创建时间序列的主要内容,如果未能解决你的问题,请参考以下文章

小时,分钟,秒钟是怎么来的

Postgres UTC时区vs当地时区

Postgres本地恢复Heroku备份将日期时间字段提前4小时

joda API 和 UTC 时区的分钟/小时时差错误

时区之间的时差为 1 小时 6 秒

Postgres 时间戳