简体   繁体   English

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

[英]PHP DateTime() class, change first day of the week to Monday

The DateTime class in PHP (5.3+) works just great as long as the first day of the week in your country is Sunday.只要您所在国家/地区一周的第一天是星期日,PHP (5.3+) 中的 DateTime 类就可以很好地工作。 In the Netherlands the first day of the week is Monday and that just makes the class useless for building a calendar with week view and calculations.在荷兰,一周的第一天是星期一,这只会让课程无法构建具有周视图和计算的日历。

I can't seem to find an answer on Stackoverflow or the rest of the Internet on how to have DateTime act as if the first day of the week is Monday.我似乎无法在 Stackoverflow 或互联网的其余部分找到关于如何让 DateTime 表现得好像一周的第一天是星期一的答案。

I found this piece on Stackoverflow, but it doesn't fix all the ways you can get into trouble and it's not an elegant solution.我在 Stackoverflow 上找到了这篇文章,但它并没有解决你遇到麻烦的所有方式,也不是一个优雅的解决方案。

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

Is there a way to change this or extent DateTime?有没有办法改变这个或扩展日期时间? Can't imagine it's not a setting as most of Europe starts their weeks on monday.无法想象这不是一个环境,因为大多数欧洲国家从周一开始他们的一周。

Added: Posting the full calendar and functions code will not make things clearer.补充:发布完整的日历和功能代码不会让事情变得更清楚。 But here is one one line for example.但这里是一行一行的例子。 I often have to check what the first day of the week is or calculate from the first day of the week to a different date and time in that week.我经常需要检查一周的第一天是什么,或者计算从一周的第一天到该周的不同日期和时间。 My code is getting full of these:我的代码充满了这些:

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

I also get an unwanted result trying to get the first full week of the month or year.尝试获取月份或年份的第一个完整周时,我也得到了一个不需要的结果。 As my $date object doesn't always contain the same date I have to keep checking it this way, making the code difficult to read.因为我的 $date 对象并不总是包含相同的日期,所以我必须继续以这种方式检查它,从而使代码难以阅读。 Having a lot more programming to do on this calendar I can't forsee where it's going to bug again.在这个日历上有更多的编程要做,我无法预见它会再次出现错误。

EDIT There are some inconsistencies though.编辑虽然有一些不一致之处。 For some strange reason DateTime does get this next one right:出于某种奇怪的原因,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   

But I think I can make the question clearer: Can the DateTime() class be used with monday as the first day of the week.但我想我可以让问题更清楚: Can the DateTime() class be used with monday as the first day of the week. If not, can the class be extended to use monday as the first day of the week.如果没有,是否可以将课程扩展为使用星期一作为一周的第一天。

UPDATE: Ok, I think I'm getting somewhere... I'm not a pro at coding classes..but this seems to work for the weeks.更新:好的,我想我正在取得进展......我不是编码课程的专业人士......但这几周似乎都有效。 But it still needs rules for first day, second day... and also for the day name Sunday itself.但它仍然需要第一天、第二天的规则……以及星期日本身的日期名称。 I don't think this is foolproof.我不认为这是万无一失的。 I would appreciate any help to fix it.我将不胜感激任何修复它的帮助。

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');

I found this to work, yet there are some inconsistencies in PHP's DateTime class.我发现这是可行的,但 PHP 的 DateTime 类中存在一些不一致之处。

If the departing date is a sunday the previous monday is not considered the same week (fixed by this class).如果出发日期是星期日,则前一个星期一不被视为同一周(由此类确定)。 But departing from a monday, the next sunday is considered as the same week.但是从星期一开始,下一个星期日被视为同一周。 If they fix that in the future this class will need some additions.如果他们将来解决这个问题,这个课程将需要一些补充。

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

}

}

There's nothing to stop you manually modifying a date to get the "first" day of the week, depending on your definition of "first".没有什么可以阻止您手动修改日期以获得一周的“第一天”,具体取决于您对“第一天”的定义。 For instance:例如:

$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"

Notice how the output changes as you vary $firstDayOfWeek ;请注意输出如何随$firstDayOfWeek的变化而变化; if it was changed to 4 above (Thursday), it would then consider Thu, 10 May 2012 as the "first" day.如果将其更改为上面的4 (星期四),则它会将Thu, 10 May 2012视为“第一天”。

Edit : this is a rather basic example.编辑:这是一个相当基本的例子。 The correct way to do this is by using the user/system's locale to give you the "first" day, and compute from there.执行此操作的正确方法是使用用户/系统的区域设置为您提供“第一”天,并从那里开始计算。 See this question for more information.有关详细信息,请参阅此问题

You can also get the start and the end of the week with setISODate, the last parameter is the ISO-daynumber in the week, monday is 1 and sunday 7也可以通过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);

I too am confused about what the problem is, because DateTime does have a notion of the week starting from Monday: The N format gives you the days of the week counting from Monday to Sunday, with Monday being 1 and Sunday being 7. Moreover, the W format, the only way to get a week number, also starts the week on Monday.我也对问题出在哪里感到困惑,因为DateTime确实有从星期一开始的一周的概念: N格式为您提供了从星期一到星期日的星期几,星期一为 1,星期日为 7。此外, W格式是获取周数的唯一方法,也是从星期一开始一周。 (I seem to remember that Dutch week numbers aren't exactly like ISO week numbers, but that's a different story). (我似乎记得荷兰周数与 ISO 周数并不完全相同,但这是另一回事)。 So what feature are you missing exactly?那么你到底缺少什么功能?

Edit So the problem is (only?) that the relative datetime formats , such as "Monday this week" give the wrong result when the reference date is a Sunday.编辑所以问题是(仅?)当参考日期是星期日时,相对日期时间格式(例如“本周星期一”)会给出错误的结果。 From the docs it sounds like DateTime just defers to strtotime , which is supposed to be locale-dependent.从文档听起来DateTime只是遵从strtotime ,这应该是依赖于语言环境的。 So if you have your locale set properly and this is not working, it sounds like a bug (for what that's worth).因此,如果您正确设置了区域设置并且这不起作用,那么这听起来像是一个错误(这是值得的)。

The proper answer:正确答案:

$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));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM