2016-09-01 30 views
9

Tôi phải có một ngày được thêm 6 tháng với ngày cụ thể. tôi đã sử dụng đoạn mã sauThêm ngày trong php cho kết quả khác nhau

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

đó đã cho kết quả như 2017-03-02
Sau đó, tôi đã thay đổi ngày bắt đầu trong mã như sau

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

được đưa ra kết quả như 2017-03 -01
Tại sao điều này xảy ra ngay từ đầu? Có gì sai với mã của tôi không?
Sử dụng Mysql truy vấn

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

cho kết quả 2017-02-28
Đó là giải pháp đúng để có được những ngày tháng chính xác?

+0

Bạn có thể thử điều này. $ date = new DateTime ('2016-08-30); $ date-> add (DateInterval :: createFromDateString (+6 tháng)); var_dump ($ date); –

+2

Câu hỏi đúng là: ** bạn ** có nghĩa là gì bởi '2016-08-30 +6 tháng'? Bạn mong đợi ngày nào nhận được từ biểu thức này mà không cần sử dụng máy tính? Có phải là ngày thứ 30 của tháng thứ 6 trong tương lai (tháng 2 trong trường hợp này) không? Hoặc '2016-08-30' cộng với' 6 * 30 ngày'? – axiac

+0

@axiac: cũng bị nhầm lẫn ngay bây giờ về đầu ra dự kiến. Tôi đang sử dụng chức năng này để hết hạn một tính năng trong trang web của mình. Tôi đã chia sẻ sự cố này vì sự bất thường được tìm thấy và có thể hữu ích cho những người khác. – Thejas

Trả lời

4

Điều này xảy ra do hành vi của PHP. Trong trường hợp này, 6 tháng được thêm vào cho tháng hai (nó có 28 ngày) để nó thêm ba ngày nữa, nhưng trong MySQL nó chỉ thêm vài tháng.

Để giải quyết điều này sử dụng last day of 6 month hoặc last day of sixth month thay vì +6 months

$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

Output

2016-08-30 
2017-02-28 

Một giải pháp

$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

Output

2016-08-25 
2017-02-25 

Cũng tham khảo Relative Formats

0

chức năng này không hoạt động từ trái sang phải như người ta nghĩ. Hàm này phân tích toàn bộ chuỗi, sau đó áp dụng các khoảng theo kích thước (năm, tháng, ...). Lấy ví dụ sau đây:

<?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

Có vẻ như ngày PHP "chỉnh" sẽ khác với MySQL:

  • PHP sửa 2017-02-30 bởi cán ngày không hợp lệ (29 và 30 tháng hai 2017) vào tháng tới
  • MySQL sửa chữa 2017-02-30 bằng cách kẹp ngày không hợp lệ đến ngày cuối cùng của tháng

Đây là giải pháp có thể hữu ích. Nó sử dụng lớp DateTime nhưng chuyển đổi thành date/strtotime là tầm thường.

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 
Các vấn đề liên quan