2009-05-29 35 views
10

Tôi đang cố gắng để viết một hàm lịch như thế nàyLấy Đầu tiên hoặc Thứ sáu tuần trước trong một tháng

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

$week là một số nguyên (1, 2, 3 ...), $ ngày là một ngày (Sun, Mon, ...) hoặc số, tùy theo điều nào dễ dàng hơn. Hướng là một chút khó hiểu, bởi vì nó thực hiện một phép tính khác.

Đối với một ví dụ, chúng ta hãy gọi

get_date(5, 2009, 1, 'Sun', 'forward');

Nó sử dụng mặc định, và được Chúa Nhật đầu tiên vào tháng tức là 2009/05/03. Nếu chúng ta gọi là

get_date(5, 2009, 2, 'Sun', 'backward');

, nó sẽ trả Chủ Nhật cuối cùng thứ hai của tháng tức là 2009/05/24.

+0

Chỉ vì lợi ích của sự tò mò .. Bạn đang sử dụng nó để làm gì ?! Nó không đơn giản như vậy nhưng có thể được thực hiện anyway. – MartinodF

+0

Tôi đang viết lịch biểu công việc. Một số vị trí là hàng tháng và tôi cần có khả năng xác định ngày nào sẽ hiển thị chúng trong lịch. – Zahymaka

+0

Đã viết xuống cho bạn, hy vọng nó hoạt động như bạn mong đợi! – MartinodF

Trả lời

12

Có lẽ nó có thể được thực hiện nhanh hơn ...
Điều này rất thú vị khi viết mã.

Xin lưu ý rằng $direction là 1 cho phía trước và -1 cho lạc hậu để giảm bớt mọi thứ lên :)
Ngoài ra, $day bắt đầu với một giá trị là 1 thứ Hai và kết thúc lúc 7 cho chủ nhật.

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); 
} 

Tôi đã thử nghiệm nó với một vài ví dụ và dường như làm việc luôn, hãy chắc chắn kiểm tra lại nó dù;)

+0

Oh và cũng lưu ý rằng thứ hai = 1, chủ nhật = 7 – MartinodF

2

Bạn có thể sử dụng mktime để lấy dấu thời gian unix trong ngày đầu tiên trong tháng:

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

Khi bạn có ngày ngày đầu tiên của một tháng nào đó thật dễ dàng để lấy các ngày trong tuần cho ngày đó sử dụng date:

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

Từ đó, bạn chỉ cần tiến lên để có được ngày bạn đang theo dõi.

20

Phiên bản ngôn ngữ-agnostic:

Để có được ngày cụ thể đầu tiên của tháng, bắt đầu với những ngày đầu tiên của tháng: yyyy-mm-01. Sử dụng bất kỳ chức năng có sẵn để cung cấp cho một số tương ứng với ngày trong tuần. Trừ số đó ra khỏi ngày bạn đang tìm kiếm; ví dụ: nếu ngày đầu tiên của tháng là Thứ Tư (2) và bạn đang tìm kiếm Thứ Sáu (4), trừ 2 từ 4, còn lại 2. Nếu câu trả lời là số âm, hãy thêm 7. Cuối cùng, thêm số đó vào đầu tiên của tháng; cho ví dụ của tôi, thứ Sáu đầu tiên sẽ là thứ ba.

Để nhận được thứ Sáu cuối cùng của tháng, hãy tìm thứ Sáu đầu tiên của tháng tiếp theo và trừ 7 ngày.

0

Chỉ cần tìm hiểu ngày đầu tiên và ngày cuối cùng của tháng được đề cập là (ngày 1 tháng 5 năm 2009 là ngày thứ Sáu và ngày 31 tháng 5 năm 2009 là chủ nhật) Tôi tin rằng hầu hết các hàm PHP sử dụng Monday = 0, Sunday = 6 , do đó, thứ Sáu = 4, vì vậy bạn biết rằng Chủ Nhật (6) - Thứ Sáu (4) = 2, sau đó 31-2 = 29, có nghĩa là thứ Sáu cuối cùng của tháng này là vào ngày 29. Đối với thứ Sáu đầu tiên, nếu số này là số âm, cộng 7, nếu số là 0, tháng bắt đầu vào thứ Sáu.

8

strtotime() có thể giúp bạn. ví dụ.

<?php 
$tsFirst = strtotime('2009-04-00 next friday'); 
$tsLast = strtotime('2009-05-01 last friday'); 
echo date(DATE_RFC850, $tsFirst), " | ", date(DATE_RFC850, $tsLast);
in
Friday, 03-Apr-09 00:00:00 CEST | Friday, 24-Apr-09 00:00:00 CEST

+0

Tôi đã kiểm tra, nó không hỗ trợ "cuối cùng thứ hai" hoặc tương tự, và nó là cách chậm hơn. – MartinodF

6

Không cần tính toán hoặc vòng - đây là rất dễ dàng để làm với strtotime():

Tìm các thứ N hoặc xảy ra cuối cùng của một ngày cụ thể của một cụ thể một tháng:

///////////////////////////////////////////////////////////////// 
// Quick Code 
///////////////////////////////////////////////////////////////// 

