给定一个星期数,例如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";
}
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('Y-m-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 框架,你可以使用 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('Y-m-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 d m Y H:i:s');
}
return $result;
}
var_dump(daysInWeek(24));
这具有照顾闰年等的额外优势。
看到它工作。包括艰难的第 1 周和第 53 周。
此计算在很大程度上取决于您居住的地方。例如,在欧洲,我们从星期一开始一周,在美国,星期日是一周的第一天。在英国,第 1 周是 1 月 1 日,其他国家/地区从包含一年中第一个星期四的那周开始第 1 周。
此函数将给出找到 $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('Y-m-d'));
$dto->modify("+1 days");
}
return $weekDaysArray;
}
我发现这个解决方案有问题。我必须将周数填零,否则它会中断。
我的解决方案现在看起来像这样:
$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('d m Y', strtotime($year."W".$week.($dayrange[$count]))); }
我有同样的问题,只使用 strftime 而不是日期作为我的起点,即使用 %WI 从 strftime 导出周数想知道该周的日期范围 - 周一到周日(或实际上任何起始日)。对几个类似帖子的评论,特别是尝试了上述几种方法并没有让我得到我想要的解决方案。当然,我可能误解了一些东西,但我无法得到我想要的东西。
因此,我想分享我的解决方案。
我的第一个想法是,鉴于 strftime %W 的描述是:
当年的周数,从第一个星期一开始作为第一周的第一天
如果我确定每年的第一个星期一是什么,我可以计算一个日期范围数组,其索引等于 %W 的值。此后我可以使用 strftime 调用该函数。
所以这里是:
功能:
<?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
我已经测试了几年,包括 2018 年,即 2018 年 1 月 1 日 = 星期一的下一年。到目前为止,似乎提供了正确的日期范围。
所以我希望这会有所帮助。
问候
另一种解决方案:
//$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('Y-m-d', $start + (6*86400) );
$start = date('Y-m-d', $start);
}
例子:
week_bounds("2014/02/10", $start, $end);
echo $start."<br>".$end;
出去:
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('Y-m-d 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('Y-m-d 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('Y-m-d'));
echo '</pre>';
用作来自 php 日期 php的 date() 对象
基于周数和天数的周期
一些国家(如斯堪的纳维亚国家和德国)使用周数,作为预订假期、会议等的实用方式。此功能可以根据周数开始日期和周期长度(以天为单位)发送有关周期的文本消息。
function MakePeriod($year,$Week,$StartDay,$NumberOfDays, $lan='DK'){
//Please note that start dates in january of week 53 must be entered as "the year before"
switch($lan){
case "NO":
$WeekDays=['mandag','tirsdag','onsdag','torsdag','fredag','lørdag','søndag'];
$the=" den ";
$weekName="Uke ";
$dateformat="j/n Y";
break;
case "DK":
$WeekDays=['mandag','tirsdag','onsdag','torsdag','fredag','lørdag','søndag'];
$the=" den ";
$weekName="Uge ";
$dateformat="j/n Y";
break;
case "SV":
$WeekDays=['måndag','tisdag','onsdag','torsdag','fredag','lördag','söndag'];
$the=" den ";
$weekName="Vecka ";
$dateformat="j/n Y";
break;
case "GE":
$WeekDays=['Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag','Sonntag'];
$the=" die ";
$weekName="Woche ";
$dateformat="j/n Y";
break;
case "EN":
case "US":
$WeekDays=['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'];
$the=" the ";
$weekName="Week ";
$dateformat="n/j/Y";
break;
}
$EndDay= (($StartDay-1+$NumberOfDays) % 7)+1;
$ExtraDays= $NumberOfDays % 7;
$FirstWeek=$Week;
$LastWeek=$Week;
$NumberOfWeeks=floor($NumberOfDays / 7) ;
$LastWeek=$Week+$NumberOfWeeks;
if($StartDay+$ExtraDays>7){
$LastWeek++;
}
if($FirstWeek<10) $FirstWeek='0'.$FirstWeek;
if($LastWeek<10) $LastWeek='0'.$LastWeek;
$date1 = date( $dateformat, strtotime($year."W".$FirstWeek.$StartDay) ); // First day of week
$date2 = date( $dateformat, strtotime($year."W".$LastWeek.$EndDay) ); // Last day of week
if($LastWeek>53){
$LastWeek=$LastWeek-53;
$year++;
if($LastWeek<10) $LastWeek='0'.$LastWeek;
$date2 = date( $dateformat, strtotime($year."W".$LastWeek.$EndDay) );
}
$EndDayName=$WeekDays[$EndDay-1];
$StartDayName=$WeekDays[$StartDay-1];
$retval= " $weekName $Week $StartDayName $the $date1 - $EndDayName $the $date2 ";
return $retval;
}
测试:
$Year=2021;
$Week=22;
$StartDay=4;
$NumberOfDays=3;
$Period=MakePeriod($Year,$Week,$StartDay,$NumberOfDays,"DK");
echo $Period;
Uge 22 torsdag den 3/6 2021 - søndag den 6/6 2021
<?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, Y-m-d, w');
#echo 'Current Date (Week of the year, YYYY-MM-DD, day of week ): ' . $sCurrentDate . "\n";
$iWeekOfTheYear = $date->format('W');// Week of the Year i.e. 19-Feb-2014 = 08
$iDayOfWeek = $date->format('w');// day of week for the current month i.e. 19-Feb-2014 = 4
$iDayOfMonth = $date->format('d'); // date of the month i.e. 19-Feb-2014 = 19
$iNoDaysAdd = 6;// number of days adding to get last date of the week i.e. 19-Feb-2014 + 6 days = 25-Feb-2014
$date->sub(new DateInterval("P{$iDayOfWeek}D"));// getting start date of the week
$sStartDateOfWeek = $date->format('Y-m-d');// getting start date of the week
$date->add(new DateInterval("P{$iNoDaysAdd}D"));// getting end date of the week
$sEndDateOfWeek = $date->format('Y-m-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 i.e. no. of days to substract
$date->sub(new DateInterval("P{$iDaysAgo}D"));// getting 4 weeks ago i.e. no. of days to substract
$sStartDateOfWeekAgo = $date->format('Y-m-d');// getting 4 weeks ago start date i.e. 19-Jan-2014
$date->add(new DateInterval("P{$iNoDaysAdd}D")); // getting 4 weeks ago end date i.e. 25-Jan-2014
$sEndDateOfWeekAgo = $date->format('Y-m-d');// getting 4 weeks ago start date i.e. 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;
}
?>