获取当前季度php的startdate和enddate

时间:2014-01-17 12:21:44

标签: php codeigniter date

我正在尝试按季度设置开始日期和结束日期。

例如,我正在开发一个报告系统,我需要报告第1季度,第2季度,第3季度和第4季度的数据。

第一季度 - 1月至3月

第二季度 - 四月 - 六月

第三季度 - 七月至九月

第四季度 - 十月 - 十二月

我举例说明当月和上个月的一些案例,如下所示。

   case 'this_month':
      $start_date = date(DATE_FORMAT, mktime(0, 0, 0, date("m"), 1, date("Y")));
      $end_date = date(DATE_FORMAT, mktime(0, 0, 0, date("m"), date("d"), date("Y")));
    break;
    case 'last_month':
      $start_date = date(DATE_FORMAT, mktime(0, 0, 0, date("m") - 1, 1, date("Y")));
      $end_date = date(DATE_FORMAT, mktime(0, 0, 0, date("m"), 0, date("Y")));
    break;

但是现在我需要为这个和上个季度添加案例,我不知道如何实际这样做,因此它反映了适当的季度范围。

任何想法?

21 个答案:

答案 0 :(得分:18)

/**
* Compute the start and end date of some fixed o relative quarter in a specific year.
* @param mixed $quarter  Integer from 1 to 4 or relative string value:
*                        'this', 'current', 'previous', 'first' or 'last'.
*                        'this' is equivalent to 'current'. Any other value
*                        will be ignored and instead current quarter will be used.
*                        Default value 'current'. Particulary, 'previous' value
*                        only make sense with current year so if you use it with
*                        other year like: get_dates_of_quarter('previous', 1990)
*                        the year will be ignored and instead the current year
*                        will be used.
* @param int $year       Year of the quarter. Any wrong value will be ignored and
*                        instead the current year will be used.
*                        Default value null (current year).
* @param string $format  String to format returned dates
* @return array          Array with two elements (keys): start and end date.
*/
public static function get_dates_of_quarter($quarter = 'current', $year = null, $format = null)
{
    if ( !is_int($year) ) {        
       $year = (new DateTime)->format('Y');
    }
    $current_quarter = ceil((new DateTime)->format('n') / 3);
    switch (  strtolower($quarter) ) {
    case 'this':
    case 'current':
       $quarter = ceil((new DateTime)->format('n') / 3);
       break;

    case 'previous':
       $year = (new DateTime)->format('Y');
       if ($current_quarter == 1) {
          $quarter = 4;
          $year--;
        } else {
          $quarter =  $current_quarter - 1;
        }
        break;

    case 'first':
        $quarter = 1;
        break;

    case 'last':
        $quarter = 4;
        break;

    default:
        $quarter = (!is_int($quarter) || $quarter < 1 || $quarter > 4) ? $current_quarter : $quarter;
        break;
    }
    if ( $quarter === 'this' ) {
        $quarter = ceil((new DateTime)->format('n') / 3);
    }
    $start = new DateTime($year.'-'.(3*$quarter-2).'-1 00:00:00');
    $end = new DateTime($year.'-'.(3*$quarter).'-'.($quarter == 1 || $quarter == 4 ? 31 : 30) .' 23:59:59');

    return array(
        'start' => $format ? $start->format($format) : $start,
        'end' => $format ? $end->format($format) : $end,
    );
}

我开发此功能以任何方式处理季度:相对(此,前一个,第一个,最后一个)和固定。

示例:

get_dates_of_quarter();
//return current quarter start and end dates

get_dates_of_quarter(2);
//return 2nd quarter start and end dates of current year

get_dates_of_quarter('first', 2010, 'Y-m-d');
//return start='2010-01-01' and end='2014-03-31'

get_dates_of_quarter('current', 2009, 'Y-m-d');
//Supposing today is '2014-08-22' (3rd quarter), this will return
//3rd quarter but of year 2009.
//return start='2009-07-01' and end='2009-09-30'

get_dates_of_quarter('previous');
//Supposing today is '2014-02-18' (1st quarter), this will return
//return start='2013-10-01' and end='2013-12-31'

