หลายวันก่อนมีสมาชิกในชมรมคนทำเว็บโพสว่า php คิดเดือนให้ผิด เชื่อถือไม่ได้ เราก็ใช้ php มานาน ก็คิดว่าเค้าเขียน code ผิดรึเปล่า แต่เค้าก็บอกว่าลบ code ออกไปแล้ว แต่ก็ให้ตัวอย่างวันที่มา ลองเขียน code date_diff ดูมันนับผิดจริงๆ ลองไล่หาสาเหตุดูเข้าใจว่ามันคิดผิดเพราะนับเป็นวัน สาเหตุ คือ php จะแปลงวันที่เป็นตัวเลข timestamp อย่าง

  • 2010-04-28 22:41:43 = 1272508903
  • 2007-02-14 20:25:25 จะเป็น 1171502725

และแต่ละเดือนมีวันไม่เท่ากัน แถมบางปีเดือนกุมพาพันธ์ ก็มี 28 / 29 วัน แต่ date_diff ของ php เหมือนจะไม่ได้คิดเรื่องนี้ เอาเวลาตายตัวมาคิด ทำให้ต้องใช้วิธี แยกปี แยกเดือน แล้วเอามาใส่สูตรเอาเอง

[code language=”php” title=”phpMonthsDiff.php”]<?php

$dateRanges = [
[’01/02/2016′, ’01/03/2016′],
[’01/02/2016′, ’01/04/2016′],
[’01/11/2013′, ’30/11/2013′],
[’01/01/2013′, ’31/12/2013′],
[’31/01/2011′, ’28/02/2011′],
[’01/09/2009′, ’01/05/2010′],
[’01/01/2013′, ’31/03/2013′],
[’15/02/2013′, ’15/04/2013′],
[’01/02/1985′, ’31/12/2013′],
];

foreach ($dateRanges as $range) {
list($dateStart, $dateEnd) = $range;

$timeStart = DateTime::createFromFormat(‘d/m/Y’, $dateStart);
$timeEnd = DateTime::createFromFormat(‘d/m/Y’, $dateEnd);

$months = $timeStart->diff($timeEnd)->format(‘%m’);

echo ‘<br>’, $dateStart, ‘ => ‘, $dateEnd, ‘ = ‘, $months, ‘ months’;
}
echo ‘<hr>’;
foreach ($dateRanges as $range) {
list($dateStart, $dateEnd) = $range;

$timeStart = DateTime::createFromFormat(‘d/m/Y’, $dateStart);
$timeEnd = DateTime::createFromFormat(‘d/m/Y’, $dateEnd);

$months = abs(($timeEnd->format(‘Y’) – $timeStart->format(‘Y’)) * 12 + ($timeEnd->format(‘m’) – $timeStart->format(‘m’)));

echo ‘<br>’, $dateStart, ‘ => ‘, $dateEnd, ‘ = ‘, $months, ‘ months’;
}
[/code]

ผลที่ได้คือ

  • 01/02/2016 => 01/03/2016 = 1 months
  • 01/02/2016 => 01/04/2016 = 2 months
  • 01/11/2013 => 30/11/2013 = 0 months
  • 01/01/2013 => 31/12/2013 = 11 months
  • 31/01/2011 => 28/02/2011 = 0 months
  • 01/09/2009 => 01/05/2010 = 8 months
  • 01/01/2013 => 31/03/2013 = 2 months
  • 15/02/2013 => 15/04/2013 = 2 months
  • 01/02/1985 => 31/12/2013 = 10 months

  • 01/02/2016 => 01/03/2016 = 1 months
  • 01/02/2016 => 01/04/2016 = 2 months
  • 01/11/2013 => 30/11/2013 = 0 months
  • 01/01/2013 => 31/12/2013 = 11 months
  • 31/01/2011 => 28/02/2011 = 1 months
  • 01/09/2009 => 01/05/2010 = 8 months
  • 01/01/2013 => 31/03/2013 = 2 months
  • 15/02/2013 => 15/04/2013 = 2 months
  • 01/02/1985 => 31/12/2013 = 346 months