A site contains monthly data in a JSON format. This can be queried like so:
http://www.example.com?startdate=1-1-1985&enddate=31-1-1985
I want to be able to run a script that will obtain the specific data I am looking for, starting from today's month, then work backward until null data is returned. Each month's value needs to add up. So far, this is what I've got:
//Build base URL:
$userid=$_GET['userid'];
$startdate=/*Beginning of today's month*/;
$enddate=/*End of today's month*/;
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
//Set JSON variables:
$get=file_get_contents($url);
$json=json_decode($get);
//Set loop variables:
$value=0;
$month=0;
/*For each month from today backwards{
$number=$json->integer;
if($number!=null){
$value=$value+$number;
$month=$month+1;
}else{
break;
}
}
echo $value;
echo $month;
*/
The part I'm having problems with is the beginning of the fourth part. How do I run a loop that starts with the range of today's month, obtain $number, then repeat with the previous month, until it reaches a month that returns null?
You could use the DateTime object and it's associated methods ( specifically sub in this case ) to count backwards by subtracting 1month at a time. An array stores the months/dates and the url is constructed using the variable counter $i
Initially this has a maximum backwards range of 20years ( which I guessed would be more than enough ) but it's easy to change.
$df='Y-m-d';
$userid=$_GET['userid'];
$timezone=new DateTimeZone('Europe/London');
$interval=new DateInterval('P1M');
$ts=date( $df, strtotime( date('Y-m-1') ) );
$tf=date( $df, strtotime( date('Y-m-1'). ' - 20 years') );
$start=new DateTime( $ts, $timezone );
$end=new DateTime( $tf, $timezone );
$dates=array();
$i=0;
while( $start->sub( $interval ) > $end ){
$dates[]=$start->format( $df );
if( $i > 1 ){
$startdate=$dates[ $i - 1 ];
$enddate=$dates[ $i ];
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
echo $url,'<br />';
/* uncomment when happy with mechanism */
/*
$data=file_get_contents( $url );
if( $data ) ) {
$json=json_decode( $data );
#process.....
break;
}
*/
}
$i++;
}
A snippet of the output
http://www.example.com?userid=bobodaclown&startdate=2017-10-01&enddate=2017-09-01
http://www.example.com?userid=bobodaclown&startdate=2017-09-01&enddate=2017-08-01
http://www.example.com?userid=bobodaclown&startdate=2017-08-01&enddate=2017-07-01
http://www.example.com?userid=bobodaclown&startdate=2017-07-01&enddate=2017-06-01
http://www.example.com?userid=bobodaclown&startdate=2017-06-01&enddate=2017-05-01
http://www.example.com?userid=bobodaclown&startdate=2017-05-01&enddate=2017-04-01
http://www.example.com?userid=bobodaclown&startdate=2017-04-01&enddate=2017-03-01
By using strtotime() and mktime() functions you can while loop until you get Null results. The below code will print 5 urls for 5 months. Change while condition accordingly.
// define $i
$i=0;
$userid = '343';//$_GET['userid']; //dont forget to replace with userid
do{
$timestring = strtotime("now -$i month");
//get Month
$month = date('m',$timestring);
//get Year
$year = date('Y',$timestring);
// First date Month and Year
$startdate = date('d-m-Y', mktime(0, 0, 0, $month, 1, $year));
// Last date Month and Year
$enddate = date('d-m-Y', mktime(0, 0, 0, $month+1, 0,$year));
$url='http://www.example.com?userid='.$userid.'&startdate='.$startdate.'&enddate='.$enddate;
// commenting your code
//Set JSON variables:
//$get=file_get_contents($url);
//$json=json_decode($get);
// $number=$json->integer;
echo $url;
echo "\n";
$i++;
}while ($i!=5); // change while condition according to your requirement. while ($number!=null)
Out Put:
http://www.example.com?userid=343&startdate=01-12-2017&enddate=31-12-2017
http://www.example.com?userid=343&startdate=01-11-2017&enddate=30-11-2017
http://www.example.com?userid=343&startdate=01-10-2017&enddate=31-10-2017
http://www.example.com?userid=343&startdate=01-09-2017&enddate=30-09-2017
http://www.example.com?userid=343&startdate=01-08-2017&enddate=31-08-2017
Related
I'm trying to get days count between two dates from database. Date_from and Date_to. And I'm getting an error. Any help would be appreciated.
The code:
<?php
require('config/conn.php');
// Select all from table 'reguests'
$query = 'SELECT * FROM requests';
//Results from table
$result = mysqli_query($conn, $query);
//Fetch data
$requests = mysqli_fetch_all($result, MYSQLI_ASSOC);
//Free result from fetch
mysqli_free_result($result);
//Get Days Count Between Dates From And To
$dateFrom = $request['date_from'];
$dateTo = $requests['date_to'];
$daysDiff = floor(abs(strtotime($dateTo) - strtotime($dateFrom)) / (60*60*24));
//Close conn
mysqli_close($conn);
?>
Output:
<td><?php echo $daysDiff ?>
Your question title says to exclude weekends, but your code doesn't seem to try to?
To account for more complicated logic like that it's probably prudent to calculate a period and use it to iterate over days.
Something like this:
$dateFrom = new DateTime();
$dateTo = new DateTime( '+1 month +1 second' ); // Add 1s so period includes last day.
$period = new DatePeriod( $dateFrom, new DateInterval( 'P1D' ), $dateTo );
$days = 0;
foreach ( $period as $date ) {
$day = $date->format( 'l' );
if ( 'Saturday' !== $day && 'Sunday' !== $day ) {
$days ++;
}
}
echo $days; // 23
Please review your title, it's ambiguous with your problem. But to check difference between dates, please check the Php manual on the link: http://php.net/manual/en/datetime.diff.php
If you really wanna check if a day is weekend, please check: Checking if date is weekend PHP
I am using an ACF Field to allow a client to content manage a countdown to their next event I am using JS flip clock on the desktop version but as it isn't responsive, I decided to use date diff to echo out just the number of days for mobile.
The site is currently live at theindustrialproject.co.uk
The code I currently have is this:
<?php
$date1 = date_create(date());
$date2 = date_create(the_field('mobile_date'));
$diff = date_diff($date1,$date2);
$difference = $diff;
if ($difference < 0) { $difference = 0; }
echo '<span class="countdown-mobile">'. floor($difference/60/60/24)."</span><br />";
if ($difference == 1) { echo "<p>Day</p>"; }
else { echo "<p>Days</p>"; }
?>
but it always returns 0. For reference, I pulled the code from here
Without knowing what the function the_field('mobile_date') will return ( either a date or timestamp? ) you might need to alter that particular line below but you should be able to use the DateTime object and format the difference like this
$format='Y-m-d';
$timezone=new DateTimeZone('Europe/London');
/* We need 2 datetime objects - one for now the other for the future date */
$now=new DateTime( date( $format, strtotime('now') ), $timezone );
$target=new DateTime( the_field('mobile_date'), $timezone );
/* Format the difference in days */
$days = $now->diff( $target )->days;
echo "<span class='countdown-mobile'>{$days}</span><br />" . ( $days == 1 ? '<p>Day</p>' : '<p>Days</p>' );
I've been reading about problems in php with strtotime and "next month" issues. What i want to make is counter of months between two dates.
For example if I have start date 01.02.2012 and stop date 07.04.2012 I'd like to get return value - 3 months. Also 3 months would be the result if start date i 28.02.2012 and 07.04.2012. I am not counting exact number of days/months, just a number of months I have between two dates. It's not a big deal to make it with some strange date, mktime and strtotime usage, but unfortunatelly start and stop dates might be in two different years so
mktime(0,0,0,date('m')+1,1,date('Y');
isnt going to work (i do not now the year and if it changes between start and stop date. i can calculate it but it is not nice solution). Perfect solution would be to use:
$stat = Array('02.01.2012', '07.04.2012')
$cursor = strtotime($stat[0]);
$stop = strtotime($stat[1]);
$counter = 0;
while ( $cursor < $stop ) {
$cursor = strtotime("first day of next month", $cursor);
echo $cursor . '<br>';
$counter++;
if ( $counter > 100) { break; } // safety break;
}
echo $counter . '<br>';
Unfortunatelly strtotime isnt returning proper values. If I use it is returning empty string.
Any ideas how to get timestamp of the first day of next month?
SOLUTION
$stat = Array('02.01.2012', '01.04.2012');
$start = new DateTime( $stat[0] );
$stop = new DateTime( $stat[1] );
while ( $start->format( 'U') <= $stop->format( 'U' ) ) {
$counter ++;
echo $start->format('d:m:Y') . '<br>';
$start->modify( 'first day of next month' );
}
echo '::' . $counter . '..<br>';
<?php
$stat = Array('02.01.2012', '07.04.2012');
$stop = strtotime($stat[1]);
list($d, $m, $y) = explode('.', $stat[0]);
$count = 0;
while (true) {
$m++;
$cursor = mktime(0, 0, 0, $m, $d, $y);
if ($cursor < $stop) $count ++; else exit;
}
echo $count;
?>
the easy way :D
I have a MySQL table with events in it. Each event has a datetime column that indicates when it starts.
I'm looking for a way to produce a string similar to this using PHP:
'event X starts in 2 hours'
Should also work for days, weeks and months:
'event X starts in 5 days/weeks/months'
You should have some variable with the number of seconds till your date available. My example function is below.
<?php
function timeRemaining($total) {
if (!$total || $total <= 0) return false;
// define your ranges here (desc order), the keys will go to output.
$elements = array(
"years" => 60*60*24*30*12,
"months" => 60*60*24*30,
"weeks" => 60*60*24*7,
"days" => 60*60*24,
"hours" => 60*60,
"minutes" => 60,
"seconds" => 1
);
// compute in a cycle to compress the code
$return = array();
foreach ($elements as $name => $dur) {
$return[$name] = floor($total / $dur);
$total -= $return[$name] * $dur;
}
// return data in the array form
return $return;
}
// how much till new year?
echo "<pre>",
print_r(timeRemaining(mktime(0,0,0,1,1,2012)-time()));
echo "</pre>";
?>
Just copy-paste into any php file for testing, as an example it returns the array with years, months etc remaining till new year. You can tailor the output for your needs by feeding the return value to another string-generating function, just don't forget to check the value against false, which'll mean the time has passed.
Please note that the months use a simplified 30-days range, and the year here is set to 360 days, not 365.25 as in the real world.
Hope it will be of use.
To use this I first changed the format of the date to:
Select DATE_FORMAT(date_of, '%d/%m/%Y') as example from tbl
The php Function:
<?php
function days_ago($time)
{
$today = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
$time_array = explode("/", $time);
if(count($time_array) < 2)
{
$time = "N/A";
}
else
{
$time = mktime(0, 0, 0, date($time_array[1]), date($time_array[0]), date($time_array[2]));
$daysAgo = $today - $time;
$time = ($daysAgo/86400);
}
return $time;
}
?>
I took the following snippet from the here.
<?php
$dateDiff = $date1 - $date2;
$fullDays = floor($dateDiff/(60*60*24));
$fullHours = floor(($dateDiff-($fullDays*60*60*24))/(60*60));
$fullMinutes = floor(($dateDiff-($fullDays*60*60*24)-($fullHours*60*60))/60);
echo "Differernce is $fullDays days, $fullHours hours and $fullMinutes minutes.";
?>
$date1 would be the database date, $date2 would be the current date. Does that help?
I have a start date of 20090101 and an end date of 20091130 and I'm trying to build and array of all the months in between, which would look like this:
<?php
/* ... */
$arrDates['Jan'] = 2009;
$arrDates['Feb'] = 2009;
$arrDates['Mar'] = 2009;
/* ... */
?>
How can I do this?
I don't fully understand your array structure.
But maybe this helps: When using PHP 5.3 you can use code like below to get an iterator with all months in the given range:
<?php
$db = new DateTime( '2009-01-01 00:00:00' );
$de = new DateTime( '2009-11-30 23:59:59' );
$di = DateInterval::createFromDateString( 'first day of next month' );
foreach ( $di as $dt )
{
echo $dt->format( "Y-m\n" );
}
?>
The following snippet creates such an array:
$startDate = '20090101';
$endDate = '20091130';
$arrDates = array();
$cur = strtotime($startDate);
$end = strtotime($endDate);
while ($cur < $end) {
$arrDates[date('M', $cur)] = date('Y', $cur);
$cur = mktime(0, 0, 0, date('m', $cur) + 1, 1, date('Y', $cur));
}
// If you want to add the 'end' month too...
$arrDates[date('M', $end)] = date('Y', $end);
However, note that, as danii commented, you are unclear about how you want to handle a timespan that is larger than a year. The code above will simply use the last year in the range you provide.
This code will work with pretty much any version of PHP (PHP 4+). If you want a more elegant solution and are using PHP 5.2+, I recommend the solution offered by GZipp.
I had a similar situation for a website i was building for travelagency. You need timestamps, arrays and looping. Take a look at the date function PHP provides. It gives you some interesting options to play with dates. E.g. the no. of days in a specified month.
You say "the months in between", but since your example includes the starting month, I assume you mean "the months in between plus the starting and ending months".
$dt_start = new DateTime('20090101');
$dt_end = new DateTime('20091130');
$arrDates[] = $dt_start->format('M');
while ($dt_start->modify('first day of next month') <= $dt_end) {
$arrDates[] = $dt_start->format('M'); // Or whatever you want to do with it.
}
(This is essentially johannes' solution with a little manual reading applied to adapt it for PHP 5.2.)
You can't use the month as a key, the key must be unique or if your range spans more than a year it won't work correctly.
This will return an array with Mon-Year as the key
function foo($startdate, $enddate) {
// create a timestamp for start date
if(!preg_match('/^(\d{4})(\d{2})(\d{2})$/', $startdate, $m)) die('Invalid start date format');
$start_time = mktime(0, 0, 0, $m[2], $m[3], $m[1]);
// create a timestamp for end date
if(!preg_match('/^(\d{4})(\d{2})(\d{2})$/', $enddate, $m)) die('Invalid end date format');
$end_time = mktime(23, 59, 59, $m[2], $m[3], $m[1]);
// build the array of months by incrementing $start_time by one month through each iteration
$ret = array();
while($start_time < $end_time) {
$ret[date('M-Y', $start_time)] = date('Y', $start_time);
$start_time = strtotime(date('m/d/Y', $start_time).' +1month');
}
return $ret;
}
$arrDates = foo('20090101', '20111130');
print_r($arrDates);
Array(
[Jan-2009] => 2009
[Feb-2009] => 2009
[Mar-2009] => 2009
[Apr-2009] => 2009
[May-2009] => 2009
[Jun-2009] => 2009
[Jul-2009] => 2009
[Aug-2009] => 2009
....
)
A bit convoluted but works...:
function buildDateRange($strStartDate, $strEndDate)
{
$strStartM = date('M', $strStartDate);
$strStartY = date('Y', $strStartDate);
$strEndM = date('M', $strEndDate);
$strEndY = date('Y', $strEndDate);
$intCurMN = date('m', $strStartDate);
$ii = 0;
$blnFinished = FALSE;
while(!$blnFinished)
{
$strCurM = date('M', mktime(0, 0, 0, $intCurMN , "01", $strStartY));
$strCurY = date('Y' ,mktime(0, 0, 0, $intCurMN , "01", $strStartY));
$arrSearchDates [$strCurM] = $strCurY;
$intCurMN = date('m', mktime(0, 0, 0, $intCurMN+1 , "01", $strStartY));
if($strEndM == $strCurM && $strEndY == $strCurY)
{
$blnFinished = TRUE;
}
}
Return ($arrSearchDates);
}