【问题标题】:MySQL: Calculate the difference between Date/Times - only during M-F "Work week"MySQL:计算日期/时间之间的差异 - 仅在 M-F“工作周”期间
【发布时间】:2011-01-14 10:04:39
【问题描述】:

我需要计算开始日期/时间和结束日期/时间之间的差异。但是,我只想在为期 5 天的工作周中执行此操作(不包括周六/周日)。做这个的最好方式是什么?我的想法是,从日期开始,我必须得到星期几,如果是工作日,那么我添加到累加器中。如果不是,那我什么都不加。

我确定以前有人这样做过,但我似乎找不到任何搜索结果。任何链接或其他帮助都会非常有用。

非常感谢,

布鲁斯

【问题讨论】:

  • 哦,我应该包括一点背景知识:本质上,我正在使用 PHP 和 MySQL 将 Excel 电子表格转换为基于 Web 的数据库。我需要 MySQL 等效的 'NETWORKDAYS()' 函数。所以,如果这不能在 MySQL 中完成,我可以在 PHP 端完成。

标签: php mysql datetime


【解决方案1】:

DAYOFWEEK 返回 1 表示周日,7 表示周六。我不确定您的架构是如何设置的,但这将执行周一至周五工作周的两个日期的 TIMEDIFF。

select TIMEDIFF(date1,date2) from table 
where DAYOFWEEK(date1) not in (1,7) and DAYOFWEEK(date2) not in (1,7)

MySQL DATE/TIME functions

编辑:来自布鲁斯关于假期的评论。如果您有一个充满假期日期的表格,那么这样的事情可以排除那些日子的处理:

select TIMEDIFF(date1,date2) from table 
where date1 not in (select holiday from holiday_table) and
date2 not in (select holiday from holiday_table) and
DAYOFWEEK(date1) not in (1,7) and DAYOFWEEK(date2) not in (1,7)

【讨论】:

  • 哇,谢谢你的快速回答,特雷弗!看起来这样就可以了!
  • 是的,我会接受答案 - 今晚或明天早上将对其进行测试。我也在考虑加入一个单独的“日历”表。由于我们已经使用了一个基于 Web 的日历,并且输入了所有的假期,这个特殊的应用程序也可以利用它,因为假期也不被认为是“工作日”。你会怎么做这样的事情?一个子选择?我可能会使用 MySQL 存储函数。我只是想确保它在未来是可移植的。我看到 MySQL 的存储函数大多是标准的,以防我们不得不移动到另一个数据库。
  • 我一直在 MySQL 3.23.58 和 4.1 中使用 PHP 4.0.6 进行编码(所有从未见过网络的内部应用程序,并且前面有 mod_security)所有这些“新” MySQL 的特性(无论如何对我们来说)都很好,我想确保我们设计的东西在未来只需要很少的改动就可以工作。
  • 我接受了这个答案,下面的答案也值得称赞,但我先答应过你:-)
【解决方案2】:

NETWORKDAYS() “返回 start_date 和 end_date 之间的整个工作日数。工作日不包括周末和假日中标识的任何日期。使用 NETWORKDAYS 计算基于特定期限内工作天数的员工福利。 "根据 Excel 2007 帮助文件。

“介于”描述有点不准确,因为它包含了开始和结束日期,即 networkdays(21-01-2010. 22-01-2010) = 2。它也没有考虑时间。

这是 PHP 中的一个函数,它会给出相同的结果。如果结束日期小于开始日期,它就不能正常工作,也不会对假期做任何事情(见下面的函数)。

function networkdays($startdate, $enddate)
  {
     $start_array = getdate(strtotime($startdate));
     $end_array = getdate(strtotime($enddate));

     // Make appropriate Sundays
     $start_sunday = mktime(0, 0, 0, $start_array[mon], $start_array[mday]+(7-$start_array[wday]),$start_array[year]);
     $end_sunday = mktime(0, 0, 0, $end_array[mon], $end_array[mday]- $end_array[wday],$end_array[year]);

     // Calculate days in the whole weeks
     $week_diff = $end_sunday - $start_sunday;
     $number_of_weeks = round($week_diff /604800); // 60 seconds * 60 minutes * 24 hours * 7 days = 1 week in seconds
     $days_in_whole_weeks = $number_of_weeks * 5;

     //Calculate extra days at start and end
     //[wday] is 0 (Sunday) to 7 (Saturday)
     $days_at_start = 6 - $start_array[wday];
     $days_at_end = $end_array[wday];

     $total_days = $days_in_whole_weeks + $days_at_start + $days_at_end;

     return $total_days;
}

要考虑假期,您必须使用此函数计算天数,然后使用类似的查询

Select count (holiday_date) from holidays
where holiday_date between start_date and end_date
and DAYOFWEEK(holiday_date) not in (1,7)

请注意,将 end_date 视为 00:00(即早上的第一件事)没有问题 - 您可能必须将其设置为 23:59:59 才能正常工作。这完全取决于您的假期是如何存储的。

返回同一时间段的假期,然后从您首先想到的数字中减去。

【讨论】:

  • Kevin - 这是解决这个问题的另一种好方法,它是基于 PHP 的,所以我真的很感激。我希望我可以将其标记为可接受的答案,但我已经向 Trevor 承诺了基于 MySQL 的答案。太糟糕了,我不能同时接受它们,因为从技术上讲,它们都解决了我的问题。非常感谢,布鲁斯
  • 谢谢布鲁斯,但我不确定第一个答案是否适合您的需要。它所做的是选择不是周末的日子,并计算它们之间的所有日子。 NETWORKDAYS() 计算 2 个日期的非周末天数,这是不一样的。例如,如果您想要 NETWORKDAYS(6-feb-2010, 13-feb-2010) (应该是 5),第一个答案将返回一个空结果集,因为两个日期都是星期六。它似乎在 838:59:59 或 35 天时耗尽了动力。没有尝试您的解决方案 Trevor,只是不要认为这是所要求的。
  • 好的,我明白了。还有一个问题:如果我需要包括小时数,并以小时为单位显示结果(例如,开始时间是星期五早上 8 点,结束时间是星期二早上 8 点,结果应该是 48.0 小时)我需要以十分之一显示结果一个小时。因此,如果开始是星期五 8a,结束是星期五下午 5:30,那么结果将是 9.5 小时。我该怎么做?
  • 我给你的代码的天数版本你的时间是 0 小时 0 分钟 0 秒。您可能会从 24 小时中减去开始时间,并添加结束时间的时间部分并将它们添加到天数中。如果开始和结束在同一天,这可能会出现问题。一个额外的转折是不得不担心夏令时。您可能需要在午夜和开始/结束时间之间使用 timediff() 之类的东西来确保它被拾取。
猜你喜欢
  • 1970-01-01
  • 2012-06-10
  • 2010-11-07
  • 2021-11-25
  • 2011-08-01
  • 2016-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多