Postgresql 营业时间内的时差
我想找出Postgresql 营业时间内的时差,postgresql,datetime,timestamp,date-arithmetic,Postgresql,Datetime,Timestamp,Date Arithmetic,我想找出NOW()和时间戳列之间的时间差。 计算时差时,只需计算从上午9点到下午5点以及工作日的营业时间。 e、 g.对于第一条记录2021-04-21 07:56:36,如果现在是2021-04-21 10:00:00,则必须从上午9点开始计算时差,在这种情况下,结果为1小时,如下所示: (NOW() - created_at) - ('2021-04-21 09:00'::timestamp - created_at) AS timediff 对于具有2021-04-19 21:55:
NOW()
和时间戳列之间的时间差。
计算时差时,只需计算从上午9点到下午5点以及工作日的营业时间。
e、 g.对于第一条记录2021-04-21 07:56:36
,如果现在是2021-04-21 10:00:00
,则必须从上午9点开始计算时差,在这种情况下,结果为1小时,如下所示:
(NOW() - created_at) - ('2021-04-21 09:00'::timestamp - created_at) AS timediff
对于具有2021-04-19 21:55:46
的第二条记录,从2021-04-20 09:00
到2021-04-20 17:00
和2021-04-21 09:00
到2021-04-21 10:00
第三条记录为2021-04-17 14:22:05
,时间为17小时,由8+8+1小时组成
样本数据:
+----------------------------------+---------------------+
| id | created_at |
+----------------------------------+---------------------+
| 9d38ea6e7077400db310cfc47b31d482 | 2021-04-21 07:56:36 |
| 9d38ea6e7077400db310cfc47b31d481 | 2021-04-19 21:55:46 |
| 9d38ea6e7077400db310cfc47b31d480 | 2021-04-17 14:22:05 |
| 9d38ea6e7077400db310cfc47b31d479 | 2021-04-18 22:43:44 |
+----------------------------------+---------------------+
预期结果:
+----------------------------------+---------------------+----------+
| id | created_at | timediff |
+----------------------------------+---------------------+----------+
| 9d38ea6e7077400db310cfc47b31d482 | 2021-04-21 07:56:36 | 01:00:00 |
| 9d38ea6e7077400db310cfc47b31d481 | 2021-04-19 21:55:46 | 09:00:00 |
| 9d38ea6e7077400db310cfc47b31d480 | 2021-04-17 14:22:05 | 17:00:00 |
| 9d38ea6e7077400db310cfc47b31d479 | 2021-04-18 22:43:44 | 17:00:00 |
+----------------------------------+---------------------+----------+
我建议生成在创建的
和当前时间戳之间的所有工作时间范围,并将它们相加。虽然就性能而言,这远不是最佳解决方案,但我认为这是最直接的方法。
我使用带有时区范围和交叉点的时间戳
请参见中的设置和示例
警告
虽然实现很容易理解和调试,但它可能会导致性能低下,尤其是在与非常旧的创建的_一起使用时。如果您的系统中可能存在这种情况,您最好编写一个函数,检查创建的_的星期几和当前的_日期,查找它们之间的天数并确定工作时间
SELECT id,
created_at,
SUM(upper(business_range) - lower(business_range) ) business_hours
FROM (
SELECT id,
created_at,
tstzrange(date_in_range + '09:00'::time with time zone, date_in_range + '17:00'::time with time zone)
* tstzrange(created_at, current_timestamp) as business_range
FROM (
SELECT id,
created_at,
created_at::date + generate_series(0, current_timestamp::date - created_at::date) as date_in_range
FROM times
) dates_in_range
WHERE date_part('dow', date_in_range) in (1,2,3,4,5)
) business_hour_ranges
GROUP BY
id,
created_at