Php 增加/减少一个月的安全方法

Php 增加/减少一个月的安全方法,php,datetime,Php,Datetime,我看过很多关于PHP的帖子,说要小心加/减天数/月份。甚至对此提出警告。我想要一个函数,它总是将日期递增/递减到下一个月/上一个月。实际日期(1-28/31)与我的情况无关 因此,我考虑在每次递增/递减月份之前,始终将日期设置为第14天,因为这会使两侧各有大约13天的误差,因此不可能跳过整个月份(通过在月份的两端使用天数) 但我觉得这是一个糟糕的实现,但我还没有看到任何解决方案,似乎能够妥善处理这一问题。事实上,SO上接受投票结果的许多线程几乎都存在跳过月份的问题。我使用自定义类来增加/减少日期

我看过很多关于PHP的帖子,说要小心加/减天数/月份。甚至对此提出警告。我想要一个函数,它总是将日期递增/递减到下一个月/上一个月。实际日期(1-28/31)与我的情况无关

因此,我考虑在每次递增/递减月份之前,始终将日期设置为第14天,因为这会使两侧各有大约13天的误差,因此不可能跳过整个月份(通过在月份的两端使用天数)


但我觉得这是一个糟糕的实现,但我还没有看到任何解决方案,似乎能够妥善处理这一问题。事实上,SO上接受投票结果的许多线程几乎都存在跳过月份的问题。

我使用自定义类来增加/减少日期:

class Dates
{

    public function __construct() {}

    public function add_date($_date, $_years, $_months, $_days, $_spacer, $_leading_zeros = 1) {

        $values = explode($_spacer, $_date);

        for($i = 0;$i < 3;$i++) {$values[$i] = round($values[$i]);}

        $values[2] += $_days;

        if($values[2] > 31) {
            $aux = floor($values[2] / 31);
            while($values[2] > 31) {$values[2] -= 31;}
            $values[1] += $aux;
        }

        $values[1] += $_months;
        $values[0] += $_years;

        if($values[1] > 12) {
            $aux = floor($values[1] / 12);
            while($values[1] > 12) {$values[1] -= 12;}
            $values[0] += $aux;
        }

        $leapYear = (($values[0] % 4 == 0) && (($values[0] % 100 != 0) || ($values[0] % 400 == 0))) ? 29 : 28;
        $days = Array(0, 31, $leapYear, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

        if($values[2] > $days[$values[1]]) {
            $values[2] -= $days[$values[1]];
            $values[1]++;
        }

        if($_leading_zeros) {return $this -> leading_zeros($values[0].$_spacer.$values[1].$_spacer.$values[2], $_spacer);}
        else {return $values[0].$_spacer.$values[1].$_spacer.$values[2];}

    }

    public function subtract_date($_date, $_years, $_months, $_days, $_spacer, $_leading_zeros = 1) {

        $values=explode($_spacer, $_date);

        for($i = 0;$i < 3;$i++){$values[$i] = round($values[$i]);}

        $days = Array(0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

        $values[0] -= $_years;
        $values[1] -= $_months;

        while($values[1] < 1) {
            $values[1] += 12;
            $values[0]--;
        }

        $values[2] -= $_days;

        while($values[2] < 1) {     
            $values[1]--;
            if($values[1] == 0) {
                $values[1] = 12;
                $values[0]--;
            }
            if($values[1] == 2) {$days[2] = (($values[0] % 4 == 0) && (($values[0] % 100 != 0) || ($values[0] % 400 == 0))) ? 29 : 28;}
            $values[2] += $days[$values[1]];
        }

        if($_leading_zeros) {return $this -> leading_zeros($values[0].$_spacer.$values[1].$_spacer.$values[2], $_spacer);}
        else {return $values[0].$_spacer.$values[1].$_spacer.$values[2];}
    }

    public function leading_zeros($_date, $_spacer) {

        $_date = $_spacer.$_date.$_spacer;

        for($i = 1;$i < 10;$i++) {
            while(strstr($_date, $_spacer.$i.$_spacer)){$_date = str_replace($_spacer.$i.$_spacer, $_spacer.'0'.$i.$_spacer, $_date);}
        }

        $_date = substr($_date, 1);
        $_date = substr($_date, 0, -1);

        return $_date;

    }

}
上课日期
{
公共函数{u构造(){}
公共函数add_date($_date,$_years,$_month,$_days,$_spacer,$_leading_zero=1){
$values=分解($\u间隔符,$\u日期);
对于($i=0;$i<3;$i++){$values[$i]=round($values[$i]);}
$values[2]+=$\u天;
如果($value[2]>31){
$aux=地板($values[2]/31);
而($values[2]>31){$values[2]=31;}
$values[1]+=$aux;
}
$values[1]+=$\u个月;
$values[0]+=$\u年;
如果($value[1]>12){
$aux=地板($values[1]/12);
而($values[1]>12){$values[1]=12;}
$values[0]+=$aux;
}
$leapYear=($values[0]%4==0)和&($values[0]%100!=0)| |($values[0]%400==0))?29:28;
$days=数组(0,31,$leapYear,31,30,31,30,31,31,30,31);
如果($values[2]>$days[$values[1]])){
$values[2]=$days[$values[1]];
$values[1]++;
}
如果($_前导零){返回$this->前导零($values[0]。$_spacer.$values[1]。$_spacer.$values[2],$_spacer);}
else{return$values[0].$_spacer.$values[1].$_spacer.$values[2];}
}
公共函数减去日期($日期、$年、$月、$天、$间隔符、$前导零=1){
$values=分解($\u间隔符,$\u日期);
对于($i=0;$i<3;$i++){$values[$i]=round($values[$i]);}
$days=数组(0,31,0,31,30,31,30,31,31,30,31,31,30,31);
$values[0]=$\u年;
$values[1]=$\u个月;
而($value[1]<1){
$values[1]+=12;
$values[0]-;
}
$values[2]=$\u天;
而($value[2]<1){
$values[1]-;
如果($value[1]==0){
$values[1]=12;
$values[0]-;
}
如果($values[1]==2){$days[2]=($values[0]%4==0)和($values[0]%100!=0)| |($values[0]%400==0))?29:28;}
$values[2]+=$days[$values[1]];
}
如果($_前导零){返回$this->前导零($values[0]。$_spacer.$values[1]。$_spacer.$values[2],$_spacer);}
else{return$values[0].$_spacer.$values[1].$_spacer.$values[2];}
}
公共函数前导零($\u日期,$\u间隔符){
$\u日期=$\u间隔。$\u日期。$\u间隔;
对于($i=1;$i<10;$i++){
而(strstrstr($\u日期,$\u间隔区.$i.$\u间隔区)){$\u日期=str\u替换($\u间隔区.$i.$\u间隔区,$\u间隔区.0.$i.$\u间隔区,$\u日期);}
}
$\u日期=substr($\u日期,1);
$\u date=substr($\u date,0,-1);
返回日期$\u;
}
}

