2016-09-01 18 views
9

Muszę dostać datę, która jest 6 miesięcy dodana z określoną datą. Użyłem następujący kodDodać datę w php daje różne wyniki

$start_date = "2016-08-30"; 
$end_date= date("Y-m-d", strtotime("$start_date +6 months")); 
echo $end_date; 

który dał wynik jako 2017-03-02
Potem zmienił datę rozpoczęcia w kodzie jak poniżej

$start_date = "2016-09-01"; 
$end_date= date("Y-m-d", strtotime("$start_date +6 months")); 
echo $end_date; 

który daje wynik w 2017-03 -01
Dlaczego tak się dzieje na pierwszym miejscu? Czy coś jest nie tak z moim kodem?
MySQL zapytanie

SELECT DATE_ADD('2016-08-30', INTERVAL 6 MONTH) 

daje spowodować 2017-02-28
co jest dobrym rozwiązaniem, aby uzyskać prawidłową datę?

+0

Możesz spróbować tego. $ date = new DateTime ("2016-08-30); $ date-> add (DateInterval :: createFromDateString (+6 miesięcy)); var_dump ($ date); –

+2

Prawidłowe pytanie brzmi: co ** masz na myśli przez '2016-08-30 +6 miesięcy'? O jakiej randce spodziewasz się z tego wyrażenia bez korzystania z komputera? Czy to 30 dnia szóstego miesiąca w przyszłości (w tym przypadku luty)? Lub '2016-08-30' plus' 6 * 30 dni'? – axiac

+0

@axiac: jestem także zdezorientowany w tej chwili o oczekiwanym wyniku. Używam tej funkcji do wygaśnięcia funkcji w mojej witrynie. Udostępniam ten problem od czasu znalezienia anomalii i może być pomocny również dla innych. – Thejas

Odpowiedz

4

Dzieje się tak z powodu zachowania PHP. W tym przypadku dodano 6 miesięcy, co daje luty (ma 28 dni), więc dodaje jeszcze trzy dni, ale w MySQL dodaje tylko miesiące.

Aby rozwiązać ten korzystanie last day of 6 month lub last day of sixth month zamiast +6 months

Kodeksu

$date = new DateTime('2016-08-30'); 
echo $date->format('Y-m-d'), "\n"; 
$date->modify('last day of sixth month'); 
echo $date->format('Y-m-d'), "\n"; 

Code Demo

Wyjście

2016-08-30 
2017-02-28 

Innym rozwiązaniem

$date = new DateTime('2016-08-25'); 
echo $date->format('Y-m-d'),"\n"; 
$day = $date->format('j'); 
$date->modify('first day of sixth month'); 
$date->modify('+' . (min($day, $date->format('t')) - 1) . ' days'); 
echo $date->format('Y-m-d'); 

Code Demo

Wyjście

2016-08-25 
2017-02-25 

Patrz także Relative Formats

0

Funkcja ta nie działa od lewej do prawej, jak mogłoby się wydawać. Ta funkcja analizuje ciąg jako całość, a następnie stosuje interwały według rozmiaru (rok, miesiąc, ...). Weźmy następujący przykład:

<?php 
$Date = strtotime('2011-02-22'); // February 22nd, 2011. 28 days in this month, 29 next year. 
echo date('n/j/Y', strtotime('+1 year, +7 days', $Date)); // add 1 year and 7 days. prints 2/29/2012 
echo "<br />"; 
echo date('n/j/Y', strtotime('+7 days, +1 year', $Date)); // add 7 days and 1 year, but this also prints 2/29/2012 
echo "<br />"; 
echo date('n/j/Y', strtotime('+1 year', strtotime('+7 days', $Date))); // this prints 3/1/2012, what the 2nd would do if it was left-to-right 
?> 
0

Wygląda daty PHP "korekta" różni się od MySQL:

  • PHP koryguje 2017-02-30 przez walcowanie nieprawidłowymi dni (29 i 30 lut 2017) w następnym miesiącu
  • MySQL koryguje 2017-02-30 przez zablokowanie nieprawidłowych dni do ostatniego dnia miesiąca.

Oto rozwiązanie, które może pomóc. Używa klasy DateTime, ale konwersja do daty/strtotime jest banalna.

function add_months_safe($date, $months) { 
    $day1 = (int) $date->format("j"); 
    $date->add(new DateInterval("P" . $months . "M")); 
    $day2 = (int) $date->format("j"); 
    if ($day1 !== $day2) { 
     $date->sub(new DateInterval("P" . $day2 . "D")); 
    } 
} 

$start_date = DateTime::createFromFormat("Y-m-d|", "2016-08-30"); 
echo $start_date->format("Y-m-d H:i:s");   // 2016-08-30 00:00:00 
add_months_safe($start_date, 6); 
echo $start_date->format("Y-m-d H:i:s");   // 2017-02-28 00:00:00 

$start_date = DateTime::createFromFormat("Y-m-d|", "2016-09-01"); 
echo $start_date->format("Y-m-d H:i:s");   // 2016-09-01 00:00:00 
add_months_safe($start_date, 6); 
echo $start_date->format("Y-m-d H:i:s");   // 2017-03-01 00:00:00 
Powiązane problemy