在PHP中获取给定周的开始和结束日期

34

我想使用周日作为开始日期和参考日期(例如 $date)来获取一周的日期范围,但我似乎无法弄清楚。

例如,如果我的 $date 是 2009-05-01,那么我将得到 2009-04-26 和 2009-05-02。而 2009-05-10 将产生 2009-05-10 和 2009-05-16。我当前的代码看起来像这样(我不记得从哪里拿来的了,因为我忘记在注释中写下网址):

function x_week_range(&$start_date, &$end_date, $date)
{
    $start_date = '';
    $end_date = '';
    $week = date('W', strtotime($date));
    $week = $week;

    $start_date = $date;

    $i = 0;
    while(date('W', strtotime("-$i day")) >= $week) {
        $start_date = date('Y-m-d', strtotime("-$i day"));
        $i++;
    }

    list($yr, $mo, $da) = explode('-', $start_date);

    $end_date = date('Y-m-d', mktime(0, 0, 0, $mo, $da + 6, $yr));
}

我意识到它所做的只是将当前日期加上7天。你会怎么做?

16个回答

93

我会利用PHP的strtotime函数来优化代码:

function x_week_range(&$start_date, &$end_date, $date) {
    $ts = strtotime($date);
    $start = (date('w', $ts) == 0) ? $ts : strtotime('last sunday', $ts);
    $start_date = date('Y-m-d', $start);
    $end_date = date('Y-m-d', strtotime('next saturday', $start));
}

根据您提供的数据进行了测试,并且运行正常。虽然我不太喜欢你所做的整个引用事情。如果这是我的函数,我会像这样设置:

function x_week_range($date) {
    $ts = strtotime($date);
    $start = (date('w', $ts) == 0) ? $ts : strtotime('last sunday', $ts);
    return array(date('Y-m-d', $start),
                 date('Y-m-d', strtotime('next saturday', $start)));
}

这样调用:

list($start_date, $end_date) = x_week_range('2009-05-10');

我不是很喜欢为这类事情进行数学计算。日期有些棘手,我更喜欢让 PHP 来解决。


2
我使用以下代码获取上个星期日的日期并格式化:date('Y-m-d',strtotime('last sunday')) - John M
3
尝试使用PHP5的DateTime类! - jjwdesign
@John M,看看我下面的评论,关于“上个星期日”如果今天是星期日并且你想要__这个__星期可能会有问题。 - cdmo
如果你想从周一到周日开始计算一周,那么代码需要做一些更改。函数x_week_range($date) { $ts = strtotime($date); $start = (date('w', $ts) == 0) ? $ts : strtotime('monday this week', $ts); return date('Y-m-d', $start).' 到 '.date('Y-m-d', strtotime('sunday this week', $start)); } - Raushan Singh

24

对于仍在使用mktime(),strtotime()和其他PHP函数的人...不妨尝试一下PHP5 DateTime类。起初我也有所犹豫,但它真的很容易使用。别忘了使用clone()来复制你的对象。

编辑:此代码最近已进行修改,以处理当前日期为星期日的情况。在这种情况下,我们必须获取过去的星期六,然后再加一天才能得到星期日。

$dt_min = new DateTime("last saturday"); // Edit
$dt_min->modify('+1 day'); // Edit
$dt_max = clone($dt_min);
$dt_max->modify('+6 days');

然后按你需要的格式进行格式化。

echo 'This Week ('.$dt_min->format('m/d/Y').'-'.$dt_max->format('m/d/Y').')';

请确保在您的代码中尽早设置时区。

date_default_timezone_set('America/New_York');

2
除非我读错了,否则我不确定如果今天是星期日这个逻辑是否能够正常工作。如果今天是星期日并且您创建一个“上个星期日”的DateTime对象,PHP将返回上一个星期日,而不是当前的星期日。所以如果今天的日期是2/28/2016,则上面的代码将输出This week 2/21/2016 - 2/27/2016(实际上是上周)。星期一到星期六会隐藏这个问题。建议使用类似于$dt_min = new DateTime("last Saturday + 24 hour");的方法。 - cdmo

10

