根据周数计算星期几

30

假设已知一个星期数,例如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
14个回答

64

PHP

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

以下帖子是因为我是个白痴,没有正确阅读问题,但我会在一周内从星期一开始计算日期,而不是周数。
在PHP中,根据这篇帖子PHP日期手册页面上的修改:
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
)

谢谢,今天早上脑袋有点迟钝,没有仔细阅读。回答已更新,使用了更短的代码片段! - ConroyP
真是个惊人的巧合:我在同一周(第40周)三年后读到了这篇文章,哈哈哈。 - Jorge Guberte
当我运行你的示例时,我只得到了1999年以来的日期。 - Jonathan Clark
这是顶部搜索结果,所以我想发出一个警告。如果您使用已发布的代码片段(使用strtotime($year."W".$week_number.$day)),您将在年底获得意外的结果。 - arnaslu
如之前所述,这段代码存在一些问题。我在我的回答中发布了更可靠的代码(https://dev59.com/lXVC5IYBdhLWcg3wykQt#17065451)。 - vascowhite
显示剩余7条评论

7
自从这个问题和被接受的答案发布后,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周。


不幸的是,这并不起作用,因为setISODate()包括一个时间部分,等于今天的时间(即不是0:00:00)。将其更改为$result[] = $day->format('r');,你就会明白我在说什么了。 - Dalin
2
@Dalin 我不明白这意味着它为什么不能工作。原帖从未提到过一天中的时间,只是想要日期。然而,对代码进行小修改可以将所有时间重置为00:00:00。 - vascowhite

7
如果您使用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('Y-m-d', $date->getTimestamp());
}

echo '<pre>';
print_r($weekDates);
echo '</pre>';

4

这个计算方式因所在地的不同而有很大变化。例如,在欧洲,我们将星期从周一开始计算;在美国,星期日是一周的第一天;在英国,第1周是从1月1日开始计算的;其他国家则是以包含当年第一个星期四的那一周作为第1周。

您可以在http://en.wikipedia.org/wiki/Week#Week_number上找到更多一般性的信息。


2
$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";
}

//==============================//

这应该是被接受的答案,因为它可以正常工作! - user3676604

2

这个函数将返回$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
)

如果当天是星期一,这个函数将无法正常工作!请修复它:if($currDay == 'Monday'){ $weekstart = strtotime("midnight",$date); }else{ $weekstart = strtotime('last '.$start, $date); } - FDI

1

另一段代码 hehe:

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

0
$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 的 date() 对象 date php


0

基于周数和天数的时间段

一些国家(如斯堪的纳维亚国家和德国)使用周数作为预订假期、会议等实用的方式。此功能可以根据周数开始日期和周期长度(以天为单位),提供有关该时段的文本消息。

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;

2021年6月3日星期四至2021年6月6日星期日,第22周


0

对于那些想要根据周数(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]))); }

无法返回上一年的日期,对于$week#1。 - temuri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接