php data取年月,PHP 获取一个月后的日期

在 PHP 里,如果想获取下个月的今天,我们通常会用 strtotime('2019-01-13 +1 month')

或者是 strtotime('next month', strtotime('2019-01-13'))

,结果是 1549987200

,用 date

转换成字符串就是 2019-02-13

,so easy!

随着时间流逝,到了 2019-01-31

这一天,这代码似乎出问题了,居然得到的是 2019-03-03

???

搜了一下,找到鸟哥有一篇 文章

有解释过为什么会出现这个情况,原因是:

在 date

内部对于这种事情的处理逻辑:

先做 +1 month,那么当前是 01-31,加上一以后就是 02-31

再做日期规范化, 因为 2 月没有 31 号, 所以就好像 2:60 等于 3:00 一样,2019 年 2 月 31 日就等于了 3 月 3 日

知道了原因,那我们就知道该怎么去处理这个问题了。

首先我们先约定,如果是大月的 31 号,遇到小月时则取小月的最后一天作为 下个月的今天

,为什么这么约定呢,因为在一些结算系统中,假如你第一次月结日是在 31 号,那么下一次月结如果遇到小月,通常是以小月的最后一天作为月结日,而不是跨到再下一个月去月结。

function next_month($date)

{

if (is_numeric($date)) {

$date = date('Y-m-d', $date);

}

$next_month = date('Y-m-d', strtotime('next month', strtotime($date)));

// 获取当前日期的年、月、日

list($d_y, $d_m, $d_d) = explode('-', $date);

// 获取“一个月后”的年、月、日

list($n_y, $n_m, $n_d) = explode('-', $next_month);

// 如果月份差大于 1,说明跨月了,只需要取下一个月的最后一天就可以了;

// 细心的你可能会想到,如果是 12 月,那么 $n_m - $d_m 就是负数,需不需要再特殊处理呢?

// 其实是不用的,因为 12 月和 1 月都是大月,不存在“一个月后的今天”是跨到了次年 2 月的情况

if ($n_m - $d_m > 1) {

$next_month = date('Y-m-d', strtotime('last day of next month', strtotime($date)));

}

return $next_month;

}

这回可以正确地获取到 一个月后的日期

了,但是,如果我要获取两个月后的今天呢?

echo next_month(next_month('2019-01-31'));

上面这种用法会输出 2019-03-28

这个结果,很明显是不行的,如果是用 date('Y-m-d', strtotime('2019-01-31 +2 months'))

,在这一次需求里还行,但是如果恰巧遇上两个月后是小月呢?又或者是我要知道第 N 个月后的今天的日期?

其实也很简单,只要对上面的函数稍作修改即可:

function next_months($date, $months = 1) {

if (is_numeric($date)) {

$date = date('Y-m-d', $date);

}

$next_month = date('Y-m-d', strtotime('+' . $months . ' month', strtotime($date)));

list($d_y, $d_m, $d_d) = explode('-', $date);

list($n_y, $n_m, $n_d) = explode('-', $next_month);

$diff = ($n_y - $d_y) * 12 + ($n_m - $d_m);

if ($diff > $months) {

$next_month = date('Y-m-d', strtotime('last day of next month', strtotime($date)));

}

return $next_month;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值