从给定的日期查找以前的三个工作日 [英] Find three previous working days from a given date
问题描述
从给定的日期起,我需要找到三个工作日,省略周末和假期。这本身并不是一项艰巨的任务,但似乎我会这样做的方式过于复杂,所以我以为我会先征询你的意见。
为了使事情更有趣,让我们来做一个比赛。我提供300作为赏金,无论谁提出了符合这个规范的最短,最干净的解决方案:
- 编写一个函数从指定的日期返回三个前一个工作日
- 工作日被定义为不是星期六或星期天的任何一天,而不是假期
- 该函数知道给定日期的年份的假期,并可以考虑这些因素
- 该函数接受一个参数,日期在
Ymd
格式 - 该函数返回一个包含
Ymd
格式的三个日期的数组,从最旧到最新。
额外:
- 该功能还可以找到 next 三个工作日除了前三个
假日数组的一个例子:
$ holidays = array(
'2010-01-01',
'2010-01-06',
'2010-04-02 ',
'2010-04-04',
'2010-04-05',
'2010-05-01',
'2010-05-13'
'2010-05-23',
'2010-06-26',
'2010-11-06',
'2010-12-06',
'2010-12-25',
'2010-12-26'
);
请注意,在实际情况下,假期不是硬编码,但来自 get_holidays($ year)
函数。如果你愿意,你可以在你的答案中加入/使用。
当我提供赏金时,这意味着至少有三天之前我可以标记答复为接受(2天添加赏金,1天直到我可以接受)。
注意
如果您使用固定的日期长度(如86400秒)从一天跳到另一天,则会遇到夏令时问题。使用 strtotime(' - 1天',$ timestamp)
这个问题的一个例子: p>
最终解决方案 p>
这是我最终使用的最终解决方案,改编自Keith Minkler使用 strtotime
的上周末
。检测来自传递的计数的方向,如果为负值,向后搜索,向前搜索正数:
function working_days($ date,$ count){
$ working_days = array();
$ direction = $ count< 0? 'last':'next';
$ holidays = get_holidays(date(Y,strtotime($ date)));
while(count($ working_days)< abs($ count)){
$ date = date(Ymd,strtotime($ direction weekday,strtotime($ date) ));
if(!in_array($ date,$ holidays)){
$ working_days [] = $ date;
}
}
sort($ working_days);
return $ working_days;
}
如下所示:
function last_working_days($ date,$ backwards = true)
{
$ holidays = get_holidays(date(Y,strtotime($ date)));
$ working_days = array();
do
{
$ direction = $ backwards? 'last':'next';
$ date = date(Y-m-d,strtotime($ direction weekday,strtotime($ date)));
if(!in_array($ date,$ holidays))
{
$ working_days [] = $ date;
}
}
while(count($ working_days)< 3);
return $ working_days;
}
I need to find three previous working days from a given date, omitting weekends and holidays. This isn't a hard task in itself, but it seems that the way I was going to do it would be overly complicated, so I thought I'd ask for your opinion first.
To make things more interesting, let's make this a contest. I'm offering 300 as a bounty to whoever comes up with the shortest, cleanest solution that adheres to this specification:
- Write a function that returns three previous working days from a given date
- Working day is defined as any day that is not saturday or sunday and isn't an holiday
- The function knows the holidays for the year of the given date and can take these into account
- The function accepts one parameter, the date, in
Y-m-d
format - The function returns an array with three dates in
Y-m-d
format, sorted from oldest to newest.
Extra:
- The function can find also the next three working days in addition to the previous three
An example of the holidays array:
$holidays = array(
'2010-01-01',
'2010-01-06',
'2010-04-02',
'2010-04-04',
'2010-04-05',
'2010-05-01',
'2010-05-13',
'2010-05-23',
'2010-06-26',
'2010-11-06',
'2010-12-06',
'2010-12-25',
'2010-12-26'
);
Note that in the real scenario, the holidays aren't hardcoded but come from get_holidays($year)
function. You can include / use that in your answer if you wish.
As I'm offering a bounty, that means there will be at least three days before I can mark an answer as accepted (2 days to add a bounty, 1 day until I can accept).
Note
If you use a fixed day length such as 86400 seconds to jump from day to another, you'll run into problems with daylight savings time. Use strtotime('-1 day', $timestamp)
instead.
An example of this problem:
Final solution
Here's the final solution I ended up using, adapted from Keith Minkler's idea of using strtotime
's last weekday
. Detects the direction from the passed count, if negative, searches backwards, and forwards on positive:
function working_days($date, $count) {
$working_days = array();
$direction = $count < 0 ? 'last' : 'next';
$holidays = get_holidays(date("Y", strtotime($date)));
while(count($working_days) < abs($count)) {
$date = date("Y-m-d", strtotime("$direction weekday", strtotime($date)));
if(!in_array($date, $holidays)) {
$working_days[] = $date;
}
}
sort($working_days);
return $working_days;
}
You can use expressions like "last weekday" or "next thursday" in strtotime, such as this:
function last_working_days($date, $backwards = true)
{
$holidays = get_holidays(date("Y", strtotime($date)));
$working_days = array();
do
{
$direction = $backwards ? 'last' : 'next';
$date = date("Y-m-d", strtotime("$direction weekday", strtotime($date)));
if (!in_array($date, $holidays))
{
$working_days[] = $date;
}
}
while (count($working_days) < 3);
return $working_days;
}
这篇关于从给定的日期查找以前的三个工作日的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!