计算每周的星期数

给定一个星期的数字,例如date -u +%W ,你如何计算从星期一开始的那一天?

第40周的rfc-3339输出示例:

 2008-10-06 2008-10-07 2008-10-08 2008-10-09 2008-10-10 2008-10-11 2008-10-12 

PHP

 $week_number = 40; $year = 2008; for($day=1; $day<=7; $day++) { echo date('m/d/Y', strtotime($year."W".$week_number.$day))."\n"; } 

下面的post是因为我是一个白痴谁没有正确地阅读这个问题,但会得到从星期一开始的一个星期的date,给定date,而不是周数。

在PHP中 ,改编自PHPdate手册页上的这篇文章 :

 function week_from_monday($date) { // Assuming $date is in format DD-MM-YYYY list($day, $month, $year) = explode("-", $_REQUEST["date"]); // Get the weekday of the given date $wkday = date('l',mktime('0','0','0', $month, $day, $year)); switch($wkday) { case 'Monday': $numDaysToMon = 0; break; case 'Tuesday': $numDaysToMon = 1; break; case 'Wednesday': $numDaysToMon = 2; break; case 'Thursday': $numDaysToMon = 3; break; case 'Friday': $numDaysToMon = 4; break; case 'Saturday': $numDaysToMon = 5; break; case 'Sunday': $numDaysToMon = 6; break; } // Timestamp of the monday for that week $monday = mktime('0','0','0', $month, $day-$numDaysToMon, $year); $seconds_in_a_day = 86400; // Get date for 7 days from Monday (inclusive) for($i=0; $i<7; $i++) { $dates[$i] = date('Ym-d',$monday+($seconds_in_a_day*$i)); } return $dates; } 

来自week_from_monday('07-10-2008')输出给出:

 Array ( [0] => 2008-10-06 [1] => 2008-10-07 [2] => 2008-10-08 [3] => 2008-10-09 [4] => 2008-10-10 [5] => 2008-10-11 [6] => 2008-10-12 ) 

如果你有Zend Framework,你可以使用Zend_Date类来做到这一点:

 require_once 'Zend/Date.php'; $date = new Zend_Date(); $date->setYear(2008) ->setWeek(40) ->setWeekDay(1); $weekDates = array(); for ($day = 1; $day <= 7; $day++) { if ($day == 1) { // we're already at day 1 } else { // get the next day in the week $date->addDay(1); } $weekDates[] = date('Ym-d', $date->getTimestamp()); } echo '<pre>'; print_r($weekDates); echo '</pre>'; 

由于这个问题和被接受的答案都被公布了,所以DateTime类使得这更简单:

 function daysInWeek($weekNum) { $result = array(); $datetime = new DateTime('00:00:00'); $datetime->setISODate((int)$datetime->format('o'), $weekNum, 1); $interval = new DateInterval('P1D'); $week = new DatePeriod($datetime, $interval, 6); foreach($week as $day){ $result[] = $day->format('D dm YH:i:s'); } return $result; } var_dump(daysInWeek(24)); 

这有利于照顾闰年等。

看到它工作 。 包括1周和53周的困难。

这个计算在很大程度上取决于你住的地方。 例如,在欧洲,我们在星期一开始一周,在美国星期天是一周中的第一天。 在英国,第一周是在1月1日,其他国家从本周的第一周开始第一周。

您可以在http://en.wikipedia.org/wiki/Week#Week_numberfind更多的一般信息;

这个函数会给出find$ date的星期几的时间戳。 如果没有给出$ date,则假定“现在”。 如果您更喜欢可读date到时间戳,请将date格式传递到第二个参数。 如果周一(幸运)没有开始你的一周,那么通过第三个参数的不同日子。

 function week_dates($date = null, $format = null, $start = 'monday') { // is date given? if not, use current time... if(is_null($date)) $date = 'now'; // get the timestamp of the day that started $date's week... $weekstart = strtotime('last '.$start, strtotime($date)); // add 86400 to the timestamp for each day that follows it... for($i = 0; $i < 7; $i++) { $day = $weekstart + (86400 * $i); if(is_null($format)) $dates[$i] = $day; else $dates[$i] = date($format, $day); } return $dates; } 

所以week_dates()应该返回类似于…

 Array ( [0] => 1234155600 [1] => 1234242000 [2] => 1234328400 [3] => 1234414800 [4] => 1234501200 [5] => 1234587600 [6] => 1234674000 ) 
 $week_number = 40; $year = 2008; for($day=1; $day<=7; $day++) { echo date('m/d/Y', strtotime($year."W".$week_number.$day))."\n"; } 

如果$week_number小于10,这将失败。

 //============Try this================// $week_number = 40; $year = 2008; if($week_number < 10){ $week_number = "0".$week_number; } for($day=1; $day<=7; $day++) { echo date('m/d/Y', strtotime($year."W".$week_number.$day))."\n"; } //==============================// 

另嘿嘿:

 public function getAllowedDays($year, $week) { $weekDaysArray = array(); $dto = new \DateTime(); $dto->setISODate($year, $week); for($i = 0; $i < 7; $i++) { array_push($weekDaysArray, $dto->format('Ym-d')); $dto->modify("+1 days"); } return $weekDaysArray; } 

我发现这个解决scheme有问题。 我不得不填补周数,否则它是打破。

现在我的解决scheme如下所示:

 $week_number = 40; $year = 2008; for($day=1; $day<=7; $day++) { echo date('m/d/Y', strtotime($year."W".str_pad($week_number,2,'0',STR_PAD_LEFT).$day))."\n"; } 

对于那些寻找星期几(星期几)(1-52) 从星期天开始,那么这里是我的小工作。 考虑到检查周是在正确的范围内,并填写值1-9保持它的所有工作。

 $week = 2; $year = 2009; $week = (($week >= 1) AND ($week <= 52))?($week-1):(1); $dayrange = array(7,1,2,3,4,5,6); for($count=0; $count<=6; $count++) { $week = ($count == 1)?($week + 1): ($week); $week = str_pad($week,2,'0',STR_PAD_LEFT); echo date('dm Y', strtotime($year."W".$week.($dayrange[$count]))); } 

我有同样的问题,只使用strftime而不是date作为我的出发点,即使用%WI想要知道该周的date范围 – 周一到周日(或实际上任何开始date)从strftime得到一个星期的数字。 审查几个类似的post,特别是尝试了几个上述方法没有让我到我想要的解决scheme。 当然,我可能误解了一些东西,但是我得不到我想要的东西。

因此,我想分享我的解决scheme。

我的第一个想法是,鉴于strftime%W的描述是:

从第一个星期一开始,作为第一周的第一天

如果我确定每年的第一个星期一是什么,我可以计算一个索引值等于%W的date范围数组。 此后,我可以使用strftime调用函数。

所以在这里:

function:

 <?php /* * function to establish scope of week given a week of the year value returned from strftime %W */ // note strftime %W reports 1/1/YYYY as wk 00 unless 1/1/YYYY is a monday when it reports wk 01 // note strtotime Monday [last, this, next] week - runs sun - sat function date_Range_For_Week($W,$Y){ // where $W = %W returned from strftime // $Y = %Y returned from strftime // establish 1st day of 1/1/YYYY $first_Day_Of_Year = mktime(0,0,0,1,1,$Y); // establish the first monday of year after 1/1/YYYY $first_Monday_Of_Year = strtotime("Monday this week",(mktime(0,0,0,1,1,$Y))); // Check for week 00 advance first monday if found // We could use strtotime "Monday next week" or add 604800 seconds to find next monday // I have decided to avoid any potential strtotime overhead and do the arthimetic if (strftime("%W",$first_Monday_Of_Year) != "01"){ $first_Monday_Of_Year += (60 * 60 * 24 * 7); } // create array to ranges for the year. Note 52 wks is the norm but it is possible to have 54 weeks // in a given yr therefore allow for this in array index $week_Start = array(); $week_End = array(); for($i=0;$i<=53;$i++){ if ($i == 0){ if ($first_Day_Of_Year != $first_Monday_Of_Year){ $week_Start[$i] = $first_Day_Of_Year; $week_End[$i] = $first_Monday_Of_Year - (60 * 60 * 24 * 1); } else { // %W returns no week 00 $week_Start[$i] = 0; $week_End[$i] = 0; } $current_Monday = $first_Monday_Of_Year; } else { $week_Start[$i] = $current_Monday; $week_End[$i] = $current_Monday + (60 * 60 * 24 * 6); // find next monday $current_Monday += (60 * 60 * 24 * 7); // test for end of year if (strftime("%W",$current_Monday) == "01"){ $i = 999; }; } }; $result = array("start" => strftime("%a on %d, %b, %Y", $week_Start[$W]), "end" => strftime("%a on %d, %b, %Y", $week_End[$W])); return $result; } ?> 

例:

 // usage example //assume we wish to find the date range of a week for a given date July 12th 2011 $Y = strftime("%Y",mktime(0,0,0,7,12,2011)); $W = strftime("%W",mktime(0,0,0,7,12,2011)); // use dynamic array variable to check if we have range if so get result if not run function $date_Range = date_Range . "$Y"; isset(${$date_Range}) ? null : ${$date_Range} = date_Range_For_Week($W, $Y); echo "Date sought: " . strftime(" was %a on %b %d, %Y, %X time zone: %Z",mktime(0,0,0,7,12,2011)) . "<br/>"; echo "start of week " . $W . " is " . ${$date_Range}["start"] . "<br/>"; echo "end of week " . $W . " is " . ${$date_Range}["end"]; 

输出:

 > Date sought: was Tue on Jul 12, 2011, 00:00:00 time zone: GMT Daylight > Time start of week 28 is Mon on 11, Jul, 2011 end of week 28 is Sun on > 17, Jul, 2011 

我已经testing了几年,包括2018年的第二年,即1/1/2018 =星期一。 迄今似乎提供了正确的date范围。

所以我希望这有助于

问候

另一个scheme

 //$date Date in week //$start Week start (out) //$end Week end (out) function week_bounds($date, &$start, &$end) { $date = strtotime($date); $start = $date; while( date('w', $start)>1 ) { $start -= 86400; } $end = date('Ym-d', $start + (6*86400) ); $start = date('Ym-d', $start); } 

例:

 week_bounds("2014/02/10", $start, $end); echo $start."<br>".$end; 

date:

 2014-02-10 2014-02-16 
 $year = 2016; //enter the year $wk_number = 46; //enter the weak nr $start = new DateTime($year.'-01-01 00:00:00'); $end = new DateTime($year.'-12-31 00:00:00'); $start_date = $start->format('Ymd H:i:s'); $output[0]= $start; $end = $end->format('U'); $x = 1; //create array full of data objects for($i=0;;$i++){ if($i == intval(date('z',$end)) || $i === 365){ break; } $a = new DateTime($start_date); $b = $a->modify('+1 day'); $output[$x]= $a; $start_date = $b->format('Ymd H:i:s'); $x++; } //create a object to use for($i=0;$i<count($output);$i++){ if(intval ($output[$i]->format('W')) === $wk_number){ $output_[$output[$i]->format('N')] = $output[$i]; } } $dayNumberOfWeek = 1; //enter the desired day in 1 = Mon -> 7 = Sun echo '<pre>'; print_r($output_[$dayNumberOfWeek]->format('Ym-d')); echo '</pre>'; 

作为date()PHP的datePHP的对象

  <?php $iWeeksAgo = 5;// need weeks ago $sWeekDayStartOn = 0;// 0 - Sunday, 1 - Monday, 2 - Tuesday $aWeeksDetails = getWeekDetails($iWeeksAgo, $sWeekDayStartOn); print_r($aWeeksDetails); die('end of line of getWeekDetails '); function getWeekDetails($iWeeksAgo, $sWeekDayStartOn){ $date = new DateTime(); $sCurrentDate = $date->format('W, Ymd, w'); #echo 'Current Date (Week of the year, YYYY-MM-DD, day of week ): ' . $sCurrentDate . "\n"; $iWeekOfTheYear = $date->format('W');// Week of the Year ie 19-Feb-2014 = 08 $iDayOfWeek = $date->format('w');// day of week for the current month ie 19-Feb-2014 = 4 $iDayOfMonth = $date->format('d'); // date of the month ie 19-Feb-2014 = 19 $iNoDaysAdd = 6;// number of days adding to get last date of the week ie 19-Feb-2014 + 6 days = 25-Feb-2014 $date->sub(new DateInterval("P{$iDayOfWeek}D"));// getting start date of the week $sStartDateOfWeek = $date->format('Ym-d');// getting start date of the week $date->add(new DateInterval("P{$iNoDaysAdd}D"));// getting end date of the week $sEndDateOfWeek = $date->format('Ym-d');// getting end date of the week $iWeekOfTheYearWeek = (string) $date->format('YW');//week of the year $iWeekOfTheYearWeekWithPeriod = (string) $date->format('Y-W');//week of the year with year //To check uncomment #echo "Start Date / End Date of Current week($iWeekOfTheYearWeek), week with - ($iWeekOfTheYearWeekWithPeriod) : " . $sStartDateOfWeek . ',' . $sEndDateOfWeek . "\n"; $iDaysAgo = ($iWeeksAgo*7) + $iNoDaysAdd + $sWeekDayStartOn;// getting 4 weeks ago ie no. of days to substract $date->sub(new DateInterval("P{$iDaysAgo}D"));// getting 4 weeks ago ie no. of days to substract $sStartDateOfWeekAgo = $date->format('Ym-d');// getting 4 weeks ago start date ie 19-Jan-2014 $date->add(new DateInterval("P{$iNoDaysAdd}D")); // getting 4 weeks ago end date ie 25-Jan-2014 $sEndDateOfWeekAgo = $date->format('Ym-d');// getting 4 weeks ago start date ie 25-Jan-2014 $iProccessedWeekAgoOfTheYear = (string) $date->format('YW');//ago week of the year $iProccessedWeekOfTheYearWeekAgo = (string) $date->format('YW');//ago week of the year with year $iProccessedWeekOfTheYearWeekWithPeriodAgo = (string) $date->format('Y-W');//ago week of the year with year //To check uncomment #echo "Start Date / End Date of week($iProccessedWeekOfTheYearWeekAgo), week with - ($iProccessedWeekOfTheYearWeekWithPeriodAgo) ago: " . $sStartDateOfWeekAgo . ',' . $sEndDateOfWeekAgo . "\n"; $aWeeksDetails = array ('weeksago' => $iWeeksAgo, 'currentweek' => $iWeekOfTheYear, 'currentdate' => $sCurrentDate, 'startdateofcurrentweek' => $sStartDateOfWeek, 'enddateofcurrentweek' => $sEndDateOfWeek, 'weekagoyearweek' => $iProccessedWeekAgoOfTheYear, 'startdateofagoweek' => $sStartDateOfWeekAgo, 'enddateofagoweek' => $sEndDateOfWeekAgo); return $aWeeksDetails; } ?>