从给定的日期查找以前的三个工作日 [英] Find three previous working days from a given date

查看:101
本文介绍了从给定的日期查找以前的三个工作日的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从给定的日期起,我需要找到三个工作日,省略周末和假期。这本身并不是一项艰巨的任务,但似乎我会这样做的方式过于复杂,所以我以为我会先征询你的意见。



为了使事情更有趣,让我们来做一个比赛。我提供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>


http://codepad.org/ uSYiIu5w







最终解决方案 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:

http://codepad.org/uSYiIu5w


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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