Я пытаюсь установить дату начала и дату окончания квартала.
Например, я работаю над системой отчетности, где мне нужно сообщать данные за 1 квартал, квартал 2, квартал 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;
Но теперь мне нужно добавить случаи для этого и последнего квартала, и я не уверен, как это сделать, чтобы он соответствовал правильному диапазону кварталов.
Есть идеи?
проверьте это на 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;
/** * 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, 'Ym-d'); //return start='2010-01-01' and end='2014-03-31' get_dates_of_quarter('current', 2009, 'Ym-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'
В ожидании этой помощи кто-то;)
как насчет:
$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");
Простой код:
$current_quarter = ceil(date('n') / 3); $first_date = date('Ym-d', strtotime(date('Y') . '-' . (($current_quarter * 3) - 2) . '-1')); $last_date = date('Ym-t', strtotime(date('Y') . '-' . (($current_quarter * 3)) . '-1'));
Попробуйте использовать функцию 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);
Некоторые ответы слишком сложны. ИМО
public function getStartOfQuarter() { return date(sprintf('Y-%s-01', floor((date('n') - 1) / 3) * 3 + 1)); } public function getEndOfQuarter() { return date(sprintf('Y-%s-t', floor((date('n') + 2) / 3) * 3)); }
Простой пример:
define('DATE_FORMAT', 'Ym-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), ]; }
демонстрация
Думаю, это было бы намного проще.
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("Ymd H:i:s", mktime(0, 0, 0, $current_quarter_start, 1, date('Y') )); $end_date = date("Ymd 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 в соответствии с вашими потребностями.
Надеюсь это поможет!
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( "Ymd", strtotime( $date ) ); $return['end'] = date( "Ymt", strtotime( $return['begin'] . "+ 2 months" ) ); $return['version'] = $y . 'Q' . ceil( date( "m" ) / 4 ); return $return; }
Эта функция вернет начальную и конечную дату и квартал по текущей дате по умолчанию, однако, если вы хотите, чтобы на конкретную дату только месяц прошел к ней.
Это было мое решение.
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); }
в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); }
,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); }
Вы можете просто это использовать с помощью базовой математики.
Количество каждого месяца минус 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]; }
Я закончил с этим простым решением:
$curQuarter = ceil(date("m")/3); $startDate = date("Y") . "-" . $curQuarter*3-2 . "-01"; $endDate = date("Y") . "-" . $curQuarter*3 . "-31";
(Да, некоторые месяцы не будут иметь 31 день, но в моем случае это не имело значения)
$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");
Более простой способ получить начало / конец текущего квартала в датах:
$qtr_start = date("Y-".(ceil(date("n")/3))."-01");
Затем просто добавьте 3 месяца в правильное место, чтобы закончить:
$qtr_end = date("Y-".(ceil(date("n")/3)+3)."-01");
Только мои два цента.