Calculate week of a month [duplicate] - php

So I have a script that returns the number of weeks in a particular month and year. How can I take a specific day from that month and determine if it is part of week 1,2,3,4 or 5 of that month?

The most frustrating thing I have ever tried to get working - but here it is!
<?php
/**
* Returns the amount of weeks into the month a date is
* #param $date a YYYY-MM-DD formatted date
* #param $rollover The day on which the week rolls over
*/
function getWeeks($date, $rollover)
{
$cut = substr($date, 0, 8);
$daylen = 86400;
$timestamp = strtotime($date);
$first = strtotime($cut . "00");
$elapsed = ($timestamp - $first) / $daylen;
$weeks = 1;
for ($i = 1; $i <= $elapsed; $i++)
{
$dayfind = $cut . (strlen($i) < 2 ? '0' . $i : $i);
$daytimestamp = strtotime($dayfind);
$day = strtolower(date("l", $daytimestamp));
if($day == strtolower($rollover)) $weeks ++;
}
return $weeks;
}
//
echo getWeeks("2011-06-11", "sunday"); //outputs 2, for the second week of the month
?>

Edit: so much for "single line" - needed variables to avoid recomputation with the conditional. Tossed in a default argument while I was at it.
function weekOfMonth($when = null) {
if ($when === null) $when = time();
$week = date('W', $when); // note that ISO weeks start on Monday
$firstWeekOfMonth = date('W', strtotime(date('Y-m-01', $when)));
return 1 + ($week < $firstWeekOfMonth ? $week : $week - $firstWeekOfMonth);
}
Please note that weekOfMonth(strtotime('Oct 31, 2011')); will return 6; some rare months have 6 weeks in them, contrary to OP's expectation. January 2017 is another month with 6 ISO weeks - Sunday the 1st falls in the last year's week, since ISO weeks start on Monday.
For starshine531, to return a 0 indexed week of the month, change the return 1 + to return 0 + or return (int).
For Justin Stayton, for weeks starting on Sunday instead of Monday I would use strftime('%U' instead of date('W', as follows:
function weekOfMonth($when = null) {
if ($when === null) $when = time();
$week = strftime('%U', $when); // weeks start on Sunday
$firstWeekOfMonth = strftime('%U', strtotime(date('Y-m-01', $when)));
return 1 + ($week < $firstWeekOfMonth ? $week : $week - $firstWeekOfMonth);
}
For this version, 2017-04-30 is now in week 6 of April, while 2017-01-31 is now in week 5.

public function getWeeks($timestamp)
{
$maxday = date("t",$timestamp);
$thismonth = getdate($timestamp);
$timeStamp = mktime(0,0,0,$thismonth['mon'],1,$thismonth['year']); //Create time stamp of the first day from the give date.
$startday = date('w',$timeStamp); //get first day of the given month
$day = $thismonth['mday'];
$weeks = 0;
$week_num = 0;
for ($i=0; $i<($maxday+$startday); $i++) {
if(($i % 7) == 0){
$weeks++;
}
if($day == ($i - $startday + 1)){
$week_num = $weeks;
}
}
return $week_num;
}
Hello all i have been struggling for the whole day trying to figure this code out, i finally figured it out so i thought i would share it with you all.
all you need to do is put a time stamp into the function and it will return the week number back to you.
thanks

there is a problem with this method. if the passing date (Lets say 2012/01/01 which is a Sunday) and "$rollover" day is "Sunday", then this function will return 2. where its actually is 1'st week. i think i have fixed it in following function.
please add comments to make it better.
function getWeeks($date, $rollover)
{
$cut = substr($date, 0, 8);
$daylen = 86400;
$timestamp = strtotime($date);
$first = strtotime($cut . "01");
$elapsed = (($timestamp - $first) / $daylen)+1;
$i = 1;
$weeks = 0;
for($i==1; $i<=$elapsed; $i++)
{
$dayfind = $cut . (strlen($i) < 2 ? '0' . $i : $i);
$daytimestamp = strtotime($dayfind);
$day = strtolower(date("l", $daytimestamp));
if($day == strtolower($rollover))
{
$weeks++;
}
}
if($weeks==0)
{
$weeks++;
}
return $weeks;
}

This is a solution based on sberry's mathematical solution but using the PHP DateTime class instead.
function week_of_month($date) {
$first_of_month = new DateObject($date->format('Y/m/1'));
$day_of_first = $first_of_month->format('N');
$day_of_month = $date->format('j');
return floor(($day_of_first + $day_of_month - 1) / 7) + 1;
}

Just Copy and Past the code and pass month and year.
e.g month=04 year=2013.
That's exactly what You Need.
$mm= $_REQUEST['month'];
$yy= $_REQUEST['year'];
$startdate=date($yy."-".$mm."-01") ;
$current_date=date('Y-m-t');
$ld= cal_days_in_month(CAL_GREGORIAN, $mm, $yy);
$lastday=$yy.'-'.$mm.'-'.$ld;
$start_date = date('Y-m-d', strtotime($startdate));
$end_date = date('Y-m-d', strtotime($lastday));
$end_date1 = date('Y-m-d', strtotime($lastday." + 6 days"));
$count_week=0;
$week_array = array();
for($date = $start_date; $date <= $end_date1; $date = date('Y-m-d', strtotime($date. ' + 7 days')))
{
$getarray=getWeekDates($date, $start_date, $end_date);
echo "<br>";
$week_array[]=$getarray;
echo "\n";
$count_week++;
}
// its give the number of week for the given month and year
echo $count_week;
//print_r($week_array);
function getWeekDates($date, $start_date, $end_date)
{
$week = date('W', strtotime($date));
$year = date('Y', strtotime($date));
$from = date("Y-m-d", strtotime("{$year}-W{$week}+1"));
if($from < $start_date) $from = $start_date;
$to = date("Y-m-d", strtotime("{$year}-W{$week}-6"));
if($to > $end_date) $to = $end_date;
$array1 = array(
"ssdate" => $from,
"eedate" => $to,
);
return $array1;
// echo "Start Date-->".$from."End Date -->".$to;
}
for($i=0;$i<$count_week;$i++)
{
$start= $week_array[$i]['ssdate'];
echo "--";
$week_array[$i]['eedate'];
echo "<br>";
}
OUTPUT:
week( 0 )=>2013-03-01---2013-03-02
week( 1 )=>2013-03-03---2013-03-09
week( 2 )=>2013-03-10---2013-03-16
week( 3 )=>2013-03-17---2013-03-23
week( 4 )=>2013-03-24---2013-03-30
week( 5 )=>2013-03-31---2013-03-31

I think I found an elegant solution
$time = time(); // or whenever
$week_of_the_month = ceil(date('d', $time)/7);

For a Monday-Sunday (ISO 8601) week (or, if you simply don't care), you can do this in one line:
function get_week_of_month($date) {
return date('W', $date) - date('W', strtotime(date("Y-m-01", $date))) + 1;
}
(Source)
For anything else, (e.g. a Sunday-Saturday week), you just need to tweak $date inside the function:
function get_week_of_month($date) {
$date += 86400; //For weeks starting on Sunday
return date('W', $date) - date('W', strtotime(date("Y-m-01", $date))) + 1;
}
(Thanks to these guys/gals)
NOTE: You may run into some issues at the end of the year (e.g. around 12/31, 1/1, etc.). Read more here.

This is the snippet that I made to fulfill my requirements for the same. Hope this will help you.
function getWeek($timestamp) {
$week_year = date('W',$timestamp);
$week = 0;//date('d',$timestamp)/7;
$year = date('Y',$timestamp);
$month = date('m',$timestamp);
$day = date('d',$timestamp);
$prev_month = date('m',$timestamp) -1;
if($month != 1 ){
$last_day_prev = $year."-".$prev_month."-1";
$last_day_prev = date('t',strtotime($last_day_prev));
$week_year_last_mon = date('W',strtotime($year."-".$prev_month."-".$last_day_prev));
$week_year_first_this = date('W',strtotime($year."-".$month."-1"));
if($week_year_first_this == $week_year_last_mon){
$week_diff = 0;
}
else{
$week_diff = 1;
}
if($week_year ==1 && $month == 12 ){
// to handle December's last two days coming in first week of January
$week_year = 53;
}
$week = $week_year-$week_year_last_mon + 1 +$week_diff;
}
else{
// to handle first three days January coming in last week of December.
$week_year_first_this = date('W',strtotime($year."-01-1"));
if($week_year_first_this ==52 || $week_year_first_this ==53){
if($week_year == 52 || $week_year == 53){
$week =1;
}
else{
$week = $week_year + 1;
}
}
else{
$week = $week_year;
}
}
return $week;
}

This is probably not a good way to do this but it's my first thought and I'm really tired.
Put all your dates into an array. The date object must have a day name (Monday). Create a method that searches the array and when ever you hit a Sunday you add 1 to a week counter. Once you find the date you're looking for return the week counter. That is the week the day falls in of the year. For the week in the month you have to reset the week counter every time you get to the last day in each month.

Here comes two liner:
function getWeekOfMonth(DateTime $date) {
$firstDayOfMonth = new DateTime($date->format('Y-m-1'));
return ceil(($firstDayOfMonth->format('N') + $date->format('j') - 1) / 7);
}
And Wtower's solutions doesn't work 100% properly.

Thought I'd share my function as well. This returns an array of weeks. Every week is an array with weeks day (0..6) as key and months day (1..31) as value.
Function assumes that week starts with Sunday.
Enjoy!
function get_weeks($year, $month){
$days_in_month = date("t", mktime(0, 0, 0, $month, 1, $year));
$weeks_in_month = 1;
$weeks = array();
//loop through month
for ($day=1; $day<=$days_in_month; $day++) {
$week_day = date("w", mktime(0, 0, 0, $month, $day, $year));//0..6 starting sunday
$weeks[$weeks_in_month][$week_day] = $day;
if ($week_day == 6) {
$weeks_in_month++;
}
}
return $weeks;
}

My 5 cents:
/**
* calculate number of weeks in a particular month
*/
function weeksInMonth($month=null,$year=null){
if( null==($year) ) {
$year = date("Y",time());
}
if(null==($month)) {
$month = date("m",time());
}
// find number of days in this month
$daysInMonths = date('t',strtotime($year.'-'.$month.'-01'));
$numOfweeks = ($daysInMonths%7==0?0:1) + intval($daysInMonths/7);
$monthEndingDay= date('N',strtotime($year.'-'.$month.'-'.$daysInMonths));
$monthStartDay = date('N',strtotime($year.'-'.$month.'-01'));
if($monthEndingDay<$monthStartDay){
$numOfweeks++;
}
return $numOfweeks;
}

I create this function, from brazil :) I hope it is useful
function weekofmonth($time) {
$firstday = 1;
$lastday = date('j',$time);
$lastdayweek = 6; //Saturday
$week = 1;
for ($day=1;$day<=$lastday;$day++) {
$timetmp = mktime(0, 0, 0, date('n',$time), $day, date('Y',$time));
if (date('N',$timetmp) == $lastdayweek) {
$week++;
}
}
if (date('N',$time)==$lastdayweek) {
$week--;
}
return $week;
}
$time = mktime(0, 0, 0, 9, 30, 2014);
echo weekofmonth($time);

I found a easy way to determine what week of the month today is in, and it would be a small change to have it work on any other date. I'm adding my two cents in here as I think my way is much more compact then the methods listed.
$monthstart = date("N",strtotime(date("n/1/Y")));
$date =( date("j")+$monthstart ) /7;
$ddate= floor( $date );
if($ddate != date) {$ddate++;}
and $ddate contains the week number you could modify it like so
function findweek($indate)
{
$monthstart = date("N",strtotime(date("n/1/Y",strtotime($indate))));
$date =( date("j",strtotime($indate))+$monthstart ) /7;
$ddate= floor( $date );
if($ddate != $date) {$ddate++;}
return $ddate;
}
and it would return what week of the month any date you give it is.
what it does is first find the number of days from the start of the week to the first of the month. then adds that on to the current date then divides the new date by 7 and that will give you how many weeks have passed since the start of the month, including a decimal place for the part of the the current week that has passed. so what I do next is round down that number, then compare the rounded down version to the original if the two match your at the end of the week so it's already in the number. if they don't then just add one to the rounded down number and voila you have the current week number.

Srahul07's solution works perfectly... If you abide by the Monday-Sunday week system! Here in 'murica, non-business folk tend to go by Sunday-Saturday being a week, so May 1, 2011 is week 1 and May 2, 2011 is still week 1.
Adding the following logic to the bottom of his function, right before it returns $week will convert this to a Sunday -> Monday system:
if (!date('w',strtotime("$year-$month-01")) && date('w',$timestamp))
$week--;
elseif (date('w',strtotime("$year-$month-01")) && !date('w',$timestamp))
$week++;

After alot of efoort i found the solution
<?php
function getWeeks($month,$year)
{
$month = intval($month); //force month to single integer if '0x'
$suff = array('st','nd','rd','th','th','th'); //week suffixes
$end = date('t',mktime(0,0,0,$month,1,$year)); //last date day of month: 28 - 31
$start = date('w',mktime(0,0,0,$month,1,$year)); //1st day of month: 0 - 6 (Sun - Sat)
$last = 7 - $start; //get last day date (Sat) of first week
$noweeks = ceil((($end - ($last + 1))/7) + 1); //total no. weeks in month
$output = ""; //initialize string
$monthlabel = str_pad($month, 2, '0', STR_PAD_LEFT);
for($x=1;$x<$noweeks+1;$x++)
{
if($x == 1)
{
$startdate = "$year-$monthlabel-01";
$day = $last - 6;
}
else
{
$day = $last + 1 + (($x-2)*7);
$day = str_pad($day, 2, '0', STR_PAD_LEFT);
$startdate = "$year-$monthlabel-$day";
}
if($x == $noweeks)
{
$enddate = "$year-$monthlabel-$end";
}
else
{
$dayend = $day + 6;
$dayend = str_pad($dayend, 2, '0', STR_PAD_LEFT);
$enddate = "$year-$monthlabel-$dayend";
}
$j=1;
if($j--)
{
$k=getTotalDate($startdate,$enddate);
$j=1;
}
$output .= "Week ".$xyz." week -> Start date=$startdate End date=$enddate <br />";
}
return $output;
}
if(isset($_POST) && !empty($_POST)){
$month = $_POST['m'];
$year = $_POST['y'];
echo getWeeks($month,$year);
}
?>
<form method="post">
M:
<input name="m" value="" />
Y:
<input name="y" value="" />
<input type="submit" value="go" />
</form>

I really liked #michaelc's answer. However, I got stuck on a few points. It seemed that every time Sunday rolled around, there was an offset of one. I think it has to do with what day of the week is the start of the week. In any case, here is my slight alteration to it, expanded a bit for readability:
function wom(\DateTime $date) {
// The week of the year of the current month
$cw = date('W', $date->getTimestamp());
// The week of the year of the first of the given month
$fw = date('W',strtotime(date('Y-m-01',$date->getTimeStamp())));
// Offset
$o = 1;
// If it is a Saturday, offset by two.
if( date('N',$date->getTimestamp()) == 7 ) {
$o = 2;
}
return $cw -$fw + $o;
}
So if the date is Nov. 9, 2013...
$cw = 45
$fw = 44
and with the offset of 1, it correctly returns 2.
If the date is Nov. 10, 2013, $cw and $fw are the same as before, but the offset is 2, and it correctly returns 3.

function get_week_of_month( $timestamp )
{
$week_of_month = 0;
$month = date( 'j', $timestamp );
$test_month = $month;
while( $test_month == $month )
{
$week_of_month++;
$timestamp = strtotime( '-1 week', $timestamp );
$test_month = date( 'j', $timestamp );
}
return $week_of_month;
}

I found this online:
http://kcwebprogrammers.blogspot.de/2009/03/current-week-in-month-php.html
He has a very simple solution which seems to work fine for me.
$currentWeek = ceiling((date("d") - date("w") - 1) / 7) + 1;
So for example:
$now = strtotime("today");
$weekOfMonth = ceil((date("d", $now) - date("w", $now) - 1) / 7) + 1;

you can use W in newer php versions. http://php.net/manual/en/function.date.php
i have used it like so:
function getWeek($date) {
$month_start=strtotime("1 ".date('F Y',$date));
$current_date=strtotime(date('j F Y',$date));
$month_week=date("W",$month_start);
$current_week=date("W",$current_date);
return ($current_week-$month_week);
}//0 is the week of the first.

Short and foolproof:
// Function accepts $date as a string,
// Returns the week number in which the given date falls.
// Assumed week starts on Sunday.
function wom($date) {
$date = strtotime($date);
$weeknoofday = date('w', $date);
$day = date('j', $date);
$weekofmonth = ceil(($day + (7-($weeknoofday+1))) / 7);
return $weekofmonth;
}
// Test
foreach (range(1, 31) as $day) {
$test_date = "2015-01-" . str_pad($day, 2, '0', STR_PAD_LEFT);
echo "$test_date - ";
echo wom($test_date) . "\n";
}

I use this simple function:
function weekNumberInMonth($timestampDate)
{
$firstDayOfMonth = strtotime(date('01-M-Y 00:00:00', $timestampDate));
$firstWeekdayOfMonth = date( 'w', $firstDayOfMonth);
$dayNumberInMonth = date('d', $timestampDate);
$weekNumberInMonth = ceil(($dayNumberInMonth + $firstWeekdayOfMonth) / 7);
return $weekNumberInMonth;
}

if I understand correct, the question is how to identify what number of week within a month of a specific day... I was looking for similar solution. I used some ideas of above answers to develop my own solution. Hope it can be helpful for somebody. If Yes, then UpVote my answer.
function week_number_within_month($datenew){
$year = date("Y",strtotime($datenew));
$month = date("m",strtotime($datenew));
// find number of days in this month
$daysInMonths = date('t',strtotime($year.'-'.$month.'-01'));
$numOfweeks = ($daysInMonths%7==0?0:1) + intval($daysInMonths/7);
$monthEndingDay= date('N',strtotime($year.'-'.$month.'-'.$daysInMonths));
$monthStartDay = date('N',strtotime($year.'-'.$month.'-01'));
if($monthEndingDay<$monthStartDay){
$numOfweeks++;
}
$date=date('Y/m/d', strtotime($year.'-'. $month.'-01'));
$week_array=Array();
for ($i=1; $i<=$numOfweeks; $i++){ /// create an Array of all days of month separated by weeks as a keys
$max = 7;
if ($i ==1){ $max = 8 - $monthStartDay;}
if ($i == $numOfweeks){ $max = $monthEndingDay;}
for ($r=1; $r<=$max; $r++){
$week_array[$i][]=$date;
$date = date('Y/m/d',strtotime($date . "+1 days"));
}
}
$new_datenew = date('Y/m/d', strtotime($datenew));
$week_result='';
foreach ($week_array as $key => $val){ /// finding what week number of my date from week_array
foreach ($val as $kr => $value){
if ($new_datenew == $value){
$week_result = $key;
}
}
}
return $week_result;
}
print week_number_within_month('2016-09-15');

function getWeekOfMonth(\DateTime $date)
{
$firstWeekdayOfMonth = new DateTime("first weekday 0 {$date->format('M')} {$date->format('Y')}");
$offset = $firstWeekdayOfMonth->format('N')-1;
return intval(($date->format('j') + $offset)/7)+1;
}

/**
* In case of Week we can get the week of year. So whenever we will get the week of the month then we have to
* subtract the until last month weeks from it will give us the current month week.
*/
$dateComponents = getdate();
if($dateComponents['mon'] == 1)
$weekOfMonth = date('W', strtotime($dateComponents['year'].'-'.$dateComponents['mon'].'-'.$dateComponents['mday']))-1; // We subtract -1 to map it to the array
else
$weekOfMonth = date('W', strtotime($dateComponents['year'].'-'.$dateComponents['mon'].'-'.$dateComponents['mday']))-date('W', strtotime($dateComponents['year'].'-'.$dateComponents['mon'].'-01'));

Using Carbon:
$date = Carbon::now();
$d1 = $date->startOfMonth();
$d2 = $date->endOfMonth();
$weeks = $d1->diffInWeeks($d2);

If you clearly want to separate a month into 4 Weeks, you can use this function.
This is helpful, if you want
"the first monday of month"
"the third thursday of month" etc.
Here we go
/**
* This Calculates (and returns) the week number within a month, based on date('j') day of month.
* This is useful, if you want to have (for instance) the first Thu in month, regardless of date
* #param $Timestamp
* #return float|int
*/
function getWeekOfMonth($Timestamp)
{
$DayOfMonth=date('j', $Timestamp); // Day of the month without leading zeros 0-31
if($DayOfMonth>21) return 4;
if($DayOfMonth>14) return 3;
if($DayOfMonth>7) return 2;
return 1;
}

From carbon:
return (int) ceil((new Datetime())->format('d') / 7);
As simple as possible :)

Python: Number of the Week in a Month
This is a worked example in Python - should be simple to convert.

Related

Calculate the weeks between 2 dates manually in PHP

I'm trying to calculate the number of months and weeks since a particular date instead of from the beginning of the year.
It shouldn't follow calendar months but should instead count a month as every 4 weeks, and begin from a specified date. I need to be able to display the number of months, and also what week it is (1, 2, 3 or 4).
I want to put in a start date, and have it then count what month and week is it from that start date e.g if the start date is set to Mon 1st August it should show Month 1, Week 1 and so on.
My code is below. I tested it with some different start dates. Here's a list of what the code below generates and what it should display
Jun-20: Should be Week 2 - Shows as Week 0
Jun-27: Should be Week 1 - Shows as Week 3
Jul-04: Should be Week 4 - Shows as Week 2
Jul-11: Should be Week 3 - Shows as Week 1
Jul-18: Should be Week 2 - Shows as Week 0
$monthNumber = 5;
$monthStartDate = '2016-06-13';
$currentStartWeekDate = date('l') != 'Monday' ? date("Y-m-d", strtotime("last monday")) : date("Y-m-d"); // get the current week's Monday's date
$weekDateCounter = $monthStartDate;
$currentWeekNumber = 0;
while ($weekDateCounter != $currentStartWeekDate){
$currentWeekNumber += 1;
$weekDateCounter = date("Y-m-d", strtotime($weekDateCounter . "+7 days"));
//
if ($currentWeekNumber == 4){
$currentWeekNumber = 0; // reset week number
$monthNumber += 1; // increment month number
}
}
I am really at a loss with this and could use any help!
Your approach seems overly complicated:
function weekCounter($startDate,$endDate=null){
//use today as endDate if no date was supplied
$endDate = $endDate? : date('Y-m-d');
//calculate # of full weeks between dates
$secsPerWeek = 60 * 60 * 24 * 7;
$fullWeeks =
floor((strtotime($endDate) - strtotime($startDate))/$secsPerWeek);
$fullMonths = floor($fullWeeks/4);
$weeksRemainder = $fullWeeks % 4; // weeks that don't fit in a month
//increment from 0-base to 1-base, so first week is Week 1. Same with months
$fullMonths++; $weeksRemainder++;
//return months and weeks in an array
return [$fullMonths,$weeksRemainder];
}
You can call the function this way, and capture months and weeks:
//list() will assign the array members from weekCounter to the vars in list
list($months,$weeks) = weekCounter('2016-06-07'); //no end date, so today is used
//now $months and $weeks can be used as you wish
echo "Month: $months, Week: $weeks"; //outputs Month: 2, Week: 2
Live demo
The DateTime classes could make this much simpler for you. Documentation for them is here: http://php.net/manual/en/book.datetime.php
Try this out:
$date1 = new DateTime('2016-04-01');
$date2 = new DateTime('2016-07-24');
$diff = $date1->diff($date2);
$daysInbetween = $diff->days;
$weeksInbetween = floor($diff->days / 7);
$monthsInbetween = floor($weeksInbetween / 4);
print "Days inbetween = $daysInbetween" . PHP_EOL;
print "Weeks inbetween = $weeksInbetween" . PHP_EOL;
print "Months inbetween = $monthsInbetween" . PHP_EOL;
print "Total difference = $monthsInbetween months and "
. ($weeksInbetween - ($monthsInbetween * 4)) . " weeks" . PHP_EOL;
<?php
/**
* AUTHOR : VEDAVITH RAVULA
* DATE : 13122019
*/
function get_weeks($startDate = NULL,$endDate = NULL)
{
if(is_null($startDate) && is_null($endDate))
{
$startDate = date('Y-m-01');
$endDate = date('Y-m-t');
}
$date1 = new DateTime($startDate);
$date2 = new DateTime($endDate);
$interval = $date1->diff($date2);
$weeks = floor(($interval->days) / 7);
if(($date1->format("N") > 1) && ($date1->format("D") != "Sun"))
{
$diffrence = "-".( $date1->format("N"))." Days";
$date1 = $date1->modify($diffrence);
}
for($i = 0; $i <= $weeks; $i++)
{
if($i == 0)
{
$start_date = $date1->format('Y-m-d');
$date1->add(new DateInterval('P6D'));
}
else
{
$date1->add(new DateInterval('P6D'));
}
echo $start_date." - ".$date1->format('Y-m-d')."\n";
$date1->add(new DateInterval('P1D'));
$start_date = $date1->format('Y-m-d');
}
}
//function call
get_weeks("2021-11-01", "2021-11-14");

Get week number (in the year) from a date PHP

I want to take a date and work out its week number.
So far, I have the following. It is returning 24 when it should be 42.
<?php
$ddate = "2012-10-18";
$duedt = explode("-",$ddate);
$date = mktime(0, 0, 0, $duedt[2], $duedt[1],$duedt[0]);
$week = (int)date('W', $date);
echo "Weeknummer: ".$week;
?>
Is it wrong and a coincidence that the digits are reversed? Or am I nearly there?
Today, using PHP's DateTime objects is better:
<?php
$ddate = "2012-10-18";
$date = new DateTime($ddate);
$week = $date->format("W");
echo "Weeknummer: $week";
It's because in mktime(), it goes like this:
mktime(hour, minute, second, month, day, year);
Hence, your order is wrong.
<?php
$ddate = "2012-10-18";
$duedt = explode("-", $ddate);
$date = mktime(0, 0, 0, $duedt[1], $duedt[2], $duedt[0]);
$week = (int)date('W', $date);
echo "Weeknummer: " . $week;
?>
$date_string = "2012-10-18";
echo "Weeknummer: " . date("W", strtotime($date_string));
Use PHP's date function
http://php.net/manual/en/function.date.php
date("W", $yourdate)
This get today date then tell the week number for the week
<?php
$date=date("W");
echo $date." Week Number";
?>
Just as a suggestion:
<?php echo date("W", strtotime("2012-10-18")); ?>
Might be a little simpler than all that lot.
Other things you could do:
<?php echo date("Weeknumber: W", strtotime("2012-10-18 01:00:00")); ?>
<?php echo date("Weeknumber: W", strtotime($MY_DATE)); ?>
Becomes more difficult when you need year and week.
Try to find out which week is 01.01.2017.
(It is the 52nd week of 2016, which is from Mon 26.12.2016 - Sun 01.01.2017).
After a longer search I found
strftime('%G-%V',strtotime("2017-01-01"))
Result: 2016-52
https://www.php.net/manual/de/function.strftime.php
ISO-8601:1988 week number of the given year, starting with the first week of the year with at least 4 weekdays, with Monday being the start of the week. (01 through 53)
The equivalent in mysql is DATE_FORMAT(date, '%x-%v')
https://www.w3schools.com/sql/func_mysql_date_format.asp
Week where Monday is the first day of the week (01 to 53).
Could not find a corresponding solution with DateTime.
At least not without solutions like "+1day, last monday".
Edit: since strftime is now deprecated, maybe you can also use date.
Didn't verify it though.
date('o-W',strtotime("2017-01-01"));
I have tried to solve this question for years now, I thought I found a shorter solution but had to come back again to the long story. This function gives back the right ISO week notation:
/**
* calcweek("2018-12-31") => 1901
* This function calculates the production weeknumber according to the start on
* monday and with at least 4 days in the new year. Given that the $date has
* the following format Y-m-d then the outcome is and integer.
*
* #author M.S.B. Bachus
*
* #param date-notation PHP "Y-m-d" showing the data as yyyy-mm-dd
* #return integer
**/
function calcweek($date) {
// 1. Convert input to $year, $month, $day
$dateset = strtotime($date);
$year = date("Y", $dateset);
$month = date("m", $dateset);
$day = date("d", $dateset);
$referenceday = getdate(mktime(0,0,0, $month, $day, $year));
$jan1day = getdate(mktime(0,0,0,1,1,$referenceday[year]));
// 2. check if $year is a leapyear
if ( ($year%4==0 && $year%100!=0) || $year%400==0) {
$leapyear = true;
} else {
$leapyear = false;
}
// 3. check if $year-1 is a leapyear
if ( (($year-1)%4==0 && ($year-1)%100!=0) || ($year-1)%400==0 ) {
$leapyearprev = true;
} else {
$leapyearprev = false;
}
// 4. find the dayofyearnumber for y m d
$mnth = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
$dayofyearnumber = $day + $mnth[$month-1];
if ( $leapyear && $month > 2 ) { $dayofyearnumber++; }
// 5. find the jan1weekday for y (monday=1, sunday=7)
$yy = ($year-1)%100;
$c = ($year-1) - $yy;
$g = $yy + intval($yy/4);
$jan1weekday = 1+((((intval($c/100)%4)*5)+$g)%7);
// 6. find the weekday for y m d
$h = $dayofyearnumber + ($jan1weekday-1);
$weekday = 1+(($h-1)%7);
// 7. find if y m d falls in yearnumber y-1, weeknumber 52 or 53
$foundweeknum = false;
if ( $dayofyearnumber <= (8-$jan1weekday) && $jan1weekday > 4 ) {
$yearnumber = $year - 1;
if ( $jan1weekday = 5 || ( $jan1weekday = 6 && $leapyearprev )) {
$weeknumber = 53;
} else {
$weeknumber = 52;
}
$foundweeknum = true;
} else {
$yearnumber = $year;
}
// 8. find if y m d falls in yearnumber y+1, weeknumber 1
if ( $yearnumber == $year && !$foundweeknum) {
if ( $leapyear ) {
$i = 366;
} else {
$i = 365;
}
if ( ($i - $dayofyearnumber) < (4 - $weekday) ) {
$yearnumber = $year + 1;
$weeknumber = 1;
$foundweeknum = true;
}
}
// 9. find if y m d falls in yearnumber y, weeknumber 1 through 53
if ( $yearnumber == $year && !$foundweeknum ) {
$j = $dayofyearnumber + (7 - $weekday) + ($jan1weekday - 1);
$weeknumber = intval( $j/7 );
if ( $jan1weekday > 4 ) { $weeknumber--; }
}
// 10. output iso week number (YYWW)
return ($yearnumber-2000)*100+$weeknumber;
}
I found out that my short solution missed the 2018-12-31 as it gave back 1801 instead of 1901. So I had to put in this long version which is correct.
How about using the IntlGregorianCalendar class?
Requirements: Before you start to use IntlGregorianCalendar make sure that libicu or pecl/intl is installed on the Server.
So run on the CLI:
php -m
If you see intl in the [PHP Modules] list, then you can use IntlGregorianCalendar.
DateTime vs IntlGregorianCalendar:
IntlGregorianCalendar is not better then DateTime. But the good thing about IntlGregorianCalendar is that it will give you the week number as an int.
Example:
$dateTime = new DateTime('21-09-2020 09:00:00');
echo $dateTime->format("W"); // string '39'
$intlCalendar = IntlCalendar::fromDateTime ('21-09-2020 09:00:00');
echo $intlCalendar->get(IntlCalendar::FIELD_WEEK_OF_YEAR); // integer 39
<?php
$ddate = "2012-10-18";
$duedt = explode("-",$ddate);
$date = mktime(0, 0, 0, $duedt[1], $duedt[2],$duedt[0]);
$week = (int)date('W', $date);
echo "Weeknummer: ".$week;
?>
You had the params to mktime wrong - needs to be Month/Day/Year, not Day/Month/Year
To get the week number for a date in North America I do like this:
function week_number($n)
{
$w = date('w', $n);
return 1 + date('z', $n + (6 - $w) * 24 * 3600) / 7;
}
$n = strtotime('2022-12-27');
printf("%s: %d\n", date('D Y-m-d', $n), week_number($n));
and get:
Tue 2022-12-27: 53
for get week number in jalai calendar you can use this:
$weeknumber = date("W"); //number week in year
$dayweek = date("w"); //number day in week
if ($dayweek == "6")
{
$weeknumberint = (int)$weeknumber;
$date2int++;
$weeknumber = (string)$date2int;
}
echo $date2;
result:
15
week number change in saturday
The most of the above given examples create a problem when a year has 53 weeks (like 2020). So every fourth year you will experience a week difference. This code does not:
$thisYear = "2020";
$thisDate = "2020-04-24"; //or any other custom date
$weeknr = date("W", strtotime($thisDate)); //when you want the weeknumber of a specific week, or just enter the weeknumber yourself
$tempDatum = new DateTime();
$tempDatum->setISODate($thisYear, $weeknr);
$tempDatum_start = $tempDatum->format('Y-m-d');
$tempDatum->setISODate($thisYear, $weeknr, 7);
$tempDatum_end = $tempDatum->format('Y-m-d');
echo $tempDatum_start //will output the date of monday
echo $tempDatum_end // will output the date of sunday
Very simple
Just one line:
<?php $date=date("W"); echo "Week " . $date; ?>"
You can also, for example like I needed for a graph, subtract to get the previous week like:
<?php $date=date("W"); echo "Week " . ($date - 1); ?>
Your code will work but you need to flip the 4th and the 5th argument.
I would do it this way
$date_string = "2012-10-18";
$date_int = strtotime($date_string);
$date_date = date($date_int);
$week_number = date('W', $date_date);
echo "Weeknumber: {$week_number}.";
Also, your variable names will be confusing to you after a week of not looking at that code, you should consider reading http://net.tutsplus.com/tutorials/php/why-youre-a-bad-php-programmer/
The rule is that the first week of a year is the week that contains the first Thursday of the year.
I personally use Zend_Date for this kind of calculation and to get the week for today is this simple. They have a lot of other useful functions if you work with dates.
$now = Zend_Date::now();
$week = $now->get(Zend_Date::WEEK);
// 10
To get Correct Week Count for Date 2018-12-31 Please use below Code
$day_count = date('N',strtotime('2018-12-31'));
$week_count = date('W',strtotime('2018-12-31'));
if($week_count=='01' && date('m',strtotime('2018-12-31'))==12){
$yr_count = date('y',strtotime('2018-12-31')) + 1;
}else{
$yr_count = date('y',strtotime('2018-12-31'));
}
function last_monday($date)
{
if (!is_numeric($date))
$date = strtotime($date);
if (date('w', $date) == 1)
return $date;
else
return date('Y-m-d',strtotime('last monday',$date));
}
$date = '2021-01-04'; //Enter custom date
$year = date('Y',strtotime($date));
$date1 = new DateTime($date);
$ldate = last_monday($year."-01-01");
$date2 = new DateTime($ldate);
$diff = $date2->diff($date1)->format("%a");
$diff = $diff/7;
$week = intval($diff) + 1;
echo $week;
//Returns 2.
try this solution
date( 'W', strtotime( "2017-01-01 + 1 day" ) );

PHP strtotime +1 month behaviour

I know about the unwanted behaviour of PHP's function
strtotime
For example, when adding a month (+1 month) to dates like: 31.01.2011 -> 03.03.2011
I know it's not officially a PHP bug, and that this solution has some arguments behind it, but at least for me, this behavior has caused a lot waste of time (in the past and present) and I personally hate it.
What I found even stranger is that for example in:
MySQL: DATE_ADD('2011-01-31', INTERVAL 1 MONTH) returns 2011-02-28
or
C# where new DateTime(2011, 01, 31).AddMonths(1); will return 28.02.2011
wolframalpha.com giving 31.01.2013 + 1 month as input; will return Thursday, February 28, 2013
It sees to me that others have found a more decent solution to the stupid question that I saw alot in PHP bug reports "what day will it be, if I say we meet in a month from now" or something like that. The answer is: if 31 does not exists in next month, get me the last day of that month, but please stick to next month.
So MY QUESTION IS: is there a PHP function (written by somebody) that resolves this not officially recognized bug? As I don't think I am the only one who wants another behavior when adding / subtracting months.
I am particulary interested in solutions what also work not just for the end of the month, but a complete replacement of strtotime. Also the case strotime +n months should be also dealt with.
Happy coding!
what you need is to tell PHP to be smarter
$the_date = strtotime('31.01.2011');
echo date('r', strtotime('last day of next month', $the_date));
$the_date = strtotime('31.03.2011');
echo date('r', strtotime('last day of next month', $the_date));
assuming you are only interesting on the last day of next month
reference - http://www.php.net/manual/en/datetime.formats.relative.php
PHP devs surely don't consider this as bug. But in strtotime's docs there are few comments with solutions for your problem (look for 28th Feb examples ;)), i.e. this one extending DateTime class:
<?php
// this will give us 2010-02-28 ()
echo PHPDateTime::DateNextMonth(strftime('%F', strtotime("2010-01-31 00:00:00")), 31);
?>
Class PHPDateTime:
<?php
/**
* IA FrameWork
* #package: Classes & Object Oriented Programming
* #subpackage: Date & Time Manipulation
* #author: ItsAsh <ash at itsash dot co dot uk>
*/
final class PHPDateTime extends DateTime {
// Public Methods
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Calculate time difference between two dates
* ...
*/
public static function TimeDifference($date1, $date2)
$date1 = is_int($date1) ? $date1 : strtotime($date1);
$date2 = is_int($date2) ? $date2 : strtotime($date2);
if (($date1 !== false) && ($date2 !== false)) {
if ($date2 >= $date1) {
$diff = ($date2 - $date1);
if ($days = intval((floor($diff / 86400))))
$diff %= 86400;
if ($hours = intval((floor($diff / 3600))))
$diff %= 3600;
if ($minutes = intval((floor($diff / 60))))
$diff %= 60;
return array($days, $hours, $minutes, intval($diff));
}
}
return false;
}
/**
* Formatted time difference between two dates
*
* ...
*/
public static function StringTimeDifference($date1, $date2) {
$i = array();
list($d, $h, $m, $s) = (array) self::TimeDifference($date1, $date2);
if ($d > 0)
$i[] = sprintf('%d Days', $d);
if ($h > 0)
$i[] = sprintf('%d Hours', $h);
if (($d == 0) && ($m > 0))
$i[] = sprintf('%d Minutes', $m);
if (($h == 0) && ($s > 0))
$i[] = sprintf('%d Seconds', $s);
return count($i) ? implode(' ', $i) : 'Just Now';
}
/**
* Calculate the date next month
*
* ...
*/
public static function DateNextMonth($now, $date = 0) {
$mdate = array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
list($y, $m, $d) = explode('-', (is_int($now) ? strftime('%F', $now) : $now));
if ($date)
$d = $date;
if (++$m == 2)
$d = (($y % 4) === 0) ? (($d <= 29) ? $d : 29) : (($d <= 28) ? $d : 28);
else
$d = ($d <= $mdate[$m]) ? $d : $mdate[$m];
return strftime('%F', mktime(0, 0, 0, $m, $d, $y));
}
}
?>
Here's the algorithm you can use. It should be simple enough to implement yourself.
Have the original date and the +1 month date in variables
Extract the month part of both variables
If the difference is greater than 1 month (or if the original is December and the other is not January) change the latter variable to the last day of the next month. You can use for example t in date() to get the last day: date( 't.m.Y' )
Had the same issue recently and ended up writing a class that handles adding/subtracting various time intervals to DateTime objects.
Here's the code:
https://gist.github.com/pavlepredic/6220041#file-gistfile1-php
I've been using this class for a while and it seems to work fine, but I'm really interested in some peer review. What you do is create a TimeInterval object (in your case, you would specify 1 month as the interval) and then call addToDate() method, making sure you set $preventMonthOverflow argument to true. The code will make sure that the resulting date does not overflow into next month.
Sample usage:
$int = new TimeInterval(1, TimeInterval::MONTH);
$date = date_create('2013-01-31');
$future = $int->addToDate($date, true);
echo $future->format('Y-m-d');
Resulting date is:
2013-02-28
Here is an implementation of an improved version of Juhana's answer above:
<?php
function sameDateNextMonth(DateTime $createdDate, DateTime $currentDate) {
$addMon = clone $currentDate;
$addMon->add(new DateInterval("P1M"));
$nextMon = clone $currentDate;
$nextMon->modify("last day of next month");
if ($addMon->format("n") == $nextMon->format("n")) {
$recurDay = $createdDate->format("j");
$daysInMon = $addMon->format("t");
$currentDay = $currentDate->format("j");
if ($recurDay > $currentDay && $recurDay <= $daysInMon) {
$addMon->setDate($addMon->format("Y"), $addMon->format("n"), $recurDay);
}
return $addMon;
} else {
return $nextMon;
}
}
This version takes $createdDate under the presumption that you are dealing with a recurring monthly period, such as a subscription, that started on a specific date, such as the 31st. It always takes $createdDate so late "recurs on" dates won't shift to lower values as they are pushed forward thru lesser-valued months (e.g., so all 29th, 30th or 31st recur dates won't eventually get stuck on the 28th after passing thru a non-leap-year February).
Here is some driver code to test the algorithm:
$createdDate = new DateTime("2015-03-31");
echo "created date = " . $createdDate->format("Y-m-d") . PHP_EOL;
$next = sameDateNextMonth($createdDate, $createdDate);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
foreach(range(1, 12) as $i) {
$next = sameDateNextMonth($createdDate, $next);
echo " next date = " . $next->format("Y-m-d") . PHP_EOL;
}
Which outputs:
created date = 2015-03-31
next date = 2015-04-30
next date = 2015-05-31
next date = 2015-06-30
next date = 2015-07-31
next date = 2015-08-31
next date = 2015-09-30
next date = 2015-10-31
next date = 2015-11-30
next date = 2015-12-31
next date = 2016-01-31
next date = 2016-02-29
next date = 2016-03-31
next date = 2016-04-30
I have solved it by this way:
$startDate = date("Y-m-d");
$month = date("m",strtotime($startDate));
$nextmonth = date("m",strtotime("$startDate +1 month"));
if((($nextmonth-$month) > 1) || ($month == 12 && $nextmonth != 1))
{
$nextDate = date( 't.m.Y',strtotime("$initialDate +1 week"));
}else
{
$nextDate = date("Y-m-d",strtotime("$initialDate +1 month"));
}
echo $nextDate;
Somewhat similar to the Juhana's answer but more intuitive and less complications expected. Idea is like this:
Store original date and the +n month(s) date in variables
Extract the day part of both variables
If days do not match, subtract number of days from the future date
Plus side of this solution is that works for any date (not just the border dates) and it also works for subtracting months (by putting - instead of +).
Here is an example implementation:
$start = mktime(0,0,0,1,31,2015);
for ($contract = 0; $contract < 12; $contract++) {
$end = strtotime('+ ' . $contract . ' months', $start);
if (date('d', $start) != date('d', $end)) {
$end = strtotime('- ' . date('d', $end) . ' days', $end);
}
echo date('d-m-Y', $end) . '|';
}
And the output is following:
31-01-2015|28-02-2015|31-03-2015|30-04-2015|31-05-2015|30-06-2015|31-07-2015|31-08-2015|30-09-2015|31-10-2015|30-11-2015|31-12-2015|
function ldom($m,$y){
//return tha last date of a given month based on the month and the year
//(factors in leap years)
$first_day= strtotime (date($m.'/1/'.$y));
$next_month = date('m',strtotime ( '+32 day' , $first_day)) ;
$last_day= strtotime ( '-1 day' , strtotime (date($next_month.'/1/'.$y)) ) ;
return $last_day;
}

