【发布时间】:2023-04-04 20:30:01
【问题描述】:
有什么方法可以在 PHP 中找到月差?我有从 2003 年 10 月 17 日到 2004 年 3 月 24 日的输入。我需要找出这两天内有多少个月。假设如果 6 个月,我只需要几个月的输出。感谢您为我提供日差指导。
我通过 MySQL 找到了解决方案,但我需要它在 PHP 中。任何人都可以帮助我,提前谢谢。
【问题讨论】:
-
在这种情况下,一个月到底是什么?日历月? 30 天?
有什么方法可以在 PHP 中找到月差?我有从 2003 年 10 月 17 日到 2004 年 3 月 24 日的输入。我需要找出这两天内有多少个月。假设如果 6 个月,我只需要几个月的输出。感谢您为我提供日差指导。
我通过 MySQL 找到了解决方案,但我需要它在 PHP 中。任何人都可以帮助我,提前谢谢。
【问题讨论】:
无需重新发明轮子的最简单方法。这将为您提供完整个月的差异。 IE。以下两个日期相差几乎 76 个月,但结果是 75 个月。
date_default_timezone_set('Asia/Tokyo'); // you are required to set a timezone
$date1 = new DateTime('2009-08-12');
$date2 = new DateTime('2003-04-14');
$diff = $date1->diff($date2);
echo (($diff->format('%y') * 12) + $diff->format('%m')) . " full months difference";
【讨论】:
DateInterval::format 查找所有可能的格式选项。
在测试大量解决方案后,将所有解决方案都放入单元测试中,这就是我得出的结论:
/**
* Calculate the difference in months between two dates (v1 / 18.11.2013)
*
* @param \DateTime $date1
* @param \DateTime $date2
* @return int
*/
public static function diffInMonths(\DateTime $date1, \DateTime $date2)
{
$diff = $date1->diff($date2);
$months = $diff->y * 12 + $diff->m + $diff->d / 30;
return (int) round($months);
}
例如它将返回(来自单元测试的测试用例):
注意:由于它是按天四舍五入的,即使是半个月也会被四舍五入,如果你在某些情况下使用它可能会导致问题。所以不要在这种情况下使用它,它会导致你的问题。
例如:
【讨论】:
如果有人正在寻找一个简单的解决方案来计算每个涉及的月份而不是完整的月份、四舍五入的月份或类似的东西,我只是想添加这个。
// Build example data
$timeStart = strtotime("2003-10-17");
$timeEnd = strtotime("2004-03-24");
// Adding current month + all months in each passed year
$numMonths = 1 + (date("Y",$timeEnd)-date("Y",$timeStart))*12;
// Add/subtract month difference
$numMonths += date("m",$timeEnd)-date("m",$timeStart);
echo $numMonths;
【讨论】:
哇,想太多问题了……这个版本怎么样:
function monthsBetween($startDate, $endDate) {
$retval = "";
// Assume YYYY-mm-dd - as is common MYSQL format
$splitStart = explode('-', $startDate);
$splitEnd = explode('-', $endDate);
if (is_array($splitStart) && is_array($splitEnd)) {
$difYears = $splitEnd[0] - $splitStart[0];
$difMonths = $splitEnd[1] - $splitStart[1];
$difDays = $splitEnd[2] - $splitStart[2];
$retval = ($difDays > 0) ? $difMonths : $difMonths - 1;
$retval += $difYears * 12;
}
return $retval;
}
注意:与其他几个解决方案不同,这不依赖于 PHP 5.3 中添加的日期函数,因为许多共享主机还没有。
【讨论】:
$retval = ($difDays > 0) ? $difMonths : $difMonths - 1; 编辑为 $retval = ($difDays >= 0) ? $difMonths : $difMonths - 1; 所以 2017-02-01 和 2017-03-01 之间的差异只有 1
http://www.php.net/manual/en/datetime.diff.php
这将返回一个具有格式方法的 DateInterval 对象。
【讨论】:
$datetime1 = date_create('2009-10-11');
$datetime2 = date_create('2013-1-13');
$interval = date_diff($datetime1, $datetime2);
echo $interval->format('%a day %m month %y year');
【讨论】:
function monthsDif($start, $end)
{
// Assume YYYY-mm-dd - as is common MYSQL format
$splitStart = explode('-', $start);
$splitEnd = explode('-', $end);
if (is_array($splitStart) && is_array($splitEnd)) {
$startYear = $splitStart[0];
$startMonth = $splitStart[1];
$endYear = $splitEnd[0];
$endMonth = $splitEnd[1];
$difYears = $endYear - $startYear;
$difMonth = $endMonth - $startMonth;
if (0 == $difYears && 0 == $difMonth) { // month and year are same
return 0;
}
else if (0 == $difYears && $difMonth > 0) { // same year, dif months
return $difMonth;
}
else if (1 == $difYears) {
$startToEnd = 13 - $startMonth; // months remaining in start year(13 to include final month
return ($startToEnd + $endMonth); // above + end month date
}
else if ($difYears > 1) {
$startToEnd = 13 - $startMonth; // months remaining in start year
$yearsRemaing = $difYears - 2; // minus the years of the start and the end year
$remainingMonths = 12 * $yearsRemaing; // tally up remaining months
$totalMonths = $startToEnd + $remainingMonths + $endMonth; // Monthsleft + full years in between + months of last year
return $totalMonths;
}
}
else {
return false;
}
}
【讨论】:
// get year and month difference
$a1 = '20170401';
$a2 = '20160101'
$yearDiff = (substr($a1, 0, 4) - substr($a2, 0, 4));
$monthDiff = (substr($a1, 4, 2) - substr($a2, 4, 2));
$fullMonthDiff = ($yearDiff * 12) + $monthDiff;
// fullMonthDiff = 16
【讨论】:
这是我的增强版@deceze 答案:
/**
* @param string $startDate
* Current date is considered if empty string is passed
* @param string $endDate
* Current date is considered if empty string is passed
* @param bool $unsigned
* If $unsigned is true, difference is always positive, otherwise the difference might be negative
* @return int
*/
public static function diffInFullMonths($startDate, $endDate, $unsigned = false)
{
$diff = (new DateTime($startDate))->diff(new DateTime($endDate));
$reverse = $unsigned === true ? '' : '%r';
return ((int) $diff->format("{$reverse}%y") * 12) + ((int) $diff->format("{$reverse}%m"));
}
【讨论】:
最好的方法。
function getIntervals(DateTime $from, DateTime $to)
{
$intervals = [];
$startDate = $from->modify('first day of this month');
$endDate = $to->modify('last day of this month');
while($startDate < $endDate){
$firstDay = $startDate->format('Y-m-d H:i:s');
$startDate->modify('last day of this month')->modify('+1 day');
$intervals[] = [
'firstDay' => $firstDay,
'lastDay' => $startDate->modify('-1 second')->format('Y-m-d H:i:s'),
];
$startDate->modify('+1 second');
}
return $intervals;
}
$dateTimeFirst = new \DateTime('2013-01-01');
$dateTimeSecond = new \DateTime('2013-03-31');
$interval = getIntervals($dateTimeFirst, $dateTimeSecond);
print_r($interval);
结果:
Array
(
[0] => Array
(
[firstDay] => 2013-01-01 00:00:00
[lastDay] => 2013-01-31 23:59:59
)
[1] => Array
(
[firstDay] => 2013-02-01 00:00:00
[lastDay] => 2013-02-28 23:59:59
)
[2] => Array
(
[firstDay] => 2013-03-01 00:00:00
[lastDay] => 2013-03-31 23:59:59
)
)
【讨论】:
在我的情况下,我还需要计算整月和一天的剩余时间以及构建折线图标签。
/**
* Calculate the difference in months between two dates
*
* @param \DateTime $from
* @param \DateTime $to
* @return int
*/
public static function diffInMonths(\DateTime $from, \DateTime $to)
{
// Count months from year and month diff
$diff = $to->diff($from)->format('%y') * 12 + $to->diff($from)->format('%m');
// If there is some day leftover, count it as the full month
if ($to->diff($from)->format('%d') > 0) $diff++;
// The month count isn't still right in some cases. This covers it.
if ($from->format('d') >= $to->format('d')) $diff++;
}
【讨论】:
<?php
# end date is 2008 Oct. 11 00:00:00
$_endDate = mktime(0,0,0,11,10,2008);
# begin date is 2007 May 31 13:26:26
$_beginDate = mktime(13,26,26,05,31,2007);
$timestamp_diff= $_endDate-$_beginDate +1 ;
# how many days between those two date
$days_diff = $timestamp_diff/2635200;
?>
【讨论】:
这是一个快速的:
$date1 = mktime(0,0,0,10,0,2003); // m d y, use 0 for day
$date2 = mktime(0,0,0,3,0,2004); // m d y, use 0 for day
echo round(($date2-$date1) / 60 / 60 / 24 / 30);
【讨论】:
31 days 以防January, March, May, July, August, October, December 或28 days 以防February 会发生什么,因为你除以30。