Я пытаюсь создать Datetimeчерез 3 дня после последнего дня этого месяца на основе даты из конструктора с помощью этого кода:
(new Datetime('2019-01-01'))->modify('last day of this month, +3 days')->format('Y-m-d')
поэтому ожидаемый результат равен 2019-02-03, но задан 2019-01-31.
Учтите, что этот код работает как шарм
(new Datetime('2019-01-01'))->modify('+1 days, +3 days')->format('Y-m-d')
ожидается: 2019-01-05 дано: 2019-01-05
и это тоже работает:
(new Datetime('2019-01-01'))->modify('last day of this month, +3 hours')->format('Y-m-d H')
ожидается: 2019-01-31 03 дано 2019-01-31 03
Вопрос: Это баг или фича? Или, может быть, с помощью last day of this month блокирует следующие days модификации?
последний день 31, и вы используете H, чтобы получить +3 часа. вы предполагаете, каковы ваши ожидания?
+3 часа - определяет часовой пояс, так что это не баг. модификация ожидает часовой пояс после того, как вы напишете день
@Sergej ->modify('last day of this month')->modify('+3 days') работает, вопрос в том, почему ->modify('last day of this month, +3 days') не работает. modify('+1 days, +3 days') работает как положено. Почему часовой пояс задействован? new Datetime('2019-01-01') находится в "2019-01-01 00:00:00.000000" часовом поясе по умолчанию
modify('+1 days, +3 days') - это такое же правило, как добавление дней к заданной дате. и первое правило не является правилом того же типа, что и две разные операции даты. сначала найдите последний день, а затем добавьте в него день. так что это не баг. функция модификации имеет такой дизайн.
Вы можете добавить часы, потому что это одна и та же начальная точка с 12 часов ночи для всей даты. так что это будет работать и с любой следующей датой. чтобы устранить это ограничение, нам нужно разделить операцию с двухкратной записью modify() в соответствии с первым ответом @Sergej.
Я считаю, что вопрос здесь не в том, как достичь конечного результата, а в том, является ли это ошибкой/функцией. Я бы сказал, что это отсутствие функции, прежде чем я назвал это ошибкой. Сам синтаксический анализатор кажется неспособным вычислить модификаторы дня, когда последний из или первый из используется в модификаторе даты для единичного оператора.






Это отмечено в документации для Относительные форматы, где сказано:
Note that expressions such as “last day of” and “first day of” imply a day of a month, not, for example of the year or week.
So, expressions, such as “first day of this year” will give the first day of this month, with no apparent regard for the year.
As powerful as the parser is, it can lead to disappointing or confusing results.
Вполне вероятно, что он имеет приоритет над фразой «Последний день» и игнорирует остальную часть утверждения дня, даже если оно разделено запятой. Что касается того, почему он анализирует время, вероятно, он сначала анализирует временные эффекты, а затем ищет дневные эффекты. Исходный код для функциональности можно глубже изучить, почему это происходит. Следует отметить, как сканируются фразы первого и последнего дня.
firstdayof | lastdayof
{
DEBUG_OUTPUT("firstdayof | lastdayof");
TIMELIB_INIT;
TIMELIB_HAVE_RELATIVE();
/* skip "last day of" or "first day of" */
if (*ptr == 'l' || *ptr == 'L') {
s->time->relative.first_last_day_of = TIMELIB_SPECIAL_LAST_DAY_OF_MONTH;
} else {
s->time->relative.first_last_day_of = TIMELIB_SPECIAL_FIRST_DAY_OF_MONTH;
}
TIMELIB_DEINIT;
return TIMELIB_LF_DAY_OF_MONTH;
}
Указатель смотрит только на то, есть ли l или L, поэтому кажется, что он срезает некоторые углы.
можно попробовать использовать
->modify('last day of this month')->modify('+3 days')