Вы говорите: -
кажется, что вы не можете использовать strotime, если вам нужно надежное и точное манипулирование даты
Вы можете, вам просто нужно знать, как он себя ведет. Ваш вопрос побудил меня провести пару тестов.
PHP не просто вычесть 30 дней с даты, когда вычитая месяц, хотя кажется, что он делает из одного случая вы смотрите. На самом деле мой тест here предполагает, что он добавляет 31 день к началу предыдущего месяца (результат 3 марта предлагает это мне) в этом случае.
$thirtyOnedayMonths = array(
1, 3, 5, 7, 8, 10, 12
);
$oneMonth = new \DateInterval('P1M');
$format = 'Y-m-d';
foreach($thirtyOnedayMonths as $month){
$date = new \DateTime("2013-{$month}-31 00:00:01");
var_dump($date->format($format));
$date->sub($oneMonth);
var_dump($date->format($format));
}
Есть 31 дней между 2013-11-12 и 2013-10-12 и PHP вычисляет месяц вычитание правильно, как можно видеть here.
$date = new \DateTime('2013-11-12 00:00:01');
var_dump($date);
$interval = new DateInterval('P1M');
$date->sub($interval);
var_dump($date);
В вашем конкретном случае 2013-10-31 - 1 месяц - 2013-09-31, которого нет. Любая функция даты/времени должна вернуть действительную дату, которой нет в 2013-09-31.
В этом случае PHP, как я сказал выше, кажется, добавляет 31 дней к началу предыдущего месяца, чтобы прийти к действительной дате.
Как только вы знаете ожидаемое поведение, вы можете запрограммировать его соответствующим образом. Если текущее поведение не соответствует вашему варианту использования, вы можете расширить класс DateTime, чтобы обеспечить поведение, которое работает для вас.
Я предположил, что strtotime
и DateTime::sub()
ведут себя одинаково, this test предлагает им это сделать.
$thirtyOnedayMonths = array(
1, 3, 5, 7, 8, 10, 12
);
$format = 'Y-m-d';
foreach($thirtyOnedayMonths as $month){
$date = date($format, strtotime('-1 month', strtotime("2013-{$month}-31 00:00:01")));
var_dump($date);
}
Если вы работаете с событиями с датами и временем, а затем сделать жизнь проще для себя и использовать объекты DateTime –
Я думаю, что реальная проблема заключается в том, что это вычитание одного месяца с Oct.31, возвращаясь Sept.31, который не существует и вместо этого преобразуется в Oct.1. Если я возьму ваш код и отправлю его 29 октября, я получу 29 сентября, как и ожидалось. – Blazemonger
http://stackoverflow.com/questions/9087462/php-strtotime-is-not-returning-the-correct-month – Lawson