使用 PHP 获取过去 12 个月的信息

发布于 2024-12-02 21:13:12 字数 1397 浏览 0 评论 0原文

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

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

for ($i = 1; $i <= 12; $i++)
    $months[] = date("Y-m%", strtotime("-$i 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)

但是当我在 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)

我已经尝试过 Windows 和 Unix。有人有解决方案吗?

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:

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:

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:

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?

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

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

发布评论

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

评论(5

獨角戲 2024-12-09 21:13:12

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

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

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

for ($i = 1; $i <= 12; $i++) {
    $months[] = date("Y-m%", strtotime( date( 'Y-m-01' )." -$i months"));
}
荆棘i 2024-12-09 21:13:12

我想提出一个使用 DatePeriod 的替代解决方案。

这里有许多注意事项需要注意。首先,您不希望时区信息或日期/时间信息等信息妨碍您。您只对月份感兴趣。因此,我们可以对其中一些信息进行标准化,以防止溢出和夏令时并发症等并发症……因为仅在这些罕见事件发生的特定日期/时间,您可能很容易陷入这个陷阱。

$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
}

输出:

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

I'd like to propose an alternative solution using DatePeriod instead.

There are a number of caveats to watch out for here. For one, you don't want things like Timezone information, or day/time information 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 could easily 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
逐鹿 2024-12-09 21:13:12

因为并不是每个月都有 31 号。因此 strtotime() 会提前到下个月。即 4/31 = 5/1。

为此,您最好使用mktime(),因为它比strtotime()更笨

更新

要利用 strtotime()智能函数并避免跟踪 mktime() 的年份,以下是我的建议:

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

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

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

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

UPDATE

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

$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.

把人绕傻吧 2024-12-09 21:13:12

我认为这会起作用:

$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>";

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

然后您可以使用 $months_array 数组来构建您需要的任何内容。

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.

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

别低头,皇冠会掉 2024-12-09 21:13:12

不同月份长度的乐趣。 strtotime 是字面上的意思,并尝试将“Aug 31”改为“Sep 31”,而“Sep 31”并不存在。所以你最终会得到 10 月 1 日之类的东西。更安全的方法是:

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

strtotime 有时很神奇,但它不可靠,而且肯定不“快”。

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:

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".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文