我正在尝试按季度设置开始日期和结束日期。
例如,我正在开发一个报告系统,我需要报告第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;
但是现在我需要为这个和上个季度添加案例,我不知道如何实际这样做,因此它反映了适当的季度范围。
任何想法?
答案 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),
];
}
答案 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");
只是我的两分钱。