计算 n 天,跳过指定日期
Posted
技术标签:
【中文标题】计算 n 天,跳过指定日期【英文标题】:Count n days, skipping specified dates 【发布时间】:2012-03-27 13:07:12 【问题描述】:我正在尝试找出计算从现在起 n 天后哪一天的最佳方法,但不包括某些日期(邮政服务节假日/星期日)。
例如,从 12 月 20 日开始的 5 天: 12 月 21 日 = 1 12 月 22 日 = 2 12 月 23 日 = 跳过(星期日) 12 月 24 日 = 3 12 月 25 日 = 跳过(圣诞节) 12 月 26 日 = 4 12 月 27 日 = 5我的设置将是一个包含开始日期的表格,一个用于确定每种类型记录应计算的天数的表格,以及一个列出应从计数中排除的天数的表格(周日不包含在此列表中)。
【问题讨论】:
【参考方案1】:你可以写一个存储函数-
CREATE FUNCTION find_a_day(start_date DATE, n INT)
RETURNS date
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE end_date DATE DEFAULT start_date;
WHILE i < n DO
SET end_date = end_date + INTERVAL 1 DAY;
-- Create 'holidays' table!
SELECT COUNT(*) INTO @holydays FROM holidays WHERE date = end_date;
IF @holydays = 0 AND DAYOFWEEK(end_date) <> 1 THEN
SET i = i + 1;
END IF;
END WHILE;
RETURN end_date;
END
创建一个包含 Postal Service 假期的 holydays
表。
【讨论】:
这非常有效。有大量记录可能会有点慢,但它允许我在一个简单的函数中使用内置的日期功能。谢谢! 您应该能够通过首先计算日期范围来提高性能:Start-date
到 End-date = Start-date + n days
。将i
设置为n
减去开始日期和结束日期之间的跳过天数(一次命中数据库)。按原样运行循环的其余部分。迭代次数和后续数据库命中数现在限制为跳过的天数。【参考方案2】:
当然,“最佳”方式取决于您的实施环境。
(1) 如果您的开始日期较少,您可以按照您现在所遵循的路线进行。
for each startingDate
counter = 0
advanceDate = startingDate
do while counter < nOfBusinessDays
advanceDate = advanceDate.addDays(1) # whatever your environment provides for date arithmetic
if advanceDate is found in tableOfSundays # see (a) below
continue
if advanceDate is found in tableOfHolidays
continue
counter++
end do while
# advanceDate is nOfBusinessDays later than startingDate
end for each
(a) 如果您的日期算术包提供星期几功能,您可以将其用于星期日测试。
(2) 如果您有很多需要评估的开始日期,和/或您将重复计算相同的日期加天数,您可以预先计算一个工作日地图。该地图将涵盖表格中最早开始日期和最晚开始日期之间的时间跨度,加上要计算的最大工作日数以及任何中间的星期日和节假日。将地图实现为按日期升序排列的普通数组。那么从开始日期算起工作日只是数组索引的问题。
(3) 您可以实现混合解决方案,使用方法 (1) 开始,然后在方法 (2) 映射中缓存答案。 (这解决了如何找出地图中最近一天应该是什么的边界问题。)
【讨论】:
我想我应该澄清一下数量。通过这个,我可能每天运行 100,000 或更多。它们将在导入时或节假日更新时计算。我认为最简单的方法就是生成一个表格,其中包含最早日期和超出此应用程序生命周期的某些日期之间的所有天数(如您的选项 #2),并标记要跳过的日期。我觉得我通过绕过内置的日期函数来重新发明***,虽然......以上是关于计算 n 天,跳过指定日期的主要内容,如果未能解决你的问题,请参考以下文章