Получение первого дня недели в месяце с помощью strtotime

Я пытаюсь определить первую среду данного месяца, используя strtotime, но аргумент «первая среда» терпит неудачу всякий раз, когда первая среда выпадает на 1-е число.

Для более общей иллюстрации этой проблемы см. Следующий код и результат:

$mon = strtotime("December 2010 first monday");
$tue = strtotime("December 2010 first tuesday");
$wed = strtotime("December 2010 first wednesday");
$thu = strtotime("December 2010 first thursday");
$fri = strtotime("December 2010 first friday");
$sat = strtotime("December 2010 first saturday");
$sun = strtotime("December 2010 first sunday");

echo strftime("%m/%d/%y", $mon) . "<br>";
echo strftime("%m/%d/%y", $tue) . "<br>";
echo strftime("%m/%d/%y", $wed) . "<br>";
echo strftime("%m/%d/%y", $thu) . "<br>";
echo strftime("%m/%d/%y", $fri) . "<br>";
echo strftime("%m/%d/%y", $sat) . "<br>";
echo strftime("%m/%d/%y", $sun) . "<br>";

Результаты в:

12/06/10
12/07/10
12/08/10
12/02/10
12/03/10
12/04/10
12/05/10

Заметили что-нибудь? Разве один день недели не должен совпадать с 1-м числом месяца? Но этого никогда не происходит, и вместо этого всегда возвращается второй экземпляр дня, 8-го числа.

У кого-нибудь есть объяснение этому?


person Yarin    schedule 05.12.2010    source источник


Ответы (6)


У меня нет никаких объяснений, так как я тоже поражен, но мне удалось выяснить, как получить правильную дату, опуская «первое», например:

$ php -r 'echo date("m/d/y", strtotime("December 2010 Wednesday"));'
12/01/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Thursday"));'
12/02/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Friday"));'
12/03/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Saturday"));'
12/04/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Sunday"));'
12/05/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Monday"));'
12/06/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Tuesday"));'
12/07/10
person Andreas Wong    schedule 05.12.2010
comment
Что ж, вы можете посмотреть исходный код php, если вы ‹i› ‹/i› действительно любопытны, что касается меня, давайте продолжим: D - person Andreas Wong; 05.12.2010
comment
Кажется, это не работает полностью. Я использую это решение 12 июня и получаю 12/15/2014. Возможно, это относительно недели текущего месяца? - person Webnet; 14.06.2014

Основываясь на предоставленных ответах, нужно знать о различиях в относительном форматировании даты между php 5.2 и php 5.3.

ТЕСТ:

$date1 = strtotime("first wednesday of 2010-12");
$date2 = strtotime("first wednesday 2010-12");
$date3 = strtotime("wednesday 2010-12");

5.2 Результаты:

1969-12-31
2010-12-08
2010-12-01

5.3 Результаты:

2010-12-01
2010-12-08
2010-12-01

Поэтому только третий метод возвращает правильные результаты в версиях PHP 5.

person Yarin    schedule 07.12.2010

Просто у вас неправильное форматирование. Вам необходимо включить of:

echo strftime("%m/%d/%y", strtotime("first Monday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Tuesday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Wednesday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Thursday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Friday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Saturday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Sunday of December 2010"));

Печать:

12/06/10
12/07/10
12/01/10
12/02/10
12/03/10
12/04/10
12/05/10

Принятое решение работает, но вы столкнетесь с проблемами, если захотите найти второй день недели:

echo strftime("%m/%d/%y", strtotime("December 2010 second Wednesday"));

Печать:

12/15/10

В документации есть несколько примеров:

http://www.php.net/manual/en/datetime.formats.relative.php

Второй блок примечаний в вышеупомянутой документации объясняет, как of влияет на процесс вычисления даты:

Также обратите внимание, что «of» в «порядковом пространстве dayname space 'of'» и «'last' space dayname space 'of'» делает что-то особенное.

  1. Он устанавливает день месяца на 1.
  2. "порядковое имя дня" не переносится на другой день. (Пример: «первый вторник июля 2008 года» означает «2008-07-01»).
  3. «порядковое имя дня» действительно переходит на другой день. (Пример: «первый вторник июля 2008 года» означает «2008-07-08», см. Также пункт 4 в списке выше).
  4. «'last' dayname 'of'» принимает последнее название дня текущего месяца. (Пример: «последняя среда июля 2008 г.» означает «30 июля 2008 г.»)
  5. "'last' dayname" берет последнее имя текущего дня. (Пример: «последняя среда июля 2008» означает «2008-06-25»; «июль 2008» сначала устанавливает текущую дату на «2008-07-01», а затем «последняя среда» перемещается на предыдущую среду, которая является «2008». -06-25 ").
person Mike    schedule 05.12.2010
comment
формат «of» работает только в PHP ›= 5.3 и не работает в версии 5.2. Смотрите мой ответ по результатам тестов. - person Yarin; 07.12.2010
comment
@ Ярин: Хорошо замечено. Обработка дат в ›= 5.3 выглядит намного более надежной, чем в более ранних версиях. Жаль, что существует так много потенциальных ловушек. - person Mike; 07.12.2010

Я нашел эту заметку в руководстве по PHP.

«В PHP 5 до 5.2.7 при запросе определенного наступления данного дня недели в месяце, когда этот день недели был первым днем ​​месяца, к возвращаемой метке времени неправильно добавлялась одна неделя. Это было исправлено в 5.2.7 и более поздние версии ".

person jasonmcclurg    schedule 08.03.2011

PHP 5.5.11

$firstWeekdayOfMonth = new DateTime('first weekday 0 jun 2016');

Я не знаю почему, но нулевой вид заставляет парсер strtotime запускаться в начале месяца, учитывая первый день.

person Elier    schedule 25.08.2016

Я считаю, что это порядок, в котором вы расставляете ценности. Когда пишешь «декабрь 2010», уже идет 01.12.2010. При добавлении "first {day}" функция действует для того самого первого дня после 01.12.2010. Я думаю, что если вы объявите значение "first {day}", а затем "декабрь 2010", все должно работать нормально.

person user12533177    schedule 13.12.2019