等待这个帮助某人;)

答案 1 :(得分:11)

怎么样:

$offset = (date('n')%3)-1; // modulo ftw
$start = new DateTime("first day of -$offset month midnight");
$offset = 3-(date('n')%3); // modulo ftw again
$end = new DateTime("last day of +$offset month midnight");

答案 2 :(得分:8)

选中this quarter

 case 'this_quarter':

          $current_month = date('m');
          $current_year = date('Y');
          if($current_month>=1 && $current_month<=3)
          {
            $start_date = strtotime('1-January-'.$current_year);  // timestamp or 1-Januray 12:00:00 AM
            $end_date = strtotime('1-April-'.$current_year);  // timestamp or 1-April 12:00:00 AM means end of 31 March
          }
          else  if($current_month>=4 && $current_month<=6)
          {
            $start_date = strtotime('1-April-'.$current_year);  // timestamp or 1-April 12:00:00 AM
            $end_date = strtotime('1-July-'.$current_year);  // timestamp or 1-July 12:00:00 AM means end of 30 June
          }
          else  if($current_month>=7 && $current_month<=9)
          {
            $start_date = strtotime('1-July-'.$current_year);  // timestamp or 1-July 12:00:00 AM
            $end_date = strtotime('1-October-'.$current_year);  // timestamp or 1-October 12:00:00 AM means end of 30 September
          }
          else  if($current_month>=10 && $current_month<=12)
          {
            $start_date = strtotime('1-October-'.$current_year);  // timestamp or 1-October 12:00:00 AM
            $end_date = strtotime('1-January-'.($current_year+1));  // timestamp or 1-January Next year 12:00:00 AM means end of 31 December this year
          }



        break;

更新:2 并为last quarter

case 'last_quarter':

          $current_month = date('m');
          $current_year = date('Y');

          if($current_month>=1 && $current_month<=3)
          {
            $start_date = strtotime('1-October-'.($current_year-1));  // timestamp or 1-October Last Year 12:00:00 AM
            $end_date = strtotime('1-January-'.$current_year);  // // timestamp or 1-January  12:00:00 AM means end of 31 December Last year
          } 
          else if($current_month>=4 && $current_month<=6)
          {
            $start_date = strtotime('1-January-'.$current_year);  // timestamp or 1-Januray 12:00:00 AM
            $end_date = strtotime('1-April-'.$current_year);  // timestamp or 1-April 12:00:00 AM means end of 31 March
          }
          else  if($current_month>=7 && $current_month<=9)
          {
            $start_date = strtotime('1-April-'.$current_year);  // timestamp or 1-April 12:00:00 AM
            $end_date = strtotime('1-July-'.$current_year);  // timestamp or 1-July 12:00:00 AM means end of 30 June
          }
          else  if($current_month>=10 && $current_month<=12)
          {
            $start_date = strtotime('1-July-'.$current_year);  // timestamp or 1-July 12:00:00 AM
            $end_date = strtotime('1-October-'.$current_year);  // timestamp or 1-October 12:00:00 AM means end of 30 September
          }



        break;

答案 3 :(得分:6)

简单代码:

$current_quarter = ceil(date('n') / 3);
$first_date = date('Y-m-d', strtotime(date('Y') . '-' . (($current_quarter * 3) - 2) . '-1'));
$last_date = date('Y-m-t', strtotime(date('Y') . '-' . (($current_quarter * 3)) . '-1'));

答案 4 :(得分:4)

有些答案太复杂了IMO

background-color : black

答案 5 :(得分:2)

我认为这可能更加简单。

function get_this_quarter() {
    $current_month = date('m');
    $current_quarter_start = ceil($current_month/4)*3+1; // get the starting month of the current quarter
    $start_date = date("Y-m-d H:i:s", mktime(0, 0, 0, $current_quarter_start, 1, date('Y') ));
    $end_date = date("Y-m-d H:i:s", mktime(0, 0, 0, $current_quarter_start+3, 1, date('Y') ));
    // by adding or subtracting from $current_quarter_start within the mktime function you can get any quarter of any year you want.
    return array($start_date, $end_date);
}