In PHP, how to know how many mondays have passed in this month uptil today?

Assume today is Feb 21, 2011 ( Monday ). It is the third Monday of this month. If date is given as input, How can I know how many Mondays have passed before it?
In PHP, how to know how many mondays have passed in this month uptil today?
$now=time() + 86400;
if (($dow = date('w', $now)) == 0) $dow = 7;
$begin = $now - (86400 * ($dow-1));
echo "Mondays: ".ceil(date('d', $begin) / 7)."<br/>";
works for me....
EDIT: includes today's monday too
That sounds like a pretty straightforward division calculation. From the current date, subtract number of days past last monday (example: wednesday = -2), divide it by 7 and ceil() it to round it up.
EDIT: That will include the current monday in the number, returning "3" for monday 21st.
<?php
function mondays_get($month, $stop_if_today = true) {
$timestamp_now = time();
for($a = 1; $a < 32; $a++) {
$day = strlen($a) == 1 ? "0".$a : $a;
$timestamp = strtotime($month . "-$day");
$day_code = date("w", $timestamp);
if($timestamp > $timestamp_now)
break;
if($day_code == 1)
#$mondays++;
}
return $mondays;
}
echo mondays_get('2011-02');
Hope this is of use to you! i've just rolled it up.
"Beware of bugs in the above code; I have only proved it correct, not tried it."
Works OK afaik
You could loop through all the days until now and count the mondays:
$firstDate = mktime(0, 0, 0, date("n"), 1, date("Y"));
$now = time();
$mondays = 0;
for ($i = $firstDate; $i < $now; $i = $i + 24*3600) {
if (date("D", $i) == "Mon")
$mondays ++;
}
Haven't tested this script
Try this...
//find the most recent monday (doesn't find today if today is Monday though)
$startDate = strtotime( 'last monday' );
//if 'last monday' was not this month, 0 mondays.
//if 'last monday' was this month, count the weeks
$mondays = date( 'm', $startDate ) != date( 'm' )
? 0
: floor( date( 'd', $startDate ) / 7 );
//increment the count if today is a monday (since strtotime didn't find it)
if ( date( 'w' ) == 1 ) $mondays++;
Another way is to find what day of the week is today, find the first such day of the month via some magic strtotime(), then calculate the difference between that and now in weeks. See below for a function that will take a Y-m-d formatted date() and return which weekday of the month it is.
Note: strtotime needs to be verbose, including "of" and the month: "first Monday of 2011-02" otherwise it advances one day. This bit me when I was testing edge cases.
Also added some display pepper which is completely optional but I felt like it.
function nthWeekdayOfMonth($day) {
$dayTS = strtotime($day) ;
$dayOfWeekToday = date('l', $dayTS) ;
$firstOfMonth = date('Y-m', $dayTS) . "-01" ;
$firstOfMonthTS = strtotime($firstOfMonth) ;
$firstWhat = date('Y-m-d', strtotime("first $dayOfWeekToday of $monthYear", $firstOfMonthTS)) ;
$firstWhatTS = strtotime($firstWhat) ;
$diffTS = $dayTS - $firstWhatTS ;
$diffWeeks = $diffTS / (86400 * 7);
$nthWeekdayOfMonth = $diffWeeks + 1;
return $nthWeekdayOfMonth ;
}
$day = date('Y-m-d') ;
$nthWeekdayOfMonth = nthWeekdayOfMonth($day) ;
switch ($nthWeekdayOfMonth) {
case 1:
$inflector = "st" ;
break ;
case 2:
$inflector = "nd" ;
break ;
case 3:
$inflector = "rd" ;
break ;
default:
$inflector = "th" ;
}
$dayTS = strtotime($day) ;
$monthName = date('F', $dayTS) ;
$dayOfWeekToday = date('l', $dayTS) ;
echo "Today is the {$nthWeekdayOfMonth}$inflector $dayOfWeekToday in $monthName" ;

