在PHP中列出两个日期之间的所有月份和年份列表

4

我希望你能够理解以下的细节。

我需要根据月份和年份的差异来列出一个月份和年份的列表。

我正在实现基于起始月份和年份以及结束月份和年份的搜索功能。

起始选择 - 01(月)- 2009(年)

结束选择 - 10(月)- 2009(年)

我所需的MySQL查询结果是:

Month                        Year
JAN                          2009
FEB                          2009
MAR                          2009
APR                          2009
MAY                          2009
JUN                          2009
JUL                          2009
AUG                          2009
SEP                          2009
OCT                          2009

6
感觉这是一个作业问题 :) - Nikhil
7个回答

9

FractalizeR的回答是正确的。

我来解释一下这些函数:

function GetMonthsFromDate($myDate) {
  $year = (int) date('Y',$myDate);
  $months = (int) date('m', $myDate);
  $dateAsMonths = 12*$year + $months;
  return $dateAsMonths;
}

function GetDateFromMonths($months) {
  $years = (int) $months / 12;
  $month = (int) $months % 12;
  $myDate = strtotime("$years/$month/01"); //makes a date like 2009/12/01
  return $myDate;
}

PS:尝试以评论的形式发布,但格式出了问题。 (当然,这些功能可以重写为一行代码,但我想让它更易读)


1
很棒的函数,尽管在GetDateFromMonths中,使用(int)$months / 12返回一个浮点数,因此无法在strtotime函数中使用。我通过替换$years = (int) ($months / 12); $month = (int) ($months % 12);来使其正常工作。 - Lenka Pitonakova
谢谢你提供这些函数,但是我遇到了一些问题,我已经在另一个答案中提供了我的解决方案。 - Wim

8

您需要编写一些函数,将日期转换为自某个日期以来经过的月数和反向转换。例如,自1980年1月起。

Jan 1980 = 0;
Dec 1980 = 12;
Jan 1981 = 13 etc.

然后你只需要使用简单的“for”循环:
for ($i = GetMonthsFromDate($StartDate), $i <= GetMonthsFromDate($StopDate), $i++) {
   echo(GetDateFromMonths($i));
}

1
这是这个问题的正确答案。 让我通过定义函数来扩展一下: function GetMonthsFromDate ($myDate) { $year = (int) date('Y',$myDate); $months = (int) date('m', $myDate); $dateAsMonths = 12*$year +months; return $dateMonths; } function GetDateFromMonths ($months) { $years = (int) $months / 12; $month = (int) $months % 12; $myDate = strtotime("$years/$month/1"); return $myDate; }(当然,这些函数可以重写为单行代码,但是希望更易读) - elviejo79

8
虽然FractalizeR的回答是正确的,但还有另一种选择。
利用strtotime('2009/08/01 - 1 month')会删除一个月的事实。
<?php
$startDate = strtotime("$startYear/$startMonth/01");
$endDate   = strtotime("$endYear/$endMonth/01");

$currentDate = $endDate;

while ($currentDate >= $startDate) {
    echo date('Y/m',$currentDate);
    $currentDate = strtotime( date('Y/m/01/',$currentDate).' -1 month');
}

再次列出月份列表


1
是的,这很完美,我认为这是快速完成任务的好东西。 - santosh
1
实际上,我更喜欢这个解决方案,而不是FractalizeR的解决方案,这应该是正确的答案。代码更直接,易于适应其他目的(只需跳过2个月、三个月或年份即可...)。 - Wim

2

这是最终答案,非常出色。

$startMonth= $_POST['startmonth'];
    $startyear= $_POST['startyear'];
    $cYear = $startyear;

    $endMonth= $_POST['endmonth'];
    $endyear= $_POST['endyear'];
    $sql = "SELECT PERIOD_DIFF(".$endyear.$endMonth.", ".$startyear.$startMonth.")";
    $queryRS =  $db->query($sql);
    $tmonthsarray = $db->fetchRow($c_jobsVat);
    $totalmonths=tmonthsarray[0];
         for($count=$startMonth; $count <= ($startMonth + $totalmonths);$count++)
         {  
            $processYear = $startyear + intval( ( $count - 1 ) / 12 );
        $processMonth= (( $count - 1 ) % 12 + 1);
        $processMonthName= date('F', mktime(0,0,0,$count));
         }