在没有所有if语句的情况下,这种方法同样有效,并且更加灵活。如代码中的注释所述,您可以轻松修改$ current_quarter_variable以满足您的需求。

希望这有帮助!

答案 6 :(得分:2)

尝试使用DateTime功能。对于您的示例,看起来像:

case 'this_month':
    $start_date = new DateTime('first day of this month');
    $end_date = new DateTime('last day of this month');
break;
case 'last_month':
    $start_date = new DateTime('first day of next month');
    $end_date = new DateTime('last day of next month');
break;

echo $start_date->format(DATE_FORMAT);
echo $end_date->format(DATE_FORMAT);

如果您想获得季度的第一天和最后一天,请尝试使用:

 $start_date = new DateTime('first day of January');
 $end_date = new DateTime('last day of March');

 echo $start_date->format(DATE_FORMAT);
 echo $end_date->format(DATE_FORMAT);

或使用函数strtotime。 strtotime示例:

$quarter_start = strtotime('first day of January');
$quarter_end = strtotime('last day of March');

echo date(DATE_FORMAT, $quarter_start);
echo date(DATE_FORMAT, $quarter_end);

答案 7 :(得分:1)

简单示例:

define('DATE_FORMAT', 'Y-m-d');

function get_start_and_end_date($case) {
    $start = 'first day of ';
    $end = 'last day of ';

    if ($case == 'this_quarter') {
        $case = 'quarter_' . ceil((new DateTime)->format('n') / 3);
    }

    switch ($case) {
        case 'prev_month'    : $start .= 'previous month'; $end .= 'previous month'; break;
        default              :
        case 'this_month'    : $start .= 'this month';     $end .= 'this month';     break;
        case 'next_month'    : $start .= 'next month';     $end .= 'next month';     break;
        case 'first_quarter' :
        case 'quarter_1'     : $start .= 'January';        $end .= 'March';          break;
        case 'quarter_2'     : $start .= 'April';          $end .= 'June';           break;
        case 'quarter_3'     : $start .= 'July';           $end .= 'September';      break;
        case 'last_quarter'  :
        case 'quarter_4'     : $start .= 'October';        $end .= 'December';       break;
    }

    return [
        'start' => (new DateTime($start))->format(DATE_FORMAT),
        'end' => (new DateTime($end))->format(DATE_FORMAT),
    ];
}

demo

答案 8 :(得分:1)

只想指出SynaTree的解决方案不适用于本季度的最后三个月。

这是使用DateTime的修改后的解决方案。

$now = new DateTimeImmutable();
$offset = ($now->format('n') - 1) % 3;
$start = $now->modify("first day of -{$offset} month midnight");
$endExcluded = $start->modify("+3 month");
$endIncluded = $start->modify("+3 month -1 second");

$endExcluded在DatePeriod循环中效果很好,当时间为00:00:00时,结束日期被排除在外。

答案 9 :(得分:0)

我最终得到了这个简单的解决方案:

$curQuarter = ceil(date("m")/3);
$startDate = date("Y") . "-" . $curQuarter*3-2 . "-01";
$endDate = date("Y") . "-" . $curQuarter*3 . "-31";

(是的,有些月份不会有31天但在我的情况下并不重要)

答案 10 :(得分:0)

使用下面的代码,我们可以获得当前季度的开始日期。

$intCurrentMonth               = date( 'n' );
$fltCurrentQuarter             = ( $intCurrentMonth - 1 ) / 3;
$intCurrentQuarter             = ( int ) $fltCurrentQuarter;
$fltCurrentQuarterMantissa     = $fltCurrentQuarter - $intCurrentQuarter;
$fltCurrentQuarterMantissa     = ( int ) ( $fltCurrentQuarterMantissa * 100 ) / 100;
$intFirstMonthOfCurrentQuarter = $intCurrentMonth - ceil( $fltCurrentQuarterMantissa * 3 );
$strFirstDateOfCurrentQuarter  = date( 'm/d/Y', strtotime( $intFirstMonthOfCurrentQuarter . '/01' ) );

