PHP DateTime (), изменить первый день недели на понедельник

Класс DateTime в PHP (5.3+) отлично работает до тех пор, пока в первый день недели в вашей стране будет воскресенье. В Нидерландах первый день недели – понедельник, и это просто делает класс бесполезным для создания календаря с недельным просмотром и расчетами.

Я не могу найти ответ на 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 не всегда содержит ту же дату, я должен продолжать проверять его таким образом, что затрудняет чтение кода. Имея намного больше программ для этого календаря, я не могу предвидеть, где снова будет ошибка.

EDIT Есть некоторые несоответствия. По какой-то странной причине DateTime делает следующее следующее:

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

Но я думаю, что я могу сделать вопрос более ясным: можно ли использовать класс DateTime () с понедельника в качестве первого дня недели. Если нет, можно ли расширить класс, чтобы использовать понедельник в качестве первого дня недели.

UPDATE: Хорошо, я думаю, что я куда-то … Я не профессионал в классах кодирования … но это, похоже, работает в течение недель. Но для него все еще нужны правила для первого дня, второго дня … а также для самого имени дня в воскресенье. Я не думаю, что это безупречно. Буду признателен за любую помощь, чтобы исправить это.

 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('Ym-d'); // And I can still concatenate calls like the DateTime class was intended echo $test->modify('Monday this week')->modify('+3 days')->format('Ym-d'); 

Я нашел, что это работает, но есть некоторые несоответствия в классе DateTime PHP.

Если уходящая дата – воскресенье, предыдущий понедельник не считается той же неделей (фиксируется этим классом). Но, уходя с понедельника, следующее воскресенье считается одной и той же неделей. Если они исправит это, в будущем этому классу потребуются некоторые дополнения.

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

Вам нечего вручную изменять дату, чтобы получить «первый» день недели, в зависимости от вашего определения «первый». Например:

 $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 как «первый» день.

Изменить : это довольно простой пример. Правильный способ сделать это – использовать локаль пользователя / системы, чтобы дать вам «первый» день и вычислить оттуда. См. Этот вопрос для получения дополнительной информации.

Я тоже смущен тем, что проблема, потому что у DateTime есть понятие недели, начиная с понедельника: формат N дает вам дни недели с понедельника по воскресенье, с понедельником 1, а воскресенье – 7. Более того, формат W , единственный способ получить номер недели, также начинается неделя в понедельник. (Кажется, я помню, что номера голландской недели не совсем такие, как номера ИСО, но это совсем другая история). Какая особенность вам не хватает точно?

Edit Итак, проблема (только?), Что относительные форматы datetime , такие как «понедельник на этой неделе», дают неверный результат, когда контрольная дата – воскресенье. Из документов это похоже на то, что DateTime просто отбрасывает strtotime , который, как предполагается, зависит от языка. Поэтому, если у вас установлен ваш язык, и это не работает, это звучит как ошибка (для чего это стоит).