Easy way to get day number of current quarter?

PHP provides ways to get the number of the current day of the month (date('j')) as well as the number of the current day of the year (date('z')). Is there a way to get the number of the current day of the current quarter?
So right now, August 5, it is day 36 of the third quarter.
If there is no standard way of calculating this, does anyone have a (prefereably PHP-based) algorithm handy?
How about:
$curMonth = date("m", time());
$curQuarter = ceil($curMonth/3);
I wrote a class with the following methods. Enjoy.
public static function getQuarterByMonth($monthNumber) {
return floor(($monthNumber - 1) / 3) + 1;
}
public static function getQuarterDay($monthNumber, $dayNumber, $yearNumber) {
$quarterDayNumber = 0;
$dayCountByMonth = array();
$startMonthNumber = ((self::getQuarterByMonth($monthNumber) - 1) * 3) + 1;
// Calculate the number of days in each month.
for ($i=1; $i<=12; $i++) {
$dayCountByMonth[$i] = date("t", strtotime($yearNumber . "-" . $i . "-01"));
}
for ($i=$startMonthNumber; $i<=$monthNumber-1; $i++) {
$quarterDayNumber += $dayCountByMonth[$i];
}
$quarterDayNumber += $dayNumber;
return $quarterDayNumber;
}
public static function getCurrentQuarterDay() {
return self::getQuarterDay(date('n'), date('j'), date('Y'));
}
function date_quarter()
{
return ceil(date('n', time()) / 3);
}
or
function date_quarter()
{
$month = date('n');
if ($month <= 3) return 1;
if ($month <= 6) return 2;
if ($month <= 9) return 3;
return 4;
}
You can use Carbon it has easy modifiers for getFirstOf{Month,Year,Quarter}()
<?php
//take current date
$now = Carbon\Carbon::now();
//modify a copy of it to the first day of the current quarter
$firstOfQuarter = $now->copy()->firstOfQuarter();
//calculate the difference in days and add 1 to correct the index
$dayOfQuarter = $now->diffInDays($firstOfQuarter) + 1;
Assuming you mean a calendar-quarter (because a company fiscal year can start in any month of the year), you could rely on the date('z') to determine the day-of-year, and then keep a simple array of the day each quarter starts on:
$quarterStartDays = array( 1 /* Jan 1 */, 90 /* Mar 1, non leap-year */, ... );
Then with the current day-of-year you can first locate the largest start-day that's less than or equal to the day-of-year, then subtract.
Note that you need different numbers depending on the leap year.
<?php
function day_of_quarter($ts=null) {
if( is_null($ts) ) $ts=time();
$d=date('d', $ts);
$m=date('m', $ts)-1;
while($m%3!=0) {
$lastmonth=mktime(0, 0, 0, $m, date("d", $ts), date("Y",$ts));
$d += date('t', $lastmonth);
$m--;
}
return $d;
}
echo day_of_quarter(mktime(0, 0, 0, 1, 1,2009));
echo "\n";
echo day_of_quarter(time());
echo "\n";
?>
We need to calculate the date of the first quarter first
$current_month = date('m');
// Get first month of quarter
$new_month = (3 * floor(($current_month - 1 ) / 3)) + 1;
// Add prefix zero if needed
$new_month = substr('0' . $new_month, -2);
$first_quarter_day_date = date('Y') . '-' . $new_month . '-01';
next we calculate the http://php.net/manual/en/datetime.diff.php
$datetime1 = new DateTime($first_quarter_day_date);
$datetime2 = new DateTime();
$interval = $datetime1->diff($datetime2);
echo $interval->format('%a days');
<?php
function quarter_day($time = "") {
$time = $time ? strtotime($time) : time();
$date = intval(date("j", $time));
$month = intval(date("n", $time));
$year = intval(date("Y", $time));
// get selected quarter as number between 1 and 4
$quarter = ceil($month / 3);
// get first month of current quarter as number between 1 and 12
$fmonth = $quarter + (($quarter - 1) * 2);
// map days in a year by month
$map = [31,28,31,30,31,30,31,31,30,31,30,31];
// check if year is leap
if (((($year % 4) == 0) && ((($year % 100) != 0) || (($year % 400) == 0)))) $map[1] = 29;
// get total number of days in selected quarter, by summing the relative portion of $map array
$total = array_sum(array_slice($map, ($fmonth - 1), 3));
// get number of days passed in selected quarter, by summing the relative portion of $map array
$map[$month-1] = $date;
$day = array_sum(array_slice($map, ($fmonth - 1), ($month - $fmonth + 1)));
return "Day $day on $total of quarter $quarter, $year.";
}
print(quarter_day("2017-01-01")) . "\n"; // prints Day 1 on 90 of quarter 1, 2017.
print(quarter_day("2017-04-01")) . "\n"; // prints Day 1 on 91 of quarter 2, 2017.
print(quarter_day("2017-08-15")) . "\n"; // prints Day 46 on 92 of quarter 3, 2017.
print(quarter_day("2017-12-31")) . "\n"; // prints Day 92 on 92 of quarter 4, 2017.
I've noticed that this thread went a bit beyond the question, and it's the first response to many google searches with "Quarter" & "PHP" in them.
If you're working with the ISO standards of organization, which you should if you're doing a business app, then
$curMonth = date("m", time());
$curQuarter = ceil($curMonth/3);
Is NOT correct, because the first day of a year in the ISO standards, can be 30, or 31 December.
Instead, you should use this :
$current_yearly_cycle_year_number = 2019;
$current_yearly_cycle_start->setISODate( $current_yearly_cycle_year_number, 1, 1 );
$current_yearly_cycle_end->setISODate( $current_yearly_cycle_year_number, 53, 1 );
if( $current_yearly_cycle_end->format("W") !== "53" )
$current_yearly_cycle_end->setISODate( $current_yearly_cycle_year_number, 52, 1 );
$week_number_start = intval( $current_yearly_cycle_start->format( "W" ) );
$timestamp_start_quarter = ( $week_number_start === 1 ? 1 : intval( ceil( $current_yearly_cycle_start->format( "m" ) / 3 ) ) );
var_dump( $timestamp_start_quarter );

Categories