2012-05-23 8 views
19

Duplicar posibles:
PHP DateTime::modify adding and subtracting monthsCómo añadir al menos 1 mes en una fecha sin saltar a saber, febrero

tengo una fecha de inicio (es decir 2011-01-30) y desea agregar 1 mes.

El problema está en definir qué es un mes. Así que si uso el siguiente código:

$d1 = DateTime::createFromFormat('Y-m-d H:i:s', '2011-01-30 15:57:57'); 
$d1->add(new DateInterval('P1M')); 
echo $d1->format('Y-m-d H:i:s'); 

me sale el siguiente resultado: 2011-03-02 15:57:57

El problema es que lo necesito para usar las siguientes reglas:

  • Si agrego 1 mes se acaba de añadir al menos 1 mes de parte y dejar la parte del día (2011-01-15 se convertirá 2011-02-15)
  • Si el día no está vigente en el mes vamos a terminar, tomamos el último día existente de (2011-01-30 se convertirá en 2011-02-28)

¿Hay una función común en php que pueda hacer esto o tengo que codificarlo solo? ¡¿Tal vez me falta un parámetro o algo así ?!

+4

Si está iterando varios meses, deberá tener cuidado de no quedarse "atascado" el día 28. por ejemplo, si comienza a las 1/30 .. 2/28 .. 3/28, cuando probablemente quiera 3/30. – Matthew

+3

Recientemente he tratado con esto implementando un sistema de facturación comercial. No hay una solución precocida. Debe hacer un seguimiento de su día de inicio, incrementar el mes, ver si ese día existe el mes siguiente, si no, usar el último día del mes. En realidad no es terriblemente complicado, pero se sentirá como que no debería tener que escribir tanto código. – Endophage

+0

El requisito aquí es agregar * meses calendario *. Salte al 1 ° del mes, agregue los meses que desee y luego regrese al número del día en que comenzó el * o * último día del nuevo mes si el mes está corto del número del día inicial. – Jason

Respuesta

11

Parece que no hay ninguna función preparado para ello, por lo que escribió por mí mismo. Esto debería resolver mi problema. Gracias de todos modos por sus respuestas y comentarios. Si encuentra algunos errores, proporcione en los comentarios.

Esta función calcula el mes y el año que terminaré después de agregar algún mes. Luego verifica si la fecha es correcta. De lo contrario, tenemos el caso de que el día no está en el mes objetivo, por lo que tomamos el último día del mes. Probado con PHP 5.3.10.

<?php 
$monthToAdd = 1; 

$d1 = DateTime::createFromFormat('Y-m-d H:i:s', '2011-01-30 15:57:57'); 

$year = $d1->format('Y'); 
$month = $d1->format('n'); 
$day = $d1->format('d'); 

$year += floor($monthToAdd/12); 
$monthToAdd = $monthToAdd%12; 
$month += $monthToAdd; 
if($month > 12) { 
    $year ++; 
    $month = $month % 12; 
    if($month === 0) 
     $month = 12; 
} 

if(!checkdate($month, $day, $year)) { 
    $d2 = DateTime::createFromFormat('Y-n-j', $year.'-'.$month.'-1'); 
    $d2->modify('last day of'); 
}else { 
    $d2 = DateTime::createFromFormat('Y-n-d', $year.'-'.$month.'-'.$day); 
} 
$d2->setTime($d1->format('H'), $d1->format('i'), $d1->format('s')); 
echo $d2->format('Y-m-d H:i:s'); 
+1

Perfecto. Necesitaba esto, pero para períodos de tiempo mutuamente excluyentes - Acabo de agregar '$ day = $ day-1;' after '$ day = $ d1-> format ('d');' – Simeon

+0

Algunos problemas con valores negativos: Reemplace '$ year + = floor ($ monthToAdd/12); 'by' $ year + = $ monthToAdd> = 0? floor ($ monthToAdd/12): ceil ($ monthToAdd/12); 'y antes de 'if (! checkdate())', agregue esto: 'if ($ month <0) { $ month = 12 + $ month% 12; $ year--; } '. Probado con PHP 5.6.29. Espero que ayude a alguien. – sk001

11

Tiene varias alternativas además de DateInterval.

Éstos son ejemplos que usan strtotime():

http://www.brightcherry.co.uk/scribbles/php-adding-and-subtracting-dates/

// Subtracting days from a date 
$date = "1998-08-14"; 
$newdate = strtotime ('-3 day' , strtotime ($date)) ; 
$newdate = date ('Y-m-j' , $newdate); 

echo $newdate; 

...

// Subtracting months from a date 
$date = "1998-08-14"; 
$newdate = strtotime ('-3 month' , strtotime ($date)) ; 
$newdate = date ('Y-m-j' , $newdate); 

echo $newdate; 

Aquí hay algunos enlaces para DateInterval:

Q: Exactamente cómo hacer se define un "mes"?

Def # 1): un "mes" es un "mes" - independientemente de #/día

Def # 2): un "mes" es de 30 días (por ejemplo)

Def # 3): un "mes" es el #/día entre el lunes 1 de meses posteriores

etc etc

Q: ¿Cuál es exactamente su "definición"?

+1

Bueno, lo mismo aquí. Si intento: $ date = "2011-01-30"; $ newdate = strtotime ('+1 mes', strtotime ($ date)); echo date ('Y-m-d', $ newdate); Me llevo 2011-03-02 y no 2011-02-28 porque necesito – Kasihasi

+0

Como se puede ver en mi pregunta, utilicé tu Def # 1. – Kasihasi

+2

Si está utilizando strtotime(), entonces la mejor manera de evitar saltarse febrero es agregar $ date = strtotime ('primer día de +1 mes'); –

0

OK - hasta donde puedo decir, todavía no ha definido claramente lo que quiere decir "mes".

Pero aquí es una de las funciones más que podría ayudar:

http://php.net/manual/en/function.getdate.php

/* Function to find the first and last day of the month from the given date. 
* 
* Author Binu v Pillai   [email protected] 
* @Param   String    yyyy-mm-dd 
* 
*/ 
function findFirstAndLastDay($anyDate) 
{ 
    //$anyDate   = '2009-08-25'; // date format should be yyyy-mm-dd 
    list($yr,$mn,$dt) = split('-',$anyDate); // separate year, month and date 
    $timeStamp   = mktime(0,0,0,$mn,1,$yr); //Create time stamp of the first day from the give date. 
    $firstDay   =  date('D',$timeStamp); //get first day of the given month 
    list($y,$m,$t)  =  split('-',date('Y-m-t',$timeStamp)); //Find the last date of the month and separating it 
    $lastDayTimeStamp = mktime(0,0,0,$m,$t,$y);//create time stamp of the last date of the give month 
    $lastDay   = date('D',$lastDayTimeStamp);// Find last day of the month 
    $arrDay    = array("$firstDay","$lastDay"); // return the result in an array format. 

    return $arrDay; 
}