Get the First or Last Friday in a Month

后端 未结 12 2262
有刺的猬
有刺的猬 2020-11-29 12:12

I\'m trying to write a calendar function like this

function get_date($month, $year, $week, $day, $direction)
{
    ....
}

$week

相关标签:
12条回答
  • 2020-11-29 12:47

    This seems to work perfect everytime; it takes any date provided and returns the date of the last friday of the month, even in case of 5 friday in the month.

    function get_last_friday_of_month($inDate) {
        $inDate = date('Y-m-24', strtotime($inDate));
        $last_friday = date('Y-m-d',strtotime($inDate.' next friday'));
        $next_friday = date('Y-m-d',strtotime($inDate.' next friday'));
    
        if(date('m', strtotime($last_friday)) === date('m', strtotime($next_friday))){
            $last_friday = $next_friday;
        }else{
            //
        }
        return $last_friday;
    }
    
    0 讨论(0)
  • 2020-11-29 12:49

    Perhaps it can be made quicker...
    This was VERY interesting to code.

    Please note that $direction is 1 for forward and -1 for backward to ease things up :)
    Also, $day begins with a value of 1 for Monday and ends at 7 for Sunday.

    function get_date($month, $year, $week, $day, $direction) {
      if($direction > 0)
        $startday = 1;
      else
        $startday = date('t', mktime(0, 0, 0, $month, 1, $year));
    
      $start = mktime(0, 0, 0, $month, $startday, $year);
      $weekday = date('N', $start);
    
      if($direction * $day >= $direction * $weekday)
        $offset = -$direction * 7;
      else
        $offset = 0;
    
      $offset += $direction * ($week * 7) + ($day - $weekday);
      return mktime(0, 0, 0, $month, $startday + $offset, $year);
    }
    

    I've tested it with a few examples and seems to work always, be sure to double-check it though ;)

    0 讨论(0)
  • 2020-11-29 12:50
    function get_date($month, $year, $week, $day) {
        # $month, $year: current month to search in
        # $week: 0=1st, 1=2nd, 2=3rd, 3=4th, -1=last
        # $day:  0=mon, 1=tue, ..., 6=sun
    
        $startday=1; $delta=0;
        if ($week < 0) {
            $startday = date('t', mktime(0, 0, 0, $month, 1, $year)); # 28..31
            $delta=1;
        }
        $start  = mktime(0, 0, 0, $month, $startday, $year);
        $dstart = date('w', $start)-1; # last of the month falls on 0=mon,6=sun
        $offset=$day-$dstart; if ($offset<$delta){$offset+=7;}
        $newday=$startday+$offset+($week*7);
        return mktime(0, 0, 0, $month, $newday, $year);
    }
    

    This works for me, and based on the language-agnostic version :-) Only too bad, I needed to do that delta-thing (for if the last day of the month is the wanted week-day, we do not need to subtract 7)

    0 讨论(0)
  • 2020-11-29 12:52

    The language-agnostic version:

    To get the first particular day of the month, start with the first day of the month: yyyy-mm-01. Use whatever function is available to give a number corresponding to the day of the week. Subtract that number from the day you are looking for; for example, if the first day of the month is Wednesday (2) and you're looking for Friday (4), subtract 2 from 4, leaving 2. If the answer is negative, add 7. Finally add that to the first of the month; for my example, the first Friday would be the 3rd.

    To get the last Friday of the month, find the first Friday of the next month and subtract 7 days.

    0 讨论(0)
  • 2020-11-29 12:56

    Below is the quickest solution and you can use in all conditions. Also you could get an array of all day of week if you tweak it a bit.

    function findDate($date, $week, $weekday){
        # $date is the date we are using to get the month and year which should be a datetime object
        # $week can be: 0 for first, 1 for second, 2 for third, 3 for fourth and -1 for last
        # $weekday can be: 1 for Monday, 2 for Tuesday, 3 for Wednesday, 4 for Thursday, 5 for Friday, 6 for Saturday and 7 for Sunday 
    
        $start = clone $date;
        $finish = clone $date;
    
        $start->modify('first day of this month');
        $finish->modify('last day of this month');
        $finish->modify('+1 day');
    
        $interval = DateInterval::createFromDateString('1 day');
        $period = new DatePeriod($start, $interval, $finish);
    
        foreach($period AS $date){
            $result[$date->format('N')][] = $date;
        }
    
        if($week == -1)
            return end($result[$weekday]);
        else
            return $result[$weekday][$week];
    }
    
    
    $date = DateTime::createFromFormat('d/m/Y', '25/12/2016');
    
    # find the third Wednesday in December 2016
    $result = findDate($date, 2, 3); 
    echo $result->format('d/m/Y');
    

    I hope this helps.

    Let me know if you need any further info. ;)

    0 讨论(0)
  • 2020-11-29 12:57

    You can use mktime to retrieve the unix timestamp of the first day in the month:

    $firstOfMonth = mktime(0, 0, 0, $month, 1, $year);
    

    When you have the date of the first day of a certain month it's easy to retrieve the weekday for that date using date:

    $weekday = date("N", $firstOfMonth);
    

    From there it's rather easy to just step forward to get the date you're after.

    0 讨论(0)
提交回复
热议问题