那是一个不好的解决方案,但可能有效。它涉及发出SQL查询,这需要时间。最好从PHP中完成所有操作。 - Vladislav Rastrusny

1

我根据你们的输入编写了这个函数。看看这个:

function CountTheMonth($startDate,$endDate,$order)
{
    $startDate = strtotime($startDate);
    $endDate   = strtotime($endDate);

    $ASC_Month = $startDate;
    $DESC_Month = $endDate;
    $Y_Axis = Array();

    if($order == 'DESC')//Big to small
    {
        while ($DESC_Month >= $startDate) 
        {    
            $Y_Axis[] = date('F-Y',$DESC_Month);
            $DESC_Month = strtotime( date('Y-m-d',$DESC_Month).' -1 month');
        }
        return $Y_Axis;
    }
    elseif($order == 'ASC')//Small to big
    {
        while ($ASC_Month <= $endDate) 
        {    
            $Y_Axis[] = date('F-Y',$ASC_Month);
            $ASC_Month = strtotime( date('Y-m-d',$ASC_Month).' +1 month');
        }
        return $Y_Axis;
    }
}

0

我完全同意@FractalizeR的解决方案和@elviejo的补充,它帮助了我前进。但我认为我遇到了一些问题,它们可能对其他人有所帮助:(如果我错了,请纠正我)

  1. 需要注意: $StartDate$StopDate 都是 timestamp 类型,而不是实际的 date 类型(1)。因此,我将函数参数更改为 $myTimestamp,以期不会让其他人感到困惑。

例如:

$StartDate = strtotime("Sept 2010");
$StopDate = time(); // current timestamp

对于@elviejo的函数:
  1. 类型转换:简单的(int)在我这不起作用(PHP5),所以我使用了intval()
  2. 使用%得到的结果范围是0到11,而月份的范围是1到12 (2)。因此,在函数GetDateFromMonths($months)中,我们必须对结果进行+1
  3. 由于在函数GetDateFromMonths($months)中我们将%加1,所以在函数GetMonthsFromDate($myTimestamp)中,我们将从$dateAsMonths减去1。
这给我以下代码:
function GetMonthsFromDate($myTimestamp)
{
  $year = (int) date('Y',$myTimestamp);
  $months = (int) date('m', $myTimestamp);
  $dateAsMonths = 12*$year + $months - 1;
  return $dateAsMonths;
}

function GetDateFromMonths($months)
{
  $years = intval($months / 12);
  $month = intval($months % 12) + 1;
  $myTimestamp = strtotime("$years/$month/01"); //makes a date like 2009/12/01, and translate it to a timestamp
  return $myTimestamp;
}

由以下代码启动的for循环:

for ($i = GetMonthsFromDate($StartDate); $i <= GetMonthsFromDate($StopDate); $i++)
{
    echo(date('d M Y',GetDateFromMonths($i))."</br>");
}

这样做能得到想要的结果。我的评论有意义吗?


注:

(1) 我甚至不认为date在PHP中存在,但我可能是错的。

(2) 一月是1,二月是2,...十一月是11,但十二月是0。这将无法得到所需的结果。


0

你的逻辑很好,可以获取月份列表。但是我不确定我们如何处理年份。

这是我的代码:

$startMonth= $_POST['startmonth'];

$startyear= $_POST['startyear'];

$endMonth= $_POST['endmonth'];

$endyear= $_POST['endyear'];

$sql = "SELECT PERIOD_DIFF(".$endyear.$endMonth.", ".$startyear.$startMonth.")";

$queryRS =  $db->query($sql);

$tmonthsarray = $db->fetchRow($c_jobsVat);

$totalmonths= $tmonthsarray[0]; 

for($count=$startMonth; $count <= ($startMonth + $totalmonths);$count++)
{
    echo "<BR>==>".date('F', mktime(0,0,0,$count)) ; // Months

    // what comes here in case of listing year
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接