如何使用时间和date相对于今天前一个月和一年?

我需要得到前一个月和一年,相对于当前的date。

但是,请参阅以下示例。

// Today is 2011-03-30 echo date('Ym-d', strtotime('last month')); // Output: 2011-03-02 

由于二月和三月的天数不同,这种行为是可以理解的(到某一点),上面的例子中的代码是我所需要的,但是在每个月的第一天和第二十八天之间只能正确运行。

那么,如何尽可能以最优雅的方式得到上个月和每年(想到date("Ym") ),这一年的每一天都有效? 最佳解决scheme将基于时间参数parsing。

更新。 稍微澄清要求。

我有一段代码可以获得最近几个月的统计数据,但是我首先显示上个月的统计数据,然后在需要时加载其他月份。 这是预期的目的。 所以,在这个月的时间里,我想知道为了加载上个月的统计数据,我应该select哪一个月份。

我也有一个时区感知的代码(现在不是很重要),并接受strtotime兼容的string作为input(初始化内部date),然后允许调整date/时间,也使用strtotime兼容的string。

我知道这可以用很less的条件和基本的math来完成,但是比起来,这真的很麻烦(当然,如果它工作正常的话):

 echo tz::date('last month')->format('Y-d') 

所以,我只需要前一个月和一年,以时间兼容的方式。

回答(谢谢,@dnagirl):

 // Today is 2011-03-30 echo date('Ym-d', strtotime('first day of last month')); // Output: 2011-02-01 

看看DateTime类。 它应该正确地进行计算,并且date格式与strttotime兼容。 就像是:

 $datestring='2011-03-30 first day of last month'; $dt=date_create($datestring); echo $dt->format('Y-m'); //2011-02 

我发现了一个答案,因为我今天也有同样的问题,这是31日。 这不是一些PHP中的错误 ,而是预期的function(在某些情况下)。 根据这个post ,strtotime实际上是把月份设置回去,而不会修改天数。 所以如果今天是5月31日,那么这个4月31日是无效date。 所以它需要4月30日,然后再增加1天,并产生5月1日。

在你的例子2011-03-30,它会回去一个月到2月30日,这是无效的,因为二月份只有28天。 然后以这两天的差距(30-28 = 2),然后在3月2日的2月28日过后两天。

正如其他人指出的,获得“上个月”的最好方法是使用strtotime或DateTime对象添加“第一天”或“最后一天”:

 // Today being 2012-05-31 //All the following return 2012-04-30 echo date('Ym-d', strtotime("last day of -1 month")); echo date('Ym-d', strtotime("last day of last month")); echo date_create("last day of -1 month")->format('Ym-d'); // All the following return 2012-04-01 echo date('Ym-d', strtotime("first day of -1 month")); echo date('Ym-d', strtotime("first day of last month")); echo date_create("first day of -1 month")->format('Ym-d'); 

所以使用这些可以创build一个date范围,如果你做一个查询等。

如果这一天本身并不重要,

 echo date('Ym-d', strtotime(date('Y-m')." -1 month")); 

如果你想要相对于特定date的前一年和一个月,并有DateTime可用,那么你可以这样做:

 $d = new DateTime('2013-01-01', new DateTimeZone('UTC')); $d->modify('first day of previous month'); $year = $d->format('Y'); //2012 $month = $d->format('m'); //12 
 date('Y-m', strtotime('first day of last month')); 

strtotime有第二个timestamp参数,使第一个参数相对于第二个参数。 所以你可以这样做:

 date('Y-m', strtotime('-1 month', time())) 

如果我正确地理解了这个问题,你只需要上个月和那一年:

 <?php $month = date('m'); $year = date('Y'); $last_month = $month-1%12; echo ($last_month==0?($year-1):$year)."-".($last_month==0?'12':$last_month); ?> 

这里是例子: http : //codepad.org/c99nVKG8

呃,它不是一个人提到的错误。 这是预期的行为,因为一个月中的天数通常是不同的。 使用strtotime获取上个月的最简单方法可能是从本月的第一个月开始使用-1个月。

 $date_string = date('Y-m', strtotime('-1 month', strtotime(date('Ym-01')))); 

我认为你在strtotime函数中发现了一个bug。 每当我必须解决这个问题,我总是发现自己在月/年的价值math。 尝试这样的事情:

 $LastMonth = (date('n') - 1) % 12; $Year = date('Y') - !$LastMonth; 

也许稍微比你想要更长的时间,但我已经使用了更多的代码比可能需要更多的可读性。

这就是说,它的结果与你得到的结果是一样的 – 你想要什么?期待它出来?

 //Today is whenever I want it to be. $today = mktime(0,0,0,3,31,2011); $hour = date("H",$today); $minute = date("i",$today); $second = date("s",$today); $month = date("m",$today); $day = date("d",$today); $year = date("Y",$today); echo "Today: ".date('Ym-d', $today)."<br/>"; echo "Recalulated: ".date("Ymd",mktime($hour,$minute,$second,$month-1,$day,$year)); 

如果你只想要月份和年份,那么把date设置为“01”而不是采取“今天”的日子:

  $day = 1; 

这应该给你你需要的东西。 您可以将小时,分钟和秒设置为零,以及您不想使用这些。

  date("Ym",mktime(0,0,0,$month-1,1,$year); 

切断它相当多;-)

这是因为上个月的天数比当月less。 我已经解决了这个问题,首先检查一下上个月是否有更less的天数,并根据它改变计算。

如果天数less于1个月的最后一天,则获得当天的-1个月:

 if (date('d') > date('d', strtotime('last day of -1 month'))) { $first_end = date('Ym-d', strtotime('last day of -1 month')); } else { $first_end = date('Ym-d', strtotime('-1 month')); } 

如果DateTime解决scheme是可接受的,则此片段将返回上个月和上个月的月份,以避免在1月份运行时出现可能的陷阱。

 function fn_LastMonthYearNumber() { $now = new DateTime(); $lastMonth = $now->sub(new DateInterval('P1M')); $lm= $lastMonth->format('m'); $ly= $lastMonth->format('Y'); return array($lm,$ly); }