我使用自定义类来增加/减少日期:

class Dates
{

    public function __construct() {}

    public function add_date($_date, $_years, $_months, $_days, $_spacer, $_leading_zeros = 1) {

        $values = explode($_spacer, $_date);

        for($i = 0;$i < 3;$i++) {$values[$i] = round($values[$i]);}

        $values[2] += $_days;

        if($values[2] > 31) {
            $aux = floor($values[2] / 31);
            while($values[2] > 31) {$values[2] -= 31;}
            $values[1] += $aux;
        }

        $values[1] += $_months;
        $values[0] += $_years;

        if($values[1] > 12) {
            $aux = floor($values[1] / 12);
            while($values[1] > 12) {$values[1] -= 12;}
            $values[0] += $aux;
        }

        $leapYear = (($values[0] % 4 == 0) && (($values[0] % 100 != 0) || ($values[0] % 400 == 0))) ? 29 : 28;
        $days = Array(0, 31, $leapYear, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

        if($values[2] > $days[$values[1]]) {
            $values[2] -= $days[$values[1]];
            $values[1]++;
        }

        if($_leading_zeros) {return $this -> leading_zeros($values[0].$_spacer.$values[1].$_spacer.$values[2], $_spacer);}
        else {return $values[0].$_spacer.$values[1].$_spacer.$values[2];}

    }

    public function subtract_date($_date, $_years, $_months, $_days, $_spacer, $_leading_zeros = 1) {

        $values=explode($_spacer, $_date);

        for($i = 0;$i < 3;$i++){$values[$i] = round($values[$i]);}

        $days = Array(0, 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

        $values[0] -= $_years;
        $values[1] -= $_months;

        while($values[1] < 1) {
            $values[1] += 12;
            $values[0]--;
        }

        $values[2] -= $_days;

        while($values[2] < 1) {     
            $values[1]--;
            if($values[1] == 0) {
                $values[1] = 12;
                $values[0]--;
            }
            if($values[1] == 2) {$days[2] = (($values[0] % 4 == 0) && (($values[0] % 100 != 0) || ($values[0] % 400 == 0))) ? 29 : 28;}
            $values[2] += $days[$values[1]];
        }

        if($_leading_zeros) {return $this -> leading_zeros($values[0].$_spacer.$values[1].$_spacer.$values[2], $_spacer);}
        else {return $values[0].$_spacer.$values[1].$_spacer.$values[2];}
    }

    public function leading_zeros($_date, $_spacer) {

        $_date = $_spacer.$_date.$_spacer;

        for($i = 1;$i < 10;$i++) {
            while(strstr($_date, $_spacer.$i.$_spacer)){$_date = str_replace($_spacer.$i.$_spacer, $_spacer.'0'.$i.$_spacer, $_date);}
        }

        $_date = substr($_date, 1);
        $_date = substr($_date, 0, -1);

        return $_date;

    }

}
上课日期
{
公共函数{u构造(){}
公共函数add_date($_date,$_years,$_month,$_days,$_spacer,$_leading_zero=1){
$values=分解($\u间隔符,$\u日期);
对于($i=0;$i<3;$i++){$values[$i]=round($values[$i]);}
$values[2]+=$\u天;
如果($value[2]>31){
$aux=地板($values[2]/31);
而($values[2]>31){$values[2]=31;}
$values[1]+=$aux;
}
$values[1]+=$\u个月;
$values[0]+=$\u年;
如果($value[1]>12){
$aux=地板($values[1]/12);
而($values[1]>12){$values[1]=12;}
$values[0]+=$aux;
}
$leapYear=($values[0]%4==0)和&($values[0]%100!=0)| |($values[0]%400==0))?29:28;
$days=数组(0,31,$leapYear,31,30,31,30,31,31,30,31);
如果($values[2]>$days[$values[1]])){
$values[2]=$days[$values[1]];
$values[1]++;
}
如果($_前导零){返回$this->前导零($values[0]。$_spacer.$values[1]。$_spacer.$values[2],$_spacer);}
else{return$values[0].$_spacer.$values[1].$_spacer.$values[2];}
}
公共函数减去日期($日期、$年、$月、$天、$间隔符、$前导零=1){
$values=分解($\u间隔符,$\u日期);
对于($i=0;$i<3;$i++){$values[$i]=round($values[$i]);}
$days=数组(0,31,0,31,30,31,30,31,31,30,31,31,30,31);
$values[0]=$\u年;
$values[1]=$\u个月;
而($value[1]<1){
$values[1]+=12;
$values[0]-;
}
$values[2]=$\u天;
而($value[2]<1){
$values[1]-;
如果($value[1]==0){
$values[1]=12;
$values[0]-;
}
如果($values[1]==2){$days[2]=($values[0]%4==0)和($values[0]%100!=0)| |($values[0]%400==0))?29:28;}
$values[2]+=$days[$values[1]];
}
如果($_前导零){返回$this->前导零($values[0]。$_spacer.$values[1]。$_spacer.$values[2],$_spacer);}
else{return$values[0].$_spacer.$values[1].$_spacer.$values[2];}
}
公共函数前导零($\u日期,$\u间隔符){
$\u日期=$\u间隔。$\u日期。$\u间隔;
对于($i=1;$i)
$ts = strtotime($yourDate);
// increment
$newTs = strtotime('first day of +1 month', $ts);
// decrement
$newTs = strtotime('first day of -1 month', $ts);
$start = 1;
$end = 24;

$template = '14.{{m}}.2014';

$tz = new DateTimeZone('Europe/London');

for($i = $start; $i < $end; $i++)
{
    $date = str_replace('{{m}}', $i, $template);

    $dt = DateTime::createFromFormat('d.m.Y', $date, $tz);

    printf("\nDate: %s", $dt->format('d.m.Y'));
}
Date: 14.01.2014
Date: 14.02.2014
Date: 14.03.2014
Date: 14.04.2014
Date: 14.05.2014
Date: 14.06.2014
Date: 14.07.2014
Date: 14.08.2014
Date: 14.09.2014
Date: 14.10.2014
Date: 14.11.2014
Date: 14.12.2014
Date: 14.01.2015
Date: 14.02.2015
Date: 14.03.2015
Date: 14.04.2015
Date: 14.05.2015
Date: 14.06.2015
Date: 14.07.2015
Date: 14.08.2015
Date: 14.09.2015
Date: 14.10.2015
Date: 14.11.2015