有很大的优化空间。

答案 11 :(得分:0)

$QuarterMonth = ["1" => ["Y-01-01","Y-03-31"],"2"=>["Y-04-01","Y-06-30"],"3"=>["Y-07-01","Y-09-30"],"4"=>["Y-10-01","Y-12-31"]];
$curMonth = date("m", time());

$qtr_month_from = date($QuarterMonth[ceil($curMonth/3)][0]);
$qtr_month_to = date($QuarterMonth[ceil($curMonth/3)][1]);

答案 12 :(得分:0)

通用版本为:

    $date = new DateTime(/* you may insert a date here, else its now */);
    //$date->modify('-3 months'); // you may want last quarter or any other modifcation
    $quarter = ceil($date->format('n')/3);

    $start = new DateTime();
    $start->setDate($date->format('Y'), (($quarter*3)-2), 1)->setTime(0, 0, 0, 0);

    $end = new DateTime();
    $end->setDate($date->format('Y'), ($quarter*3), 1);
    $end->setDate($date->format('Y'), ($quarter*3), $end->format('t'))->setTime(0, 0, 0, 0);

    echo $start->format('Y-m-d');
    echo $end->format('Y-m-d');

这很简单但有效。您可以选择输入日期并通过修改进行相对调整。

答案 13 :(得分:0)

我不确定为什么这么难-几个解决方案在这里确实很接近,但是没有找到季度的第一天和最后一天。宿舍不会在第一个宿舍结束!

从上面的KLOZ修改:

    $current_quarter = ceil(date('n') / 3);
    $first_day_of_this_quarter = date('m/d/Y', strtotime(date('Y').'-'.(($current_quarter*3)-2).'-1'));
    $last_day_of_this_quarter = date('m/d/Y', strtotime(date('Y').'-'.($current_quarter*3).'-'.(date("t",date('Y').'-'.($current_quarter*3).'-1'))));

答案 14 :(得分:0)

我需要一些功能来给我每个季度的日期,以便我可以获取一些销售信息。这是任何人需要的代码:

   private function getQuarterRange($quarter, $year=null) {
        if ($quarter > 4 || $quarter < 1)
            return null;

        if ($year == null)
            $year = date('Y');


        $startDate = date('Y-m-d', strtotime($year . '-' . (($quarter * 3) - 2). '-1'));
        $endDate = date('Y-m-d', strtotime(date('Y-m-d', strtotime($startDate)) . '+3 month - 1 day'));
        return ['startDate' => $startDate, 'endDate' => $endDate];
    }

只需致电:var_dump($this->getQuarterRange(4, 2018)); 输出:

array(2) {
  ["startDate"]=>
  string(10) "2018-10-01"
  ["endDate"]=>
  string(10) "2018-12-31"
}

答案 15 :(得分:0)

我瞥见了答案,所有内容都在今年的四分之一左右。 有时,您需要特定日期的季度。 这是我尝试的详细解释,代码注释中的内容:

/**
     * get quarter begin/end date
     * 
     * possible usage:
     * quarter start date: quarter('2016-04-12')[start] - result: 2016-04-01
     * quarter end date: quarter('2016-04-12')[end] - result: 2016-06-30
     * quarter number: quarter('2016-04-12')[number] - result: 2
     * 
     * @param  string   $time   date you want quarter begin and end for - accepted formats, at least: 'Y-m', but also: 'Y-m-d', 'Y-m-d H:i:s' etc.
     * @return array    [quarter start, quarter end, quarter number]
     */
    public function quarter($time)
    {
        /**
         * get quarter number for given date
         * we are ceiling floating point value, so I use (int) casting to get just integer (without decimal part)
         * round() could be used instead of casting to (int)
         */
        $quarter = (int)ceil(date("m", strtotime($time)) / 3);
        $year = date("Y", strtotime($time));

        $quarters = [
            1 => ['01-01', '03-31', 1],
            2 => ['04-01', '06-30', 2],
            3 => ['07-01', '09-30', 3],
            4 => ['10-01', '12-31', 4],
        ];

        $quarterStart = $year . '-' . $quarters[$quarter][0];
        $quarterEnd = $year . '-' . $quarters[$quarter][1];
        $quarterNumber = $quarters[$quarter][2];

        return ['start' => $quarterStart, 'end' => $quarterEnd, 'number' => $quarterNumber];
    }

