I am trying to make a function that gives me the number of quarters between 2 dates as an integer. The dates passed to the function are usually quarter-end dates except occasionally when one of the dates is just an arbitary date.
Basically I want it to figure out what quarter the two dates fall into and give an integer difference in the number of quarters.
E.g.
Q1 2013 -> Q2 2013 = 1
Q1 2013 -> Q4 2013 = 3
Q2 2012 -> Q2 2013 = 4
Q4 2012 -> Q1 2013 = 1
Here is my function. I realise it is poor and does not return the correct answer all the time but I'm hoping someone can help...
function quarter_diff(DateTime $d1, DateTime $d2){
//difference in months
$diff = $d1->diff($d2);
return ceil((($diff->format('%y') * 12) + $diff->format('%m')+1)/4);
}
and a fiddle here: http://phpfiddle.org/lite/code/tiw-jx3
We can see theat when the date is in the month after the end of a quarter we don not get the correct answer.
Can anyone suggest an improvement??
Convert each of your dates into quarters, then do the math, much like your first example.
Some quick pseudocode:
Convert d1 to quarter and year -> d1.quarter and d1.year
Convert d2 to quarter and year -> d2.quarter and d2.year
Number of quarters = d1.quarter - d2.quarter + (d1.year - d2.year)*4
Use the absolute value of the result to get the number of quarters difference.
You can create a quick and dirty "quarter" function by dividing month-1 by 3 and adding 1 to the integer portion of the result. Assuming January = 1, December = 12 and Q1 = January through March. You'll have to make adjustments if Q1 starts elsewhere, such as July.
Q = (int)(month - 1)/3 + 1
or
Q = ceiling(month/3)
This is what I opted for thanks to suggestion from Maple
function quarter_diff(DateTime $d1, DateTime $d2){
//Returns the number of quarters between two dateTime objects
if ($d2 > $d1){
$dtmp = $d1;
$d1=$d2;
$d2=$dtmp;
unset($dtmp);
}
$d1q = ceil($d1->format('m')/3);
$d2q = ceil($d2->format('m')/3);
$d1y = $d1->format('y');
$d2y = $d2->format('y');
return $d1q - $d2q + 4*($d1y - $d2y);
}
in MYSQL:
SELECT (year('2016-06-30') - year('2015-07-01'))*4 + quarter('2016-06-30') - quarter('2015-07-01') + 1
Related
This question is pretty similar to this and this (and other) questions, but what I want to do is the opposite, I am expecting a PHP answer to show the same result than MySQL YEARWEEK().
Today is 2019-09-16 and MySQL YEARWEEK says:
SELECT YEARWEEK(NOW()) -- returns 201937
And PHP says:
echo date('oW') // returns 201938
What do I have to do in PHP to show "201937" just like MySQL YEARWEEK does?
There are two issues:
The weeks number changes on different days (Monday for PHP, Sunday for MySQL)
The first week of the year is determined differently (week containing the 4th of january for PHP, week starting with the first Sunday of the year for MySQL)
Which then causes these differences:
First day of year: | Mo | Tu | We | Th | Fr | Sa | Su |
PHP week | ------- 01 ------ | --- 52/53 -- |
MySQL week | ----------- 52/53 ----------| 01 |
We have 2 different cases, based on when the year starts:
If it starts a Friday, Saturday or Sunday, PHP start week 1 "late" by 1 day (it can be solved by taking tomorrow's week number in PHP)
It it starts a Monday, Tuesday, Wednesday or Thursday, you'll end up with an offset of 3-6 days, PHP being ahead this time, and it becomes a mess to solve.
So all in all, it seems you're better off just counting how many Sundays already passed this year, which apparently can be done with the following (adapted from this):
ceil((date("z") + 1 - date("w")) / 7); //added +1 in case the year starts a Sunday
And if it's 0 you count how many Sundays there were last year:
$ldly = strtotime(date("Y")-1)."-12-31"); //last day last year
ceil((date("z", $ldly ) + 1 - date("w", $ldly )) / 7);
By combining the two (and adding a parameter if you want to check dates other than today) you'd get:
function weekNum($date = false) {
$day = $date ? strtotime($date) : time();
if($res = ceil((date("z", $day) + 1 - date("w", $day)) / 7)){
return $res;
}
$ldly = strtotime((date("Y", $day)-1)."-12-31"); //last day last year
return ceil((date("z", $ldly ) + 1 - date("w", $ldly )) / 7);
}
I think this should always match with the MySQL date, but do your own tests to make sure! :)
Like this?
echo date('oW', time() - 86400); // basically use yesterday's week number
I need to calculate number of days between two dates.
Required date entered by me,fetch the record from the database by the given dates.
If the database have 'startdate' as 1Jan2015 'enddate' as 5Feb2015.
For January month it should return 30 and for February 5 days.
My table:
id Name Type Project Place Start Date End Date Details
1 Sai Local Site Bangalore 2015-09-03 11:32:47 2015-09-05 11:32:47 test
2 Ram Local IGCAR Chennai 2015-04-01 15:15:36 2015-04-09 15:15:36 Installation
3 Mani Local IGCAR Chennai 2015-04-16 15:16:18 2015-05-21 15:16:18 Training
My coding
///////////Employee Outstation(Travel) details/////////////
$employeeTravel = new EmployeeTravelRecord();
//date_start = '2015-04-01' ;
//date_end = '2015-04-30';
$TravelEntryList = $employeeTravel->Find("(travel_date between ? and ? or return_date between ? and ? )",array($req['date_start'], $req['date_end'],$req['date_start'], $req['date_end']));
foreach($TravelEntryList as $Travelentry){
$amount = (strtotime($Travelentry->return_date) - strtotime($Travelentry->travel_date));
}
For second record, it returns correct value, but for third record it calculates including May month. But i want only 30 days of april.
DATEDIFF() returns value in days from one date to the other.
select *,datediff( end Date, Start Date) as days from My table;
Please have a look at this post, you should find what you're looking for :
How to get the number of days of difference between two dates on mysql?
There is a function in PHP called as date_diff for difference between two dates.
<?php
$date1 = date_create("2013-03-15");
$date2 = date_create("2013-12-12");
$diff = date_diff($date1,$date2);
echo $diff->format("%R%a days");
?>
I'm hoping that my concern will be answered as soon as possible. :) So here it is: I'm having a hard time solving this problem, as shown below:
$beg_week = "2014 - 49"; //yyyy - w
$stop_wk = "2015 - 5"
while($beg_week <= $stop_wk)
{
/* do logic to add week in the format "yyyy - w", but also
* have to consider the year */
$beg_week = '';
}
So, how can I add a week in a 'yyyy - w' format, without using strtotime()?
Convert your start and end times to timestamps using date_parse_from_format() and mktime(). Alternatively, use an SQL function like MySQL's UNIX_TIMESTAMP() if retrieving data from a datetime field.
Use date_parse_from_format() to break the date into its components.
Use mktime() to get a timestamp
Add a week's worth of seconds (60 * 60 * 24 * 7)
Use date() to output the next week.
Note: date_parse*() won't log/store an error in the returned array if you have more than 29 or 28 days in February (for a leap or regular year, respectively). This might/might not matter, depending on what you're using it for.
There is no need to jump through hoops with date() and mktime() for this. The DateTime classes can handle it simply and cleanly, something like this should work for you:-
$beg_week = (new \DateTime())->setISODate(2014, 49);
$stop_week = (new \DateTime())->setISODate(2015, 5);
$interval = new \DateInterval('P7D');
while($beg_week < $stop_week){
echo $beg_week->format('Y-m-d') . "<br/>\n";
$beg_week->add($interval);
}
Sorry it took so long before I am able to solved and share the method/approach that I used for this matter, since I've got an additional project than this. So what i did was:
First, build a function that gets the max week of a year(thanks to #salathe),
function getIsoWeekYear($year)
{
$date = new DateTime;
$date->setISODate($year,53);
return ($date->format("W") === "53" ? 53 : 52);
}
Then to increment the value of a week, considering also the given year,
$beg_week = "2014 - 50"; //just a sample and not actually a string
$end_week = "2015 - 05";
while($beg_week<=$end_week)
(
$out_data[] = $beg_week;
$b_week_exp = explode(" - ",$beg_week);
$b_yr_temp = $b_week_exp[0];
$b_wk_temp = $b_week_exp[1];
$max_wk_of_yr = getIsoWeeksInYear($b_yr_temp);
$out_year = $b_yr_temp;
$out_week_no = $b_wk_temp+1;
if($out_week_no > $max_wk_of_yr)
{
$out_year = $b_yr_temp+1;
$out_week_no = "1";
}
$beg_week = $out_year." - ".sprintf("%02s", $out_week_no);
)
That's it, if you will print_r the $out_data, you will have an array of,
2014 - 50
2014 - 51
2014 - 52
2015 - 01
2015 - 02
2015 - 03
2015 - 04
2015 - 05
Well, this logic is what I want, to have loop from $beg_week up to $end_week, because there's also a logic that I am executing in it. A very simple trick, for this very simple problem! :) Sorry, SOMETIMES I am that sluggish not to answer my own question/problem. I hope this one will help to anyone who'll also encounter this same scenario. Thank you!
Im currently trying to calculate the amount of periods (each period is 1 week, after a certain date or day). Lets say first period start on 01-01-2013 (tuesday) until 29-01-2013 (tuesday)(4 periods in total).
I have a table that looks like:
id | startDate (datetime) | endDate (datetime)
I have two input fields where a user can fill in a start date and end date. I would like to fill any date between 01-01-2013 and 29-01-2013 and decide how many times it passes a tuesday (the date the period starts) again.
So if I would select 01-01-2013 until 07-01-2013 would result in: 1, but if i would select 06-01-2013 till 09-01-2013 this would result in 2 and 06-01-2013 till 16-01-2013 would result in 3 etc.
To be clear, I dont want to know the amount of weeks between the two dates, only the amount of times it 'crosses' the same day (tuesday) that was given in the database. Every period is 1 week. Is there anyone that could help me out?
Use PHP's date() function.
$startday = strtotime($start_date_from_db);//date from db;
$endday = strtotime($end_date_from_db);//date from db;
$counter = 0;
for($i=$startday; $i<=$endday; $i+=86400) {
$current_day = date('w', $i);
if($current_day == 2) { //0 for sunday, 1 for monday, 2 for tuesday
$counter++;
}
}
When comparing dates a good method is:
1- transform the dates to timestamps:
$timestamp1 = strtotime($date1);
$timestamp2 = strtotime($date2);
2- do the desired operation, in this case:
$timebetween = $timestamp2 - $timestamp1;
3- Transform result (number of seconds) to desired value, in this case:
$weeks= $timebetween / 604800;
I have starting dates and ending dates in my database (MySQL).
How can I get the answer, how many weeks(or days) are inside of those 2 dates? (mysql or php)
For example I have this kind of database:
Started and | will_end
2009-12-17 | 2009-12-24
2009-12-12 | 2009-12-26
...
Update to the question:
How to use DATEDIFF?
How can I make this to work? or should I use DATEDIFF completly differently?
SELECT DATEDIFF('Started ','will_end') AS 'Duration' FROM my_table WHERE id = '110';
If the two columns $d1 and $d2 store unix timestamp obtained from time() then this simple line suffices:
$diffweek = abs($d1 - $d2) / 604800;
Otherwise if the columns are of DATETIME type, then:
$diffweek = abs(strtotime($d1) - strtotime($d2)) / 604800;
p/s: 604800 is the number of seconds in a week (60 * 60 * 24 * 7)
p/s2: you might want to intval($diffweek) or round($diffweek)
Calculating the number of days and dividing by seven won't give you the number of weeks between the two dates. Instead it will return the result of division by 7 that doesn't always correspond to the number of weeks between the two dates when thinking in terms of the number of weeks in the ISO calculation.
For example, given start_date = "2010-12-26" and end_date = "2011-01-25" you will be going through W51,52,01,02,03,04 and those are 6 weeks as per ISO, but if you simply calculate the difference and divide by 7, you'll get 5.
The issue appears when the start date and end date belong to different years.
The best way to do the calculation is to get the last week number of the start_date year and it should refer to the December, 28.
function weeks($ladate2,$ladate3) {
$start_week= date("W",strtotime($ladate2));
$end_week= date("W",strtotime($ladate3));
$number_of_weeks= $end_week - $start_week;
$weeks=array();
$weeks[]=$start_week;
$increment_date=$ladate2;
$i="1";
if ($number_of_weeks<0){
$start_year=date("Y",strtotime($ladate2));
$last_week_of_year= date("W",strtotime("$start_year-12-28"));
$number_of_weeks=($last_week_of_year-$start_week)+$end_week;
}
while ($i<=$number_of_weeks)
{
$increment_date=date("Y-m-d", strtotime($ladate2. " +$i week"));
$weeks[]=date("W",strtotime($increment_date));
$i=$i+1;
}
return $weeks;
}
function diff_weeks($ladate2,$ladate3) {
$weeks=weeks($ladate2,$ladate3);
$diff_weeks=count($weeks);
return $diff_weeks;
}
Best regards,
Manikam
MySQL has datediff which returns the difference in days between two dates, since MySQL 4.1.1.
Do note that, as per the manual, DATEDIFF(expr1,expr2) returns expr1 – expr2 expressed as a value in days from one date to the other. expr1 and expr2 are date or date-and-time expressions. Only the date parts of the values are used in the calculation.
You can use the TO_DAYS function on each date and subtract the two to calculate the difference in days.
DATEDIFF
Find the days and divide by 7
<?php
$dayDif = date('z',strtotime('2009-12-17)') - date('z',strtotime('2009-12-24)');
$numWeeks = $dayDif / 7;
?>
The z option for php's date function gives you the day of the year (0 - 365). By subtracting the two values you find how many days between dates. Then factor by seven for the number of weeks.
Read this page closely, the date() function is rich. http://php.net/manual/en/function.date.php