问题是不应该考虑公共假期,所以这个答案就是这样做的 - 计算考虑到周末的营业时间,但忽略可能的公共假期。
如果您需要考虑公共假期,您需要有一个单独的表格来列出公共假期的日期,这可能会因年而异,因州而异或因国家而异。主要公式可能保持不变,但您需要从结果中减去在给定日期范围内的公共假期的小时数。
让我们创建一个表,其中包含一些涵盖各种情况的示例数据:
CREATE TABLE T (CreatedDate datetime, UpdatedDate datetime);
INSERT INTO T VALUES
('2012-03-05 09:00:00', '2012-03-05 15:00:00'), -- simple part of the same day
('2012-03-05 10:00:00', '2012-03-06 10:00:00'), -- full day across the midnight
('2012-03-05 11:00:00', '2012-03-06 10:00:00'), -- less than a day across the midnight
('2012-03-05 10:00:00', '2012-03-06 15:00:00'), -- more than a day across the midnight
('2012-03-09 16:00:00', '2012-03-12 10:00:00'), -- over the weekend, less than 7 days
('2012-03-06 16:00:00', '2012-03-15 10:00:00'), -- over the weekend, more than 7 days
('2012-03-09 16:00:00', '2012-03-19 10:00:00'); -- over two weekends
在 MS SQL Server 中,我使用以下公式:
SELECT
CreatedDate,
UpdatedDate,
DATEDIFF(minute, CreatedDate, UpdatedDate)/60.0 -
DATEDIFF(day, CreatedDate, UpdatedDate)*16 -
DATEDIFF(week, CreatedDate, UpdatedDate)*16 AS BusinessHours
FROM T
这会产生以下结果:
+-------------------------+-------------------------+---------------+
| CreatedDate | UpdatedDate | BusinessHours |
+-------------------------+-------------------------+---------------+
| 2012-03-05 09:00:00 | 2012-03-05 15:00:00 | 6 |
| 2012-03-05 10:00:00 | 2012-03-06 10:00:00 | 8 |
| 2012-03-05 11:00:00 | 2012-03-06 10:00:00 | 7 |
| 2012-03-05 10:00:00 | 2012-03-06 15:00:00 | 13 |
| 2012-03-09 16:00:00 | 2012-03-12 10:00:00 | 2 |
| 2012-03-06 16:00:00 | 2012-03-15 10:00:00 | 50 |
| 2012-03-09 16:00:00 | 2012-03-19 10:00:00 | 42 |
+-------------------------+-------------------------+---------------+
它可以工作,因为在 SQL Server 中,返回指定startdate和enddate之间跨越的指定datepartDATEDIFF
边界的计数。
每天有 8 个工作时间。我计算两个日期之间的总小时数,然后减去午夜数乘以每天 16 个非营业时间,然后减去周末数乘以 16(周六 + 周日为 8 + 8 个营业时间)。
它还假设给定的开始和结束日期/时间是在工作时间内。
在 MySQL 中,最接近的等价物是TIMESTAMPDIFF
,但它的工作方式不同。它有效地计算以秒为单位的差异,并除以(丢弃小数部分)所选单位的秒数。
所以,为了得到我们需要的结果,我们可以计算TIMESTAMPDIFF
一些锚日期时间和CreatedDate
和而不是直接计算和UpdatedDate
之间的差异。CreatedDate
UpdatedDate
我选择2000-01-03 00:00:00
了星期一。您可以选择任何其他周一(或周日,如果您的一周从周日开始)午夜作为锚定日期。
MySQL 查询变为(参见SQL Fiddle):
SELECT
CreatedDate,
UpdatedDate,
TIMESTAMPDIFF(MINUTE, CreatedDate, UpdatedDate)/60.0 -
16*(
TIMESTAMPDIFF(DAY, '2000-01-03',UpdatedDate)-
TIMESTAMPDIFF(DAY, '2000-01-03',CreatedDate)
) -
16*(
TIMESTAMPDIFF(WEEK, '2000-01-03',UpdatedDate)-
TIMESTAMPDIFF(WEEK, '2000-01-03',CreatedDate)
) AS BusinessHours
FROM T