PHP DateTime()类,将一周的第一天更改为星期一

时间:2012-10-29 20:08:37

标签: php class datetime

只要您所在国家/地区的第一天是星期日,PHP(5.3+)中的DateTime类就可以正常工作。在荷兰,一周的第一天是星期一,这使得课程无法用于构建具有周视图和计算的日历。

我似乎无法在Stackoverflow或其他互联网上找到关于如何让DateTime行动的答案,就像一周的第一天是星期一一样。

我在Stackoverflow上找到了这篇文章,但它没有解决你遇到麻烦的所有方法,而且这不是一个优雅的解决方案。

$dateTime = new DateTime('2012-05-14');
$monday = clone $dateTime->modify(('Sunday' == $dateTime->format('l')) ? 'Monday last week' : 'Monday this week');

有没有办法改变这个或扩展DateTime?无法想象这不是一个场景,因为大多数欧洲星期一开始他们的周。

加了: 发布完整的日历和功能代码不会使事情更清晰。但这里有一行例如。 我经常要检查一周的第一天是什么,或者从一周的第一天计算到该周的不同日期和时间。我的代码充满了这些:

$startOfWeek = $date->modify(('Sunday' == $date->format('l')) ? 'Monday last week' : 'Monday this week')->modify('+3 hours')->format(DATETIME);

我也得到了一个不想要的结果,试图获得该月或一年的第一个完整周。由于我的$ date对象并不总是包含相同的日期,我必须以这种方式继续检查它,使代码难以阅读。在这个日历上有更多的编程要做,我不能预见它会再次出错。

编辑但是有一些不一致的地方。由于一些奇怪的原因,DateTime确实得到了下一个权利:

$test = new DateTime('2012-10-29'); // Monday
echo $test->modify('Sunday this week')->format('Y-m-d');  // 2012-11-04

// But...

$test = new DateTime('2012-11-04'); // Sunday
echo $test->modify('Monday this week')->format('Y-m-d');  // 2012-11-05 instead of 2012-10-29   

但我想我可以让问题更清晰: 可以将DateTime()类与星期一一起用作一周的第一天。如果没有,可以将课程扩展为使用星期一作为一周的第一天。

更新 好吧,我想我已经到了某个地方......我不是编码班的专业人士......但这似乎可以工作几周。但它仍然需要第一天,第二天的规则......以及星期日本身的日期。我不认为这是万无一失的。我很感激任何帮助来解决它。

class EuroDateTime extends DateTime {

// Fields
private $weekModifiers = array (
    'this week',
    'next week',
    'previous week',
    'last week'
);

// Override "modify()"
public function modify($string) {

    // Search pattern
    $pattern = '/'.implode('|', $this->weekModifiers).'/';

    // Change the modifier string if needed
    if ( $this->format('N') == 7 ) { // It's Sunday
        $matches = array();
        if ( preg_match( $pattern, $string, $matches )) {
            $string = str_replace($matches[0], '-7 days '.$matches[0], $string);
        }
    }
    return parent::modify($string);

}

}
// This works
$test = new EuroDateTime('2012-11-04');
echo $test->modify('Monday this week')->format('Y-m-d');
// And I can still concatenate calls like the DateTime class was intended
echo $test->modify('Monday this week')->modify('+3 days')->format('Y-m-d');

5 个答案:

答案 0 :(得分:6)

我发现这可行,但PHP的DateTime类中存在一些不一致。

如果离开日期是星期日,则上一个星期一不被视为同一周(由本课程确定)。但是从星期一开始,下一个星期天被视为同一周。如果他们将来修复这个问题,那么这个课程将需要一些补充。

class EuroDateTime extends DateTime {

// Override "modify()"
public function modify($string) {

    // Change the modifier string if needed
    if ( $this->format('N') == 7 ) { // It's Sunday and we're calculating a day using relative weeks
        $matches = array();
        $pattern = '/this week|next week|previous week|last week/i';
        if ( preg_match( $pattern, $string, $matches )) {
            $string = str_replace($matches[0], '-7 days '.$matches[0], $string);
        }
    }
    return parent::modify($string);

}

}

答案 1 :(得分:2)

根据您对“第一”的定义,没有什么可以阻止您手动修改日期以获得一周中的“第一天”。例如:

$firstDayOfWeek = 1; // Monday
$dateTime = new DateTime('2012-05-16'); // Wednesday

// calculate how many days to remove to get back to the "first" day
$difference = ($firstDayOfWeek - $dateTime->format('N'));
if ($difference > 0) { $difference -= 7; }
$dateTime->modify("$difference days");

var_dump($dateTime->format('r')); // "Mon, 14 May 2012 00:00:00 +0000"

注意输出随着变化而变化$firstDayOfWeek;如果它被更改为4以上(星期四),则会将Thu, 10 May 2012视为“第一天”。

编辑:这是一个相当基本的例子。正确的方法是使用用户/系统的语言环境为您提供“第一天”,并从那里进行计算。有关详细信息,请参阅this question

答案 2 :(得分:0)

我也很困惑这个问题是什么,因为DateTime 确实从星期一开始有一周的概念:N format给你一周中的几天从星期一到星期日计算,星期一是1,星期日是7.此外,W格式是获得星期号码的唯一方式,也是星期一开始的一周。 (我似乎记得荷兰周数不完全像ISO周数,但这是一个不同的故事)。那么你究竟缺少什么功能?

编辑所以问题是(仅?)relative datetime formats,例如“本周一”,当参考日期是星期日时,会给出错误的结果。从文档中听起来像DateTime只是推迟到strtotime,这应该是与语言环境相关的。所以如果你正确设置了你的语言环境并且这不起作用,那听起来像是一个错误(对于那些值得的东西)。

答案 3 :(得分:0)

您还可以使用setISODate获取一周的开始和结束,最后一个参数是本周的ISO-daynumber,星期一是1和星期日7

$firstday = new \DateTime();
$lastday = clone($firstday);
$firstday->setISODate($firstday->format("Y"),$firstday->format("W"),1);
$lastday->setISODate($firstday->format("Y"),$firstday->format("W"),7);

答案 4 :(得分:0)

正确答案:

$week_start_day; // 0 - Sunday, 1 - Monday

$date_time_from = new DateTime('now');
$date_time_to = clone $date_time_from;

$this_week_first_day = $date_time_from->setISODate($date_time_from->format("Y"), $date_time_from->format("W"), $week_start_day);
$this_week_last_day = $date_time_to->setISODate($date_time_to->format("Y"), $date_time_to->format("W"), (6 + $week_start_day));