答案 16 :(得分:0)

$monthsFromStart = (date('n') - 1) % 3; // 0, 1, 2, 0, 1, 2, ...
$monthsToEnd = 2 - $monthsFromStart; // 2, 1, 0, 2, 1, 0, ...

$startDay = new DateTime("first day of -$monthsFromStart month midnight");
$endDay = new DateTime("last day of +$monthsToEnd month midnight");

答案 17 :(得分:0)

您可以使用基本数学来大大简化这一点。

每个月数减1%3将告知您从当前季度偏移了多少个月..

/**
 * @param DateTime $date
 * @return array
 */
function getQuarterRangeFromDate(DateTime $date)
{

    // Clone the date to avoid modifying your date in current context
    $quarter_start = clone($date);

    // Find the offset of months
    $months_offset = ($date->format('m') - 1) % 3;


    // Modify quarter date
    $quarter_start->modify(" - " . $months_offset . " month")
        ->modify("first day of this month");


    $quarter_end = clone($quarter_start);
    $quarter_end->modify("+ 3 month");

    return [$quarter_start, $quarter_end];
}

答案 18 :(得分:0)

这是我的解决方案。

function getCurrentQuarter($timestamp=false){
    if(!$timestamp)$timestamp=time();
    $day = date('n', $timestamp);
    $quarter = ceil($day/3);
    return $quarter;
}

function getPreviousQuarter($timestamp=false){
    if(!$timestamp)$timestamp=time();
    $quarter = getCurrentQuarter($timestamp) - 1;
    if($quarter < 0){
        $quarter = 4;
    }
    return $quarter;
}

function getNextQuarter($timestamp=false){
    if(!$timestamp)$timestamp=time();
    $quarter = getCurrentQuarter($timestamp) + 1;
    if($quarter > 4){
        $quarter = 0;
    }
    return $quarter;
}

function getFirstAndLastDayOfQuarter($quarter, $year=false){
    if(!$year)$year=date('Y');
    $startDate = new DateTime($year.'-'.($quarter*3-2).'-1');
    //Get first day of first month of next quarter
    $endMonth = $quarter*3+1;
    if($endMonth>12){
        $endMonth = 1;
        $year++;
    }
    $endDate = new DateTime($year.'-'.$endMonth.'-1');
    //Subtract 1 second to get last day of prior month
    $endDate->sub(new DateInterval('PT1S'));
    return array($startDate, $endDate);
}

答案 19 :(得分:0)

function getDates( $passedDate = '' ) {
    if( $passedDate == '' ) {
        $v = ceil( date( "m" ) / 3 );
        $y = date( "Y" );
    } else {
        $v = ceil( $month / 3 );
        $y = date( "Y", strtotime( $passedDate ) );
    }
    $y = date( "Y" );
    $m = ( $v * 3 ) - 2;
    $date = $y . '-' . $m . '-' . 01;
    $return['begin'] = date( "Y-m-d", strtotime(  $date ) );
    $return['end'] = date( "Y-m-t", strtotime( $return['begin'] . "+ 2 months"  ) );
    $return['version'] = $y . 'Q' . ceil( date( "m" ) / 4 );
    return $return;
}

默认情况下,此函数将返回当前日期的开始日期和结束日期和季度,但是如果您希望特定日期只需将月份传递给它。

答案 20 :(得分:-1)

在日期中获取当前季度开始/结束的更简单方法:

$qtr_start = date("Y-".(ceil(date("n")/3))."-01");

然后,只需在正确的位置添加3个月即可结束:

$qtr_end = date("Y-".(ceil(date("n")/3)+3)."-01");

只是我的两分钱。