// Convenience mapping. 
$Names = array(0=>"Sun", 1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thu", 5=>"Fri", 6=>"Sat"); 

// Specify what we want 
// In this example, the Second Monday of Next March 
$tsInMonth = strtotime('March'); 
$Day = 1; 
$Ord = 2; 

// The actual calculations 
$ThisMonthTS = strtotime(date("Y-m-01", $tsInMonth)); 
$NextMonthTS = strtotime(date("Y-m-01", strtotime("next month", $tsInMonth))); 
$DateOfInterest = (-1 == $Ord) 
    ? strtotime("last ".$Names[$Day], $NextMonthTS) 
    : strtotime($Names[$Day]." + ".($Ord-1)." weeks", $ThisMonthTS); 


///////////////////////////////////////////////////////////////// 
// Explanation 
///////////////////////////////////////////////////////////////// 

// Specify the month of which we are interested. 
// You can use any timestamp inside that month, I'm using strtotime for convenience. 
$tsInMonth = strtotime('March'); 

// The day of interest, ie: Friday. 
// It can be 0=Sunday through 6=Saturday (Like 'w' from date()). 
$Day = 5; 

// The occurrence of this day in which we are interested. 
// It can be 1, 2, 3, 4 for the first, second, third, and fourth occurrence of the day in question in the month in question. 
// You can also use -1 to fine the LAST occurrence. That will return the fifth occurrence if there is one, else the 4th. 
$Ord = 3; 

//////////////////////////////////////////////////////////////// 
// We now have all the specific values we need. 
// The example values above specify the 3rd friday of next march 
//////////////////////////////////////////////////////////////// 

// We need the day name that corresponds with our day number to pass to strtotime(). 
// This isn't really necessary = we could just specify the string in the first place, but for date calcs, you are more likely to have the day number than the string itself, so this is convenient. 
$Names = array(0=>"Sun", 1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thu", 5=>"Fri", 6=>"Sat"); 

// Calculate the timestamp at midnight of the first of the month in question. 
// Remember $tsInMonth is any date in that month. 
$ThisMonthTS = strtotime(date("Y-m-01", $tsInMonth)); 

// Calculate the timestamp at midnight of the first of the FOLLOWING month. 
// This will be used if we specify -1 for last occurrence. 
$NextMonthTS = strtotime(date("Y-m-01", strtotime("next month", $tsInMonth))); 

// Now we just format the values a bit and pass them to strtotime(). 
// To find the 1,2,3,4th occurrence, we work from the first of the month forward. 
// For the last (-1) occurence,work we work back from the first occurrence of the following month. 
$DateOfInterest = (-1 == $Ord) ? 
    strtotime("last ".$Names[$Day], $NextMonthTS) : // The last occurrence of the day in this month. Calculated as "last dayname" from the first of next month, which will be the last one in this month. 
    strtotime($Names[$Day]." + ".($Ord-1)." weeks", $ThisMonthTS); // From the first of this month, move to "next dayname" which will be the first occurrence, and then move ahead a week for as many additional occurrences as you need. 
+0

Cảm ơn bạn rất nhiều – beardedlinuxgeek

+0

@beardedlinuxgeek - Niềm vui của tôi. – Eli

1
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); 
} 

này làm việc cho tôi, và dựa trên các phiên bản ngôn ngữ-agnostic :-) Chỉ quá xấu, tôi cần phải làm điều đó delta-điều (vì nếu ngày cuối cùng của tháng là ngày trong tuần mong muốn, chúng tôi không cần phải trừ 7)

5

Chức năng thời gian dựng sẵn của PHP làm cho việc này trở nên đơn giản.

http://php.net/manual/en/function.strtotime.php

// Get first Friday of next month. 
$timestamp = strtotime('first fri of next month'); 

// Get second to last Friday of the current month. 
$timestamp = strtotime('last fri of this month -7 days'); 

// Format a timestamp as a human-meaningful string. 
$formattedDate = date('F j, Y', strtotime('first wed of last month')); 

Lưu ý rằng chúng tôi luôn muốn chắc chắn rằng chúng tôi đã xác định múi giờ đúng để sử dụng với strtotime để PHP có một sự hiểu biết về nơi để tính toán dấu thời gian cho tương ứng với múi giờ gì máy nghĩ rằng nó đang ở.

date_default_timezone_set('America/New_York'); 
$formattedDate = date('F j, Y', strtotime('first wed of last month +1 week')); 
4
echo date('Y-m-d',strtotime('last friday')); 
0

cùng thể được thực hiện rất thanh lịch bằng cách sử dụng lớp DateTime.

$time_zone = new DateTimeZone('Europe/Ljubljana'); 

$first_friday_of_this_month = new DateTime('first Friday of this month', $time_zone); 
$last_friday_of_this_month = new DateTime('last Friday of this month', $time_zone); 

echo $first_friday_of_this_month->format('Y-m-d'); # 2015-11-06 
echo $last_friday_of_this_month->format('Y-m-d'); # 2015-11-27 
0

Điều này dường như hoạt động hoàn hảo mọi lúc; phải mất bất kỳ ngày nào được cung cấp và trả về ngày thứ sáu cuối cùng của tháng, ngay cả trong trường hợp thứ 5 thứ sáu trong tháng.

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

Dưới đây là giải pháp nhanh nhất và bạn có thể sử dụng trong mọi điều kiện. Ngoài ra, bạn có thể nhận được một mảng của tất cả các ngày trong tuần nếu bạn tinh chỉnh nó một chút.

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'); 

Tôi hy vọng điều này sẽ hữu ích.

Hãy cho tôi biết nếu bạn cần thêm bất kỳ thông tin nào.

Các vấn đề liên quan