我需要在PHP中创建函数,让我在给定的日期时间单位上升/下移。具体来说,我需要能够从当前月份转移到下一个/上个月。
我以为我可以使用DateTime :: add / sub(P1M)来做到这一点。然而,当试图获得前一个月时,如果日期值= 31-看起来它实际上试图倒数30天而不是递减月值,则会搞砸!:
$prevMonth = new DateTime('2010-12-31');
尝试减少月份:
$prevMonth->sub(new DateInterval('P1M')); // = '2010-12-01'
$prevMonth->add(DateInterval::createFromDateString('-1 month')); // = '2010-12-01'
$prevMonth->sub(DateInterval::createFromDateString('+1 month')); // = '2010-12-01'
$prevMonth->add(DateInterval::createFromDateString('previous month')); // = '2010-12-01'
这肯定是错误的行为。有人有任何见解吗? 谢谢 -
注意: PHP版本5.3.3
答案 0 :(得分:6)
(信用实际上属于Alex,因为在评论中指出了这一点)
问题不是PHP,而是GNU问题,如下所述:
Relative items in date strings
这里的关键是区分“上个月这个日期”的概念,因为月份是具有不同日期数量的“模糊单位”,因此无法定义像12月31日这样的日期(因为11月31日没有'存在),以及“上个月,不论日期”的概念。
如果我们感兴趣的只是前一个月,那么保证正确的DateInterval计算的唯一方法是将日期值重置为1st,或者每个月将有一些其他数字。
真正令我印象深刻的是这个问题在PHP和其他地方没有记录 - 考虑它可能影响的日期相关软件的数量。
这是一种安全的方法来处理它:
/*
Handles month/year increment calculations in a safe way,
avoiding the pitfall of 'fuzzy' month units.
Returns a DateTime object with incremented month/year values, and a date value == 1.
*/
function incrementDate($startDate, $monthIncrement = 0, $yearIncrement = 0) {
$startingTimeStamp = $startDate->getTimestamp();
// Get the month value of the given date:
$monthString = date('Y-m', $startingTimeStamp);
// Create a date string corresponding to the 1st of the give month,
// making it safe for monthly/yearly calculations:
$safeDateString = "first day of $monthString";
// Increment date by given month/year increments:
$incrementedDateString = "$safeDateString $monthIncrement month $yearIncrement year";
$newTimeStamp = strtotime($incrementedDateString);
$newDate = DateTime::createFromFormat('U', $newTimeStamp);
return $newDate;
}
答案 1 :(得分:2)
在我看来,最简单的方法就是使用mktime。
像这样:
$date = mktime(0,0,0,date('m')-1,date('d'),date('Y'));
echo date('d-m-Y', $date);
Greetz Michael
p.s mktime文档可以在这里找到:http://nl2.php.net/mktime
答案 2 :(得分:1)
你可以去上学,只使用日期和strtotime功能。
$date = '2010-12-31'; $monthOnly = date('Y-m', strtotime($date)); $previousMonth = date('Y-m-d', strtotime($monthOnly . ' -1 month'));
答案 3 :(得分:-1)
(这可能应该是一个评论,但它要长一个)
以下是它如何在Windows 7 Apache 2.2.15上使用PHP 5.3.3:
<?php $dt = new DateTime('2010-12-31');
$dt->sub(new DateInterval('P1M'));
print $dt->format('Y-m-d').'<br>';
$dt->add(DateInterval::createFromDateString('-1 month'));
print $dt->format('Y-m-d').'<br>';
$dt->sub(DateInterval::createFromDateString('+1 month'));
print $dt->format('Y-m-d').'<br>';
$dt->add(DateInterval::createFromDateString('previous month'));
print $dt->format('Y-m-d').'<br>'; ?>
2010-12-01
2010-11-01
2010-10-01
2010-09-01
所以这似乎确认它与上面的GNU有关。
注意:IMO下面的代码按预期工作。
$dt->sub(new DateInterval('P1M'));
本月:12
上个月:11
第12个月的天数:31
第11个月的天数:30
12月31日 - 31日= 11月31日
11月31日= 11月1日+ 31天= 12月1日(30 + 1)