2012-05-23 7 views
19

Eventuali duplicati:
PHP DateTime::modify adding and subtracting monthsCome aggiungere 1 mese in una data senza saltare cioè febbraio

ho una data di inizio (ad esempio 2011-01-30) e si desidera aggiungere 1 mese.

Il problema è nel definire cos'è un mese. Quindi, se io uso il seguente codice:

$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'); 

ottengo il seguente risultato: 2011-03-02 15:57:57

Il problema è che ho bisogno di utilizzare le seguenti regole:

  • Se aggiungo 1 mese sarà solo aggiungere 1 da parte mese e lasciare la parte giorno (2011-01-15 diventerà 2011-02-15)
  • Se il giorno non è esistente nel il mese che termineremo, prendiamo l'ultimo giorno esistente di questo (2011-01-30 diventerà 2011-02-28)

Esiste una funzione comune in php che può eseguire questa operazione o devo codificarla da solo? Forse mi manca solo un parametro o qualcosa del genere !?

+4

Se si sta ripetendo più mesi, è necessario fare attenzione a non rimanere "bloccati" il 28. ad esempio, se inizi a 1/30 .. 2/28 .. 3/28, quando probabilmente vorrai 3/30. – Matthew

+3

Ho recentemente affrontato questa implementazione di un sistema di fatturazione commerciale. Non esiste una soluzione pre-cotta. Devi tenere traccia del tuo giorno di inizio, aumentare il mese, vedere se quel giorno esiste nel mese successivo, in caso contrario, utilizzare l'ultimo giorno del mese. In realtà non è terribilmente complicato, ma sentirai che non dovresti scrivere così tanto codice. – Endophage

+0

Il requisito qui è di aggiungere * mesi di calendario *. Passare al 1 ° del mese, aggiungere i mesi desiderati, quindi tornare al numero del giorno iniziato * o * l'ultimo giorno del nuovo mese se il mese è in corto rispetto al numero del giorno iniziale. – Jason

risposta

11

Sembra che non v'è alcuna funzione pronto per questo, così ho scritto da solo. Questo dovrebbe risolvere il mio problema. Grazie comunque per le tue risposte e i tuoi commenti. Se si riscontrano errori, si prega di fornire nei commenti.

Questa funzione calcola il mese e l'anno in cui terminerò dopo aver aggiunto un mese. Quindi controlla se la data è giusta. In caso contrario, abbiamo il caso che il giorno non sia nel mese di destinazione, quindi prendiamo invece l'ultimo giorno del mese. Testato 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

Perfetto. Avevo bisogno di questo, ma per periodi di tempo mutuamente esclusivi - Ho appena aggiunto '$ day = $ day-1;' dopo '$ day = $ d1-> format ('d');' – Simeon

+0

Alcuni problemi con valori negativi: Replace '$ anno + = piano ($ monthToAdd/12); 'per' $ anno + = $ monthToAdd> = 0? floor ($ monthToAdd/12): ceil ($ monthToAdd/12); 'e prima di' if (! checkdate()) ', aggiungi questo:' if ($ month <0) { $ month = 12 + $ month% 12; $ anno--; } '. Testato con PHP 5.6.29. Spero che aiuti qualcuno. – sk001

11

sono disponibili diverse alternative oltre DateInterval.

Ecco alcuni esempi che utilizzano 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; 

Ecco alcuni link per DateInterval:

D: Esattamente come fare si definisce un "mese"?

Def # 1): un "mese" è un "mese" - indipendentemente dalla #/giorni

Def # 2): un "mese" è di 30 giorni (per esempio)

Def # 3): un "mese" è il #/giorni tra la 1 ° Lunedi del mesi successivi

ecc ecc

D: Qual è esattamente il vostro "definizione"?

+1

Beh, qui. Se provo: $ date = "2011-01-30"; $ newdate = strtotime ('+1 month', strtotime ($ date)); data dell'eco ('Y-m-d', $ newdate); Ottengo 2011-03-02 e non 2011-02-28 come ho bisogno di – Kasihasi

+0

Come hai potuto vedere dalla mia domanda ho usato il tuo Def # 1. – Kasihasi

+2

Se si utilizza strtotime(), il modo migliore per evitare di saltare a febbraio è aggiungere $ date = strtotime ('primo giorno di +1 mese'); –

0

OK: per quanto posso dire, non hai ancora definito chiaramente cosa intendi per "mese".

Ma qui è una funzione più che potrebbe aiutare:

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; 
} 
Problemi correlati