获取过去 12 个月的 PHP

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7262971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 02:20:45  来源:igfitidea点击:

Get the last 12 months in PHP

phpdate

提问by Rohit Chopra

So here is an interesting problem I learned today.

所以这是我今天学到的一个有趣的问题。

I need to populate an array with the last 12 months, starting with the past month. So in August 2011, the last 12 months will be Sep 2010 - July 2011. To do this, I am using:

我需要从过去一个月开始填充过去 12 个月的数组。所以在 2011 年 8 月,过去 12 个月将是 2010 年 9 月 - 2011 年 7 月。为此,我使用:

for ($i = 1; $i <= 12; $i++)
    $months[] = date("Y-m%", strtotime("-$i months"));

The code above works just fine on August 30. I get the last 12 months:

上面的代码在 8 月 30 日工作得很好。我得到了过去 12 个月的数据:

array
    0 => string '2011-07%' (length=8)
    1 => string '2011-06%' (length=8)
    2 => string '2011-05%' (length=8)
    3 => string '2011-04%' (length=8)
    4 => string '2011-03%' (length=8)
    5 => string '2011-02%' (length=8)
    6 => string '2011-01%' (length=8)
    7 => string '2010-12%' (length=8)
    8 => string '2010-11%' (length=8)
    9 => string '2010-10%' (length=8)
    10 => string '2010-09%' (length=8)
    11 => string '2010-08%' (length=8)

But when I run this on Aug 31, I get:

但是当我在 8 月 31 日运行它时,我得到:

array
    0 => string '2011-07%' (length=8)
    1 => string '2011-07%' (length=8)
    2 => string '2011-05%' (length=8)
    3 => string '2011-05%' (length=8)
    4 => string '2011-03%' (length=8)
    5 => string '2011-03%' (length=8)
    6 => string '2011-01%' (length=8)
    7 => string '2010-12%' (length=8)
    8 => string '2010-12%' (length=8)
    9 => string '2010-10%' (length=8)
    10 => string '2010-10%' (length=8)
    11 => string '2010-08%' (length=8)

I have tried both Windows and Unix. Does anyone have a solution for this?

我试过 Windows 和 Unix。有没有人对此有解决方案?

回答by JJJ

I'm sure someone has a more elegant solution, but you could start counting backwards from the 1st of this month.

我敢肯定有人有更优雅的解决方案,但您可以从本月 1 日开始倒数。

for ($i = 1; $i <= 12; $i++) {
    $months[] = date("Y-m%", strtotime( date( 'Y-m-01' )." -$i months"));
}

回答by Jason McCreary

It's because not every month has a 31st. So strtotime()is advancing to the next month. i.e. 4/31 = 5/1.

这是因为不是每个月都有 31 号。所以,strtotime()在前进到下一个月。即 4/31 = 5/1。

You'd be better off using mktime()for this as it's dumberthan strtotime().

你会更好使用mktime()这个,因为它是strtotime()

UPDATE

更新

To take advantage of a smartfunction like strtotime()and avoid tracking the year for mktime(), the following is my suggestion:

为了利用诸如的智能功能strtotime()并避免跟踪年份mktime(),以下是我的建议:

$month = time();
for ($i = 1; $i <= 12; $i++) {
  $month = strtotime('last month', $month);
  $months[] = date("r", $month);
}
print_r($months);

Adjust logic and optimize as you see fit.

调整逻辑并按照您认为合适的方式进行优化。

回答by Mark

I think this will work:

我认为这会奏效:

$this_month = date("n", time());
$this_year = date("Y", time());
$months_array = array();
for ($i = $this_month - 1; $i > ($this_month - 13); $i--) {
    echo "$i<br>";
    if ($i < 1) {
        $correct_month_number = $i + 12;
        $months_array[] = array($correct_month_number, $this_year - 1);
    }
    else {
        $months_array[] = array($i, $this_year);
    }
}
echo "<pre>"; var_dump($months_array); echo "</pre>";

The data types are a little loose, but this gets the job done. The nice thing about this is that it only calls the date() function for the current month and year, once. The rest of the logic is just simple math. No need to worry about the length of each month.

数据类型有点松散,但这可以完成工作。这样做的好处是它只调用当前月份和年份的 date() 函数一次。其余的逻辑只是简单的数学运算。无需担心每个月的长度。

Then you can use the $months_array array to build whatever you need.

然后你可以使用 $months_array 数组来构建你需要的任何东西。

回答by Sherif

I'd like to propose an alternative solution using DatePeriodinstead.

我想提出一个替代解决方案,DatePeriod而不是使用。

There are a number of caveats to watch out for here. For one, you don't want things like Timezoneinformation, or day/timeinformation to get in your way. You're only interested in the month. So we can normalize some of this information to prevent complications like overflows and daylight savings complications, etc... Since you couldeasily fall into this trap only on specific dates/times when these rare events occur.

这里有许多注意事项需要注意。一方面,您不希望诸如时区信息或日期/时间信息之类的东西妨碍您。你只对月份感兴趣。因此,我们可以正常化一些信息,以防止像溢出和夏令并发症等并发症......既然你可以很容易落入这个陷阱只在特定日期/时,这些罕见的事件发生时间。

$start = new DateTime;
$start->setDate($start->format('Y'), $start->format('n'), 1); // Normalize the day to 1
$start->setTime(0, 0, 0); // Normalize time to midnight
$start->sub(new DateInterval('P12M'));
$interval = new DateInterval('P1M');
$recurrences = 12;

foreach (new DatePeriod($start, $interval, $recurrences, true) as $date) {
    echo $date->format('F, Y'), "\n"; // attempting to make it more clear to read here
}

Output:

输出:

February, 2019
March, 2019
April, 2019
May, 2019
June, 2019
July, 2019
August, 2019
September, 2019
October, 2019
November, 2019
December, 2019
January, 2020

回答by Marc B

The joys of different month lengths. strtotime is being literally, and taking 'Aug 31' and tryinn to make "Sep 31", which doesn't exist. So you end up with Oct 1 or something. A safer approach is this:

不同月份长度的乐趣。strtotime 就是字面上的意思,取'Aug 31' 并尝试制作不存在的“Sep 31”。所以你最终会得到 10 月 1 日之类的。更安全的方法是这样的:

for ($i = 1; $i <= 12; $i++) {
    $months[] = date("Y-m%", mktime(0, 0, 0, $i, 1, 2011));
}

strtotime is magical sometimes, but it's not reliable and certainly not "fast".

strtotime 有时很神奇,但它不可靠,当然也不“快”。