如何使用 strtotime 和 date 获取相对于今天的前一个月和前一年?

发布于 2024-10-28 07:41:16 字数 919 浏览 2 评论 0原文

我需要获取相对于当前日期的上个月和上一年。

但是,请参阅以下示例。

// Today is 2011-03-30
echo date('Y-m-d', strtotime('last month'));

// Output:
2011-03-02

这种行为是可以理解的(在某种程度上),因为 2 月和 3 月的天数不同,上面示例中的代码正是我所需要的,但在每月 1 日到 28 日之间只能 100% 正确运行。

那么,如何以尽可能最优雅的方式获取上个月和一年(想想date("Ym")),这适用于一年中的每一天?最佳解决方案将基于 strtotime 参数解析。

更新。稍微澄清一下要求。

我有一段代码可以获取过去几个月的一些统计信息,但我首先显示上个月的统计信息,然后在需要时加载其他月份。这就是预期目的。因此,在这个月中,我想找出应该提取哪一年的月份才能加载上个月的统计数据。

我还有一个时区感知的代码(现在并不重要),并且接受 strtotime 兼容的字符串作为输入(以初始化内部日期),然后允许调整日期/时间,也使用 strtotime 兼容的字符串。

我知道它可以用很少的条件和基本数学来完成,但是与此相比,这真的很混乱,例如(当然,如果它工作正常的话):

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

所以,我只需要上个月和上一年,在 strtotime 中-兼容时尚。

回答(谢谢,@dnagirl):

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

I need to get previous month and year, relative to current date.

However, see following example.

// Today is 2011-03-30
echo date('Y-m-d', strtotime('last month'));

// Output:
2011-03-02

This behavior is understandable (to a certain point), due to different number of days in february and march, and code in example above is what I need, but works only 100% correctly for between 1st and 28th of each month.

So, how to get last month AND year (think of date("Y-m")) in the most elegant manner as possible, which works for every day of the year? Optimal solution will be based on strtotime argument parsing.

Update. To clarify requirements a bit.

I have a piece of code that gets some statistics of last couple of months, but I first show stats from last month, and then load other months when needed. That's intended purpose. So, during THIS month, I want to find out which month-year should I pull in order to load PREVIOUS month stats.

I also have a code that is timezone-aware (not really important right now), and that accepts strtotime-compatible string as input (to initialize internal date), and then allows date/time to be adjusted, also using strtotime-compatible strings.

I know it can be done with few conditionals and basic math, but that's really messy, compared to this, for example (if it worked correctly, of course):

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

So, I ONLY need previous month and year, in a strtotime-compatible fashion.

Answer (thanks, @dnagirl):

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

内心激荡 2024-11-04 07:41:16

看一下 DateTime 类。它应该正确地进行计算,并且日期格式与 strttotime 兼容。像这样的东西:

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

Have a look at the DateTime class. It should do the calculations correctly and the date formats are compatible with strttotime. Something like:

$datestring='2011-03-30 first day of last month';
$dt=date_create($datestring);
echo $dt->format('Y-m'); //2011-02
小忆控 2024-11-04 07:41:16

如果这一天本身并不重要,请执行以下操作:

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

if the day itself doesn't matter do this:

echo date('Y-m-d', strtotime(date('Y-m')." -1 month"));
贩梦商人 2024-11-04 07:41:16

我找到了答案,因为我今天 31 号也遇到了同样的问题。这不是一些人建议的 php 中的错误,而是预期的功能(从那以后的一些)。根据这个 post strtotime 实际上所做的是将月份设置回 1 并且不会修改天数。因此,在今天(5 月 31 日)的情况下,它会查找 4 月至 31 日,这是一个无效日期。因此,需要 4 月 30 日,然后再加 1 天,得出 5 月 1 日。

在您的示例 2011-03-30 中,它将返回一个月到 2 月 30 日,这是无效的,因为 2 月只有 28 天。然后计算这些天数的差值 (30-28 = 2),然后将 2 月 28 日移过去两天,即 3 月 2 日。

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

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

// All the following return 2012-04-01
echo date('Y-m-d', strtotime("first day of -1 month")); 
echo date('Y-m-d', strtotime("first day of last month"));
echo date_create("first day of -1 month")->format('Y-m-d');

因此,使用这些可以创建一个日期范围,如果您进行查询等

I found an answer as I had the same issue today which is a 31st. It's not a bug in php as some would suggest, but is the expected functionality (in some since). According to this post what strtotime actually does is set the month back by one and does not modify the number of days. So in the event of today, May 31st, it's looking for April-31st which is an invalid date. So it then takes April 30 an then adds 1 day past it and yields May 1st.

In your example 2011-03-30, it would go back one month to February 30th, which is invalid since February only has 28 days. It then takes difference of those days (30-28 = 2) and then moves two days past February 28th which is March 2nd.

As others have pointed out, the best way to get "last month" is to add in either "first day of" or "last day of" using either strtotime or the DateTime object:

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

// All the following return 2012-04-01
echo date('Y-m-d', strtotime("first day of -1 month")); 
echo date('Y-m-d', strtotime("first day of last month"));
echo date_create("first day of -1 month")->format('Y-m-d');

So using these it's possible to create a date range if your making a query etc.

惟欲睡 2024-11-04 07:41:16

如果您想要相对于特定日期的上一年和上个月并且有 DateTime 可用,那么您可以执行以下操作:

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

If you want the previous year and month relative to a specific date and have DateTime available then you can do this:

$d = new \DateTimeImmutable('2013-01-01', new \DateTimeZone('UTC')); 
$firstDay = $d->modify('first day of previous month');
$year = $firstDay->format('Y'); //2012
$month = $firstDay->format('m'); //12
却一份温柔 2024-11-04 07:41:16
date('Y-m', strtotime('first day of last month'));
date('Y-m', strtotime('first day of last month'));
蓝天白云 2024-11-04 07:41:16

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

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

strtotime have second timestamp parameter that make the first parameter relative to second parameter. So you can do this:

date('Y-m', strtotime('-1 month', time()))
凉墨 2024-11-04 07:41:16

如果我正确理解了这个问题,你只想要上个月和年份:

<?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

if i understand the question correctly you just want last month and the year it is in:

<?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);

?>

Here is the example: http://codepad.org/c99nVKG8

零崎曲识 2024-11-04 07:41:16

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

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

ehh, its not a bug as one person mentioned. that is the expected behavior as the number of days in a month is often different. The easiest way to get the previous month using strtotime would probably be to use -1 month from the first of this month.

$date_string = date('Y-m', strtotime('-1 month', strtotime(date('Y-m-01'))));
淡水深流 2024-11-04 07:41:16
date("m-Y", strtotime("-1 months")); 

会解决这个问题

date("m-Y", strtotime("-1 months")); 

would solve this

戒ㄋ 2024-11-04 07:41:16

我认为您发现了 strtotime 函数中的错误。每当我必须解决这个问题时,我总是发现自己在对月/年值进行数学计算。尝试这样的事情:

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

I think you've found a bug in the strtotime function. Whenever I have to work around this, I always find myself doing math on the month/year values. Try something like this:

$LastMonth = (date('n') - 1) % 12;
$Year      =  date('Y') - !$LastMonth;
看海 2024-11-04 07:41:16

这是因为上个月的天数少于当月的天数。我通过首先检查上个月的天数是否少于当前的天数并根据它更改计算来解决此问题。

如果天数较少,则获取 -1 个月的最后一天,否则获取 -1 个月的当前日期:

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

This is because the previous month has less days than the current month. I've fixed this by first checking if the previous month has less days that the current and changing the calculation based on it.

If it has less days get the last day of -1 month else get the current day -1 month:

if (date('d') > date('d', strtotime('last day of -1 month')))
{
    $first_end = date('Y-m-d', strtotime('last day of -1 month'));
}
else
{
    $first_end = date('Y-m-d', strtotime('-1 month'));
}
就像说晚安 2024-11-04 07:41:16

也许比你想要的稍微冗长一些,但为了使其更具可读性,我使用了比必要的更多的代码。

也就是说,它得到的结果与你得到的结果相同 - 你想要/期望它得到什么?

//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('Y-m-d', $today)."<br/>";
echo "Recalulated: ".date("Y-m-d",mktime($hour,$minute,$second,$month-1,$day,$year));

如果您只想要月份和年份,则只需将日期设置为“01”而不是“今天”:

 $day = 1;

这应该可以满足您的需要。您可以将小时、分钟和秒设置为零,并且您对使用这些不感兴趣。

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

减少了很多;-)

Perhaps slightly more long winded than you want, but i've used more code than maybe nescessary in order for it to be more readable.

That said, it comes out with the same result as you are getting - what is it you want/expect it to come out with?

//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('Y-m-d', $today)."<br/>";
echo "Recalulated: ".date("Y-m-d",mktime($hour,$minute,$second,$month-1,$day,$year));

If you just want the month and year, then just set the day to be '01' rather than taking 'todays' day:

 $day = 1;

That should give you what you need. You can just set the hour, minute and second to zero as well as you aren't interested in using those.

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

Cuts it down quite a bit ;-)

回梦 2024-11-04 07:41:16

如果 DateTime 解决方案可接受,此代码片段将返回上个月的年份和上个月的月份,避免在一月份运行此代码时可能出现的陷阱。

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

If a DateTime solution is acceptable this snippet returns the year of last month and month of last month avoiding the possible trap when you run this in January.

function fn_LastMonthYearNumber()
{
 $now = new DateTime();
 $lastMonth = $now->sub(new DateInterval('P1M'));
 $lm= $lastMonth->format('m');
 $ly= $lastMonth->format('Y');
 return array($lm,$ly);
}
幸福%小乖 2024-11-04 07:41:16
//return timestamp, use to format month, year as per requirement
function getMonthYear($beforeMonth = '') {
    if($beforeMonth !="" && $beforeMonth >= 1) {
        $date = date('Y')."-".date('m')."-15";
        $timestamp_before = strtotime( $date . ' -'.$beforeMonth.' month' );
        return $timestamp_before;
    } else {
        $time= time();
        return $time;
    }
}


//call function
$month_year = date("Y-m",getMonthYear(1));// last month before  current month
$month_year = date("Y-m",getMonthYear(2)); // second last month before current month
//return timestamp, use to format month, year as per requirement
function getMonthYear($beforeMonth = '') {
    if($beforeMonth !="" && $beforeMonth >= 1) {
        $date = date('Y')."-".date('m')."-15";
        $timestamp_before = strtotime( $date . ' -'.$beforeMonth.' month' );
        return $timestamp_before;
    } else {
        $time= time();
        return $time;
    }
}


//call function
$month_year = date("Y-m",getMonthYear(1));// last month before  current month
$month_year = date("Y-m",getMonthYear(2)); // second last month before current month
℉絮湮 2024-11-04 07:41:16
function getOnemonthBefore($date){
    $day = intval(date("t", strtotime("$date")));//get the last day of the month
    $month_date = date("y-m-d",strtotime("$date -$day days"));//get the day 1 month before
    return $month_date;
}

生成的日期取决于输入月份的天数。如果输入月份为二月(28 天),则 2 月 5 日之前的 28 天为 1 月 8 日。如果输入为 5 月 17 日,则之前 31 天为 4 月 16 日。同样,如果输入为 5 月 31 日,则结果日期将为 4 月 30 日

。注意:输入采用完整日期('ymd')并输出('ymd'),您可以修改此代码以满足您的需要。

function getOnemonthBefore($date){
    $day = intval(date("t", strtotime("$date")));//get the last day of the month
    $month_date = date("y-m-d",strtotime("$date -$day days"));//get the day 1 month before
    return $month_date;
}

The resulting date is dependent to the number of days the input month is consist of. If input month is february (28 days), 28 days before february 5 is january 8. If input is may 17, 31 days before is april 16. Likewise, if input is may 31, resulting date will be april 30.

NOTE: the input takes complete date ('y-m-d') and outputs ('y-m-d') you can modify this code to suit your needs.

黯然 2024-11-04 07:41:16

不短,但有效。 (去掉我的评论就更短了)

// Calculate number of days in the current month      
$currentday = date('d');

// Calculate number of days in the previous month
$dayslastmonth = date("t", mktime(0,0,0, date("n") - 1));

// Get the year and month for last month    
$lastmonthyear = date('Y-m', strtotime(date('Y-m')." -1 month"));
    
// If the current day is greater than the last day of last month
// set the day for last month equal to the current day
if($currentday <= $dayslastmonth){
  $daylastmonth = $currentday;
else{
  $daylastmonth = $dayslastmonth;
}
   
// Put it all together
$datelastmonth = $lastmonthyear."-".$daylastmonth;

Not short, but it works. (It's shorter if you remove my comments)

// Calculate number of days in the current month      
$currentday = date('d');

// Calculate number of days in the previous month
$dayslastmonth = date("t", mktime(0,0,0, date("n") - 1));

// Get the year and month for last month    
$lastmonthyear = date('Y-m', strtotime(date('Y-m')." -1 month"));
    
// If the current day is greater than the last day of last month
// set the day for last month equal to the current day
if($currentday <= $dayslastmonth){
  $daylastmonth = $currentday;
else{
  $daylastmonth = $dayslastmonth;
}
   
// Put it all together
$datelastmonth = $lastmonthyear."-".$daylastmonth;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文