I have a website that was launched a few months ago. I would like to write some code that will look through every month, since launch, and grab metrics for that month.
My question is: What is the best way to specify a start date, and then iterate by month, all the way up until the current month (or to another specified date).
Does anyone have any suggestions? I'm using PHP and a mySQL database.
You could use strtotime, to increment the date by +1 month:
$date1 = strtotime('2009-01-01');
$date2 = strtotime('2010-01-01');
while ($date1 <= $date2) {
echo date('Y-m-d', $date1) . "\n";
$date1 = strtotime('+1 month', $date1);
}
And if you have PHP >= 5.3.0, you can use DateTime::add with an DateInterval object
Check the above example here.
I have a method which is optimal in results :
$begin = new DateTime( '2014-07-14' );
$end = new DateTime( '2014-08-01' );
$end = $end->modify( '+1 month' );
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($begin, $interval, $end);
foreach($period as $dt) {
var_dump($dt->format( "m" ));
}
Hope this will help.
If you start from last day of a 30 days month, you may lose some month in between using "+1 month". Try from 2015-06-30 to 2015-12-31 for example, it will skip september 2015.
Instead of using "+1 month", I suggest to use "first day of next month" instead:
$begin = new DateTime( '2015-06-30' );
$end = new DateTime( '2015-12-31' );
$end = $end->modify( 'first day of next month' );
$interval = DateInterval::createFromDateString('first day of next month');
$period = new DatePeriod($begin, $interval, $end);
foreach($period as $dt) {
var_dump($dt->format( "m" ));
}
this will list september 2015 as well.
I don't know the schema of your stored metrics, so here's a generic example:
Select total pageviews per month from Aug 1 thru Nov 30 2009
The code for MySQL:
SELECT DATE_FORMAT(s.date, '%Y-%m') AS year_month , SUM( s.pageviews ) AS s.pageviews_total
FROM statistics s
WHERE s.date BETWEEN '2009-08-01' AND '2009-11-30'
GROUP BY DATE_FORMAT(s.date, '%Y-%m')
ORDER BY DATE_FORMAT(s.date, '%Y-%m')
Having that aggregated table output may be enough for you. If not, you can loop through it with PHP and perform other manipulations.
$start_date = mktime(0, 0, 0, 1, 1, 2009);
$end_date = mktime(0, 0, 0, 10, 1, 2009);
$current_date = $start_date;
while($current_date <= $end_date) {
$current_date = strtotime("+1 month", $current_date);
}
That is one way to do it. Another one includes two loops over months and years separately.
But if you are know SQL well, you can get all your metrics and GROUP BY EXTRACT(YEAR_MONTH FROM date) right there in DB, which will most likely be faster.
Related
I want to render dates period base on start date and end date, for example:
Input:
Start date: 30/12/2017
End date: 31/03/2017
Interval: every month
Output I want:
30/12/2017
30/01/2018
30/03/2018 (February is missing because it not have 30th)
There my code:
function period_days($start_date, $int, $end_date){
$begin = new DateTime( $start_date );
$end = new DateTime( $end_date );
$interval = DateInterval::createFromDateString($int);
$period = new DatePeriod($begin, $interval, $end->modify( '+1 day' ));
return $period;
}
echo period_days('30-12-2017', '1 month', '31-03-2018');
Result return wrong (3rd should be "2018-03-30"):
"2017-12-30 00:00:00"
"2018-01-30 00:00:00"
"2018-03-02 00:00:00"
Edit: Explain about Input:
Start date format can be '31/12/2017' or 'first Monday of January 2018' or 'third Tuesday of December 2017' or '28 December 2017' ...
Interval can be '1 day', '1 month', '2 months', '1 year' ...
End date format is d-m-Y '01/12/2018'
I use this function to add schedule recurring event, something like plugin The Event Calendar, you guys can see example on https://wpshindig.com/events/community/add
I could suggest you a work around.
Since DatePeriod breaks for February, we could get Year and month and append date separately. But this will only be working for one year.
Example :
function periodDays($start_date, $int, $end_date){
$begin = new DateTime($start_date);
$end = new DateTime($end_date);
$startDay = $begin->format("d");
$interval = DateInterval::createFromDateString($int);
$period = new DatePeriod($begin, $interval, $end);
foreach($period as $date){
echo $date->format("Y-m-") .$startDay. "<br>";
}
}
I am making a page to let the clients choose a date for an appointment, so I need to build a list of the dates like this :
always begin from tomorrow, end by 6 months
always from Mondy to Saturday, no Sunday
the day of the week need to be in chinese, like "Monday" is "星期一", but the timezone is in France
Here is the php
date_default_timezone_set('Europe/Paris');
$tomorrow = date("Y年m月d日 l", time() + 86400);
$end = date("Y年m月d日 l", time() + 86400 * 7); // just 7 days for a try
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($tomorrow, $interval, $end);
foreach ($daterange as $date) {
echo $date . '<br/>';
}
This code is not working.
I need to build an array, which store all the dates of next 6 months, begin from tomorrow, without Sunday, the days need to be in chinese and the timezone needs to be in Europe, is that possible?
I think strtotime and array_push is what you are looking for. Try this:
$curDate = date('Y-m-d', strtotime('+1 day'));
$endDate = date('Y-m-d', strtotime('+6 months +1 day'));
$myArr = array();
while ($endDate >= $curDate) {
if (date('w', strtotime($curDate)) !== '0') array_push($myArr, $curDate);
$curDate = date('Y-m-d', strtotime($curDate . " +1 days"));
}
var_dump($myArr);
For the Options, create an array from sunday to saturday.
$weekdays = array('Sunday', ..., 'Saturday');
echo date('Y/m/d', strtotime($curDate)) . ' ' . $weekdays[date('w', strtotime($curDate))];
I have found a problem with using DatePeriod which might be because I am stupid lol.
As you can see I have added +1 to my end date because I want to include the last date of the range.
But my issue is when I have ending date 31 it makes it to 32 which is not a date so it throws out an error.
Is there a way to include the ending date or to make the +1 work?
$period = new DatePeriod(
new DateTime($event['startyear'].$event['startmonth'].$event['startdate']),
new DateInterval('P1D'),
new DateTime($event['endyear'].$event['endmonth'].$event['enddate'] +1)
);
foreach ($period as $savedDate) {
echo $savedDate;
}
You should create the date object for the initial date (without the +1) and then increment the day of that object by 1 day.
For example:
$date1 = new DateTime($event['endyear'].$event['endmonth'].$event['enddate']);
$date2 = new DateTime($event['endyear'].$event['endmonth'].$event['enddate']);
$date2->modify('+1 day');
$period = new DatePeriod($date1, new DateInterval('P1D'), $date2);
What about this:
$endDate = mktime(0,0,0, $event['endmonth'], $event['enddate'], $event['endyear']);
$counter = 0;
while($endDate >= $date = mktime(0,0,0, $event['startmonth'], $event['startdate']+$counter++, $event['startyear']) ) {
echo date('Y/m/d', $date);
}
I want to create a table like this...
Oct-01 | Oct-02 | Oct-03 | Oct-04 | etc etc
Using whatever month it is now.
I'm using this to get the first day...
$first = date('01-m-Y',strtotime('this month'));
How can I increment this by the amount of days in this month?
Use cal_days_in_month(CAL_GREGORIAN, date(j), 2013)?
But how to increment the first day.
I tried using '+1 day' in the strtotime, but nothing happened.
Any ideas?
PHP's DateTime class can be used here. You don't need to use cal_days_in_month function to calculate the number of days in a month -- DateTime handles it automatigically. And it's a lot more cleaner and supports a wide range of dates.
Here's how:
$start = new DateTime('first day of this month');
$end = new DateTime('first day of this month + 1 month');
$period = new DatePeriod($start, new DateInterval('P1D'), $end);
foreach($period as $day){
echo $day->format('M-d')."<br/>";
}
Demo!
I prefer using the DateTime object:
$date = new DateTime();
$date->modify('first day of this month');
$days = array();
for($i = 1; $i <= $date->format('t'); $i++){
$days[] = $date->format('M-d');
$date->modify('+1 day');
}
You could also add the whole date object to the array giving you flexibility later to use it however you want.
<?php
$days = array();
$maxDay = cal_days_in_month(CAL_GREGORIAN, date('j'), date('Y'));
for($i = 1; $i<$maxDay; ++$i) {
$days[] = sprintf(date('M')."-%1$02d", $i);
}
echo "<pre>";
var_dump($days);
Now you can do whatever you like with $days array...
http://phpfiddle.org/lite/code/fd1-1r2
Is there anyway to find the date difference in php? I have the input of from date 2003-10-17 and todate 2004-03-24. I need the results how many days is there within these two days. Say if 224 days, i need the output in days only.
I find the solution through mysql but i need in php. Anyone help me, Thanks in advance.
$start = new DateTime( '2003-10-17' );
$end = new DateTime( '2004-03-24' );
$diff = $start->diff( $end );
echo $diff->format( '%d days' );
...should do it.
For reference see DateTime and DateInterval.
Mind you though, this is only available as of PHP 5.3.
You can use the parse timestamp feature to convert dates to timestamps, subtract the timestamps, and then convert the resulting timestamp (seconds) to days:
floor((strtotime("2004-03-24") - strtotime("2003-10-17"))/86400);
Example is as below:
$startDate = new DateTime( '2013-04-01' ); //intialize start date
$endDate = new DateTime( '2013-04-30' ); //initialize end date
$holiday = array('2013-04-11','2013-04-25'); //this is assumed list of holiday
$interval = new DateInterval('P1D'); // set the interval as 1 day
$daterange = new DatePeriod($startDate, $interval ,$endDate);
foreach($daterange as $date){
if($date->format("N") <6 AND !in_array($date->format("Y-m-d"),$holiday))
$result[] = $date->format("Y-m-d");
}
echo "<pre>";print_r($result);
A detail blog is here: http://goo.gl/YOsfPX