据说date()的"w"格式化参数或DateTime对象的format方法会返回一周中的天数(默认情况下,0表示星期日,1表示星期一等)

你可以用这个值从当前日期减去相应天数来找到本周的开始。

$start_date = new DateTime("2009-05-13");
$day_of_week = $start_date->format("w");

$start_date->modify("-$day_of_week day");

$start_date现在将等于那周的星期日,从那里可以加7天得到这一周的末尾或其他需要的日期。


同样的操作也可以使用Date函数完成:$day_of_week = date('w', strtotime($start_date)); $sunday = date('Y-m-d', strtotime('-'.$day_of_week.' days', strtotime($start_date))); - d.raev

4

基于@jjwdesign的回答,我开发了一个使用DateTime类计算特定日期一周的开始和结束的函数。适用于PHP 5.3.0++

不同之处在于您可以将您想要的“开始”日期设置为0(星期一)到6(星期日)之间的任意一天。

以下是该函数:

if(function_exists('grk_Week_Range') === FALSE){
    function grk_Week_Range($DateString, $FirstDay=6){
        #   Valeur par défaut si vide
        if(empty($DateString) === TRUE){
            $DateString = date('Y-m-d');
        }

        #   On va aller chercher le premier jour de la semaine qu'on veut
        $Days = array(
            0 => 'monday',
            1 => 'tuesday',
            2 => 'wednesday',
            3 => 'thursday',
            4 => 'friday',
            5 => 'saturday',
            6 => 'sunday'
        );

        #   On va définir pour de bon le premier jour de la semaine     
        $DT_Min = new DateTime('last '.(isset($Days[$FirstDay]) === TRUE ? $Days[$FirstDay] : $Days[6]).' '.$DateString);
        $DT_Max = clone($DT_Min);

        #   On renvoie les données
        return array(
            $DT_Min->format('Y-m-d'),
            $DT_Max->modify('+6 days')->format('Y-m-d')
        );
    }
}

结果:

print_r(grk_Week_Range('2013-08-11 16:45:32', 0));
print_r(grk_Week_Range('2013-08-11 16:45:32', 1));
print_r(grk_Week_Range('2013-08-11 16:45:32', 2));
print_r(grk_Week_Range('2013-08-11 16:45:32', 3));
print_r(grk_Week_Range('2013-08-11 16:45:32', 4));
print_r(grk_Week_Range('2013-08-11 16:45:32', 5));
print_r(grk_Week_Range('2013-08-11 16:45:32', 6));

Array
(
    [0] => 2013-07-29
    [1] => 2013-08-04
)
Array
(
    [0] => 2013-07-30
    [1] => 2013-08-05
)
Array
(
    [0] => 2013-07-31
    [1] => 2013-08-06
)
Array
(
    [0] => 2013-07-25
    [1] => 2013-07-31
)
Array
(
    [0] => 2013-07-26
    [1] => 2013-08-01
)
Array
(
    [0] => 2013-07-27
    [1] => 2013-08-02
)
Array
(
    [0] => 2013-07-28
    [1] => 2013-08-03
)

该函数可行。谢谢。不过,你的例子有点问题。它的日期是2013年8月11日,那么如何返回7月25日至8月6日的日期范围呢?8月11日不应该在其中吗? - Jarom

3

2
这是我的版本,它使用了类似于Clay的概念:

/**
 * Start of the week
 *
 * 0 = Sun, 1 = Mon, etc.
 */
define( 'WEEK_START', 0 );

/**
 * Determine the start and end dates for
 * the week in which the specified date
 * falls
 *
 * @param $date Date in week
 * @param $start Week start (out)
 * @param $end Week end (out)
 */
function week_bounds( $date, &$start, &$end ) {
    $date = strtotime( $date );
    // Find the start of the week, working backwards
    $start = $date;
    while( date( 'w', $start ) > WEEK_START ) {
        $start -= 86400; // One day
    }
    // End of the week is simply 6 days from the start
    $end = date( 'Y-m-d', $start + ( 6 * 86400 ) );
    $start = date( 'Y-m-d', $start );
}

经过初步测试,代码可能无法完全防护,或者无法处理过去或未来较远的日期。使用需自行承担风险。请勿将代码浸泡在水中。请勿向那些情绪易激动或对美元符号有厌恶情感的人展示代码。未对动物进行测试。适用于素食主义者。作者保证代码永远不会与您交谈。如果不幸代码尝试与您交流,请忽略它提供的任何建议。


2
使用此方法可以从任何给定日期获取“周”数。
//October 29, 2009 is my birthday
echo $week date('W', strtotime('2009-10-29'));
//OUTPUT: 44
//October 29 is the 44th week in the year 2009

现在,将getWeekDates函数的参数设置为"year (2009)"和"$week"。
function getWeekDates($year, $week, $start=true){
        $from = date("Y-m-d", strtotime("{$year}-W{$week}-1")); //Returns the date of monday in week
        $to = date("Y-m-d", strtotime("{$year}-W{$week}-7"));   //Returns the date of sunday in week

        if($start) {
            return $from;
        } else {
            return $to;
        }
        //return "Week {$week} in {$year} is from {$from} to {$to}.";
    }

更多信息请参见此链接http://blog.ekini.net/2009/07/09/php-get-start-and-end-dates-of-a-week-from-datew/


1

在试图寻找Paolo Bergantino所接受的答案的更精简版本时,我发现了一种非常好的方法来完成此操作:

function x_week_range2($date) {
  $ts = strtotime($date);
  $start = strtotime('sunday this week -1 week', $ts);
  $end = strtotime('sunday this week', $ts);
  return array(date('Y-m-d', $start), date('Y-m-d', $end));
}

'本周日'字符串始终意味着“本周的末尾星期天”。如果应用于落在星期天的时间戳,则为下个星期天。这让您避免了 Paola 解决方案中三元运算符的需求。


1
你现在可以使用 DateTime 来获取一周的开始/结束日期。
function getDateRangeForAllWeeks($start, $end){
    $fweek = getDateRangeForWeek($start);
    $lweek = getDateRangeForWeek($end);
    $week_dates = [];
    while($fweek['sunday']!=$lweek['sunday']){
        $week_dates [] = $fweek;
        $date = new DateTime($fweek['sunday']);
        $date->modify('next day');

        $fweek = getDateRangeForWeek($date->format("Y-m-d"));
    }
    $week_dates [] = $lweek;

    return $week_dates;
}

function getDateRangeForWeek($date){
    $dateTime = new DateTime($date);
    $monday = clone $dateTime->modify(('Sunday' == $dateTime->format('l')) ? 'Monday last week' : 'Monday this week');
    $sunday = clone $dateTime->modify('Sunday this week'); 
    return ['monday'=>$monday->format("Y-m-d"), 'sunday'=>$sunday->format("Y-m-d")];
}

Usage

print_r( getDateRangeForWeek("2016-05-07") );

print_r( getDateRangeForAllWeeks("2015-11-07", "2016-02-15") );

0

基于David Bélanger的版本(遗憾的是,我的声誉不允许我在他的帖子中发布评论..)。

当输入日期为星期一且将每周的第一天设置为星期一时,原始版本会返回上一周,而不是当前周。以下是小小修复(与原始函数的其余部分一起):

if(function_exists('grk_Week_Range') === FALSE){
function grk_Week_Range($DateString, $FirstDay=6){

    if(empty($DateString) === TRUE){
        $DateString = date('Y-m-d');
    }

    # fix
    $dayOfWeek = date('N', strtotime($DateString));
    if ($dayOfWeek == ($FirstDay +1)) { $whichWeek = 'this '; }
    else { $whichWeek = 'last '; }

    $Days = array(
        0 => 'monday',
        1 => 'tuesday',
        2 => 'wednesday',
        3 => 'thursday',
        4 => 'friday',
        5 => 'saturday',
        6 => 'sunday'
    );

    # fix   
    $DT_Min = new DateTime( $whichWeek.(isset($Days[$FirstDay]) === TRUE ? $Days[$FirstDay] : $Days[6]).' '.$DateString);
    $DT_Max = clone($DT_Min);

    return array(
        $DT_Min->format('Y-m-d'),
        $DT_Max->modify('+6 days')->format('Y-m-d')
    );
}
}

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