PHP - Calculate the difference between two dates - php

I want to calculate the number of years between two dates. One of them is retrieved from the database while the other is taken from user input in date format.
I used this code to get the date from the user:
$today = $_POST['to-day'];
$tomonth = $_POST['to-month'];
$toyaer = $_POST['to-year'];
$dateto = date("$toyaer-$tomonth-$today");
And here is how I calculated it with the one retrieved from the database,
$start = $leaveresult['date']; // i took from database
$end = strtotime($dateto);
$difference = abs($end - $start);
$years = floor($difference / (60*60*24*365));
The problem is that the result I get is always 0.
I tried different methods but all of them resulted with 0 and one of them resulted with a huge number.

This is untested but I think something like this will work:
$today = $_POST['to-day'];
$tomonth = $_POST['to-month'];
$toyear = $_POST['to-year'];
$dateto = "$toyear-$tomonth-$today";
$start = $leaveresult['date'];// i took from database
$end = strtotime($dateto);
$difference = abs($end - $start);
$years = floor($difference / (60*60*24*365));
I am assuming $leaveresult['date'] is unix timestamp
Also please note that I fixed the post variable names.
If the start date is not in unix timestamp then use
$start = strtotime($leaveresult['date']);// i took from database

The DateTime class simplifies all this by giving you a diff method. This will return a DateInterval object which you can get the values you're looking for.
Assuming $_POST looks like this:
$_POST = array(
'to-year' => 2010,
'to-month' => 8,
'to-day' => 22
);
And $leaveresult['date'] looks like this:
$leaveresult = array(
'date' => date('Y-m-d H:i:s', strtotime('-5 years')));
You can do something like this...
$input_date = new DateTime(sprintf("%d-%d-%d", $_POST['to-year'], $_POST['to-month'], $_POST['to-day']));
$database_date = new DateTime($leaveresult['date']);
$diff = $database_date->diff($input_date);
echo $diff->format('%r%y years') . PHP_EOL;
echo $diff->format('%r%m months') . PHP_EOL;
echo $diff->format('%r%d days') . PHP_EOL;
$years = $diff->y;
Which will yield
3 years
1 months
5 days
And $years will equal 3

you need in both cases a timestamp - the one you formatted ( as date object ) and the one you get from the database...
so I think you'r approach wasn't wrong, if your getting timestamps in both cases... but finally you've tried to round the number with floor... and of course this will result in 0, if it's less than a year.
test it without rounding first, and test your timestamps, maybe something is wrong there, too?

Related

Efficiently check if exactly 2 days passed from given datetime in my case

I have following code that add 2 days to a given date.
$myDate = 2018-07-28 11:00:00; // the date is picked from db
$penaltyDays = 2;
$date1 = new DateTime($myDate);
$date1->add(new DateInterval("P{$penaltyDays}D")); // add N days
$now = new DateTime();
$interval = $date1->diff($now); // get difference
$days = $interval->d; // difference in days
I want value of $days must be 0 after passing exactly 48 hours. If 3 days are passed the value of $days should be -1.
I will also appreciate if someone tell me efficient/proper way to get the result.
To make an efficient code according to your specification then I would rather use strtotime than DateTime.
This code checks if the current time is larger than the database time + two (or three) days in seconds.
$myDate = "2018-07-28 11:00:00";
$unix = strtotime($myDate);
if(time() > ($unix + 86400*3)){
$days = -1;
}else if(time() > ($unix + 86400*2)){
$days = 0;
}else{
$days = "something else";
}
Echo $days;
https://3v4l.org/d6Q15

PHP: Function to divide the time between two timestamps into equal intervals getting stuck

I have a function where I pass total 5 parameters to it.
$Date1, $Time1, $Date2 and $Time2 and $Interval.
I first form a timestamp1 using Date1Time1, then form a timestamp2 using Date2Time2 , and then I divide these two timestamps into equal intervals of hours and then store into an associative array.
e.g.
$Date1 = 27-03-2016
$Time1 = 18:00
$Date2 = 27-03-2016
$Time2 = 21:00
Now I want to divide this time into equal time intervals of 60 mins, and then want to store into an associative array into below format.
$array = [27-03-2016 => 18:00 , 27-03-2016 => 19:00, 27-03-2016 => 20:00, 27-03-2016 => 21:00]
I have written below function in php. When I run this, the file is getting hanged forever and not responding anything and when I check the server logs then it gives
error: Maximum execution time of 30 seconds exceeded at line
$end_time = date('H-i',strtotime($end_timestamp));
As I am comparatively new to php, I am not able to understand what is going wrong.
function FindTimeSpan (&$Date1,&$Time1,&$Date2,&$Time2,&$Interval)
{
$timespan=array($Date1 => $Time1);
$timestamp1 = strtotime($Date1 . $Time1);
$timestamp2 = strtotime($Date2 . $Time2);
while( $Date1 < $Date2)
{
$start_timestamp = $timestamp1;
$end_timestamp = $timestamp2 . '+' .$Interval;
//Separating Date and Time from a timestamp
$end_date = date('Y-m-d',strtotime($end_timestamp));
$end_time = date('H-i',strtotime($end_timestamp));
//pushing value to an array
$timespan = array_merge($timespan, array($end_date => $end_time));
//setting the start value to the new end value
$timestamp1 = $end_timestamp;
}
echo 'timestamp array' . json_encode($timespan);
}
The problem you encounter is an infinite loop, which is caused by the condition $Date1 < $Date2 . You don't modify any of these two values, so the condition will always be true. Strangely, you don't use the different timestamp values that are modified, but you should.
Concerning that, you should replace $end_timestamp = $timestamp2 . '+' .$Interval; by simply $end_timestamp = $timestamp2 + $Interval ; . Using the single quotes and the point will make PHP think of this as a string operation instead of a mathematical operation. With this and using this loop condition $timestamp1 < $timestamp2, your code should stop.
As said in a comment, your array structure is impossible because you can't assign have the same key multiple times. Instead of this, you should create an array per date and pushing the different times to these arrays.
To do this, you should first fix the way you retrieve the date and time in the loop. In the following code, the call to strtotime is unnecessary as the function date requires a timestamp, so no need to convert this back to a string.
//Separating Date and Time from a timestamp
$end_date = date('Y-m-d',strtotime($end_timestamp));
$end_time = date('H-i',strtotime($end_timestamp));
You should also be consistent, the format used here for the date is not consistent with the format you gave as exemple.
Now as per your suggestions above, I have made few changes in my code as well as the requirement.
I have not decided to use Assoc array.
Instead I will divide the two stamps between equal timeintervals (assuming it is possible).
Then I am doing the simple array push of this string.
Later on once this array is form, I will parse it and take the Date and Time separate.
Now my code is not entering into infinite loop as I am comparing the two timestamps. But now, the issue is it is pushing the first value to the array but all the subsequent values are getting pushed as null
so the output I am getting from the below code is like
array[1459051200,null,null,null,......]
Below is the code
$Date1 = "2016-03-27";
$Time1 = "00:00";
$Date2 = "2016-03-30";
$Time2 = "22:00";
$Interval = '60';
FindTimeSpan ($Date1, $Time1, $Date2, $Time2, $Interval);
function FindTimeSpan (&$Date1,&$Time1,&$Date2,&$Time2,&$Interval)
{
$timestamp1 = strtotime($Date1 . $Time1);
$timespan=array();
array_push($timespan,$timestamp1);
echo 'Value of array timespan' . json_encode($timespan);
$timestamp2 = strtotime($Date2 . $Time2);
while( $timestamp1 < $timestamp2)
{
$start_timestamp = $timestamp1;
$end_timestamp = $timestamp1 + $Interval;
//pushing value to an array
array_push($timespan,$end_timespan);
//
$timestamp1 = $end_timestamp;
}
echo 'timestamp array' . json_encode($timespan);
}

How to get timespan values Codeigniter

I am trying to get the values from timespan() function in Code Igniter. I have one problem, how can I know whether each of the date format is displayed? For example in regards with the codes below, one timespan might be 2 Months, 6 Days, 13 Hours, 14 Minutes which would have 4 elements but another might be 2 Months, 1 Week, 3 Days, 4 Hours, 39 Minutes which has 5 elements. If do the preg_replace then I won't know which are the months or weeks or days etc.
So how do I find out if it is the week or days or hours etc? Because I want to convert the values into cycles like 39mins/1440mins would be 0.0270833 days, then I will calculate for the hours days weeks months and years and add all of them together
// Hold Cycle Time Conversion
foreach($results as $key => $values)
{
// Convert mysql timestamp to unix
$remove = array('-', ':', ' ');
$hold_timestamp = mysql_to_unix( str_replace( $remove, '', $values['hold_date'] ) );
// Get timespan
$hold_timestamp = timespan($hold_timestamp);
// Explode into arrays
$timestamp_format = explode(',', $hold_timestamp);
// Check each array to get value
foreach($timestamp_format as $ts)
{
$separated_stamp = preg_replace('/[^0-9]/', '', $ts);
/*** Stuck here, incomplete ***/
}
}
I've decided to abandon that logic and use PHP's Date Time class instead. Got some help from this post as well. Not sure if it's the best way but it's what I've found.
// Hold Cycle Time Conversion
foreach($results as $key => $values)
{
// Declare timestamps
$last = new DateTime( $values['hold_date'] );
$now = new DateTime( date( 'Y-m-d h:i:s', time() )) ;
// Find difference
$interval = $last->diff($now);
// Store in variable to be used for calculation etc
$years = (int)$interval->format('%Y');
$months = (int)$interval->format('%m');
$days = (int)$interval->format('%d');
$hours = (int)$interval->format('%H');
$minutes = (int)$interval->format('%i');
}

PHP Incrementing date with day name

I am currently attempting to get a list of dates from a current date using the following format so that I can process it and stick it in my database
Saturday/02-05-2015
So far, i've managed to get the system to output the date correctly, but can not get it to increment in single day values.
My current code to attempt to increment this is the following
$tempStartDateN = ("$splode[0]/$splode[1]/$splode[2]/$splode[3]");
echo $tempStartDateN;
$tempStartDateN = date('l/d/m/Y', strtotime($tempStartDateN . ' + 1 day'));
echo $tempStartDateN;
I am currently using explode to process the data after the increment, which works fine, but can not get the date itself to increment as long as the day name is included.
Currently, the time is got using this code, which is processed afterwords using explode
$OldDateArray = date("Y/m/d/l");
So to keep a long question short, what is the best way to increment a date that requires the day name, day, month then year?
EDIT:
Heres my current code, managed to get this far thanks to SamV
$date = date("l/d/m/Y");
echo $date;
echo ('</br>');
list($weekdayName, $dateString) = explode("/", $date, 2);
$dateObj = new \DateTime($dateString);
for($i=0; $i<=5; $i++){
$dateObj->add(new \DateInterval("P1D")); // P1D stands for "Period 1 Day"
echo $dateObj->format("l/d/m/Y"); // Sunday/03/05/2015
echo ('</br>');
}
What this does however is:
Friday/01/05/2015
Tuesday/06/01/2015
Wednesday/07/01/2015
Thursday/08/01/2015
Friday/09/01/2015
Saturday/10/01/2015
Sunday/11/01/2015
this means that date and month are swapping around, what is causing this?
You don't need to parse the week day name to add days onto a date.
$date = "Saturday/02-05-2015";
list($weekdayName, $dateString) = explode("/", $date, 2); // Parse "02-05-2015"
$dateObj = new \DateTime($dateString);
$dateObj->add(new \DateInterval("P1D")); // P1D stands for "Period 1 Day"
echo $dateObj->format("l/d/m/Y"); // Sunday/03/05/2015
I used the DateTime class, here is the documentation.
I wrote out what you are trying to do yourself, not sure what is causing your issue. This code works though.
$date = "Friday/01-05-2015";
list($weekdayName, $dateString) = explode("/", $date, 2); // Parse "01-05-2015"
$dateObj = new \DateTime($dateString);
for($i = 0; $i < 5; $i++) {
$dateObj->add(new \DateInterval("P1D")); // P1D stands for "Period 1 Day"
echo $dateObj->format("l/d/m/Y") . '<br>';
}
Outputs:
Saturday/02/05/2015
Sunday/03/05/2015
Monday/04/05/2015
Tuesday/05/05/2015
Wednesday/06/05/2015
If strtotime is able to parse a date it returns the timestamp. Why not add to it the number of seconds in a day? Smth. like $timestamp += 24 * 3600;
P.S. As far as I can understand, strtotime may accept timestamp as second argument (http://us2.php.net/manual/en/function.strtotime.php) smth. like $timestamp = strtotime('+1 day', $timestamp);

Calculates difference between two dates in PHP [duplicate]

This question already has answers here:
Get interval seconds between two datetime in PHP?
(8 answers)
Closed last year.
HI, i have a couple of posts in my MySql database server, one of the info content in each post is the date and time in the format datetime (Ex. 2010-11-26 21:55:09) when the post was made.
So, i want to retrive the actual date and time from the SQL server with the function NOW() and calculates how many seconds or minutes or hours or days ago was post the info.
I dont know how to create this php script but i know that for sure is allready made, so thanks for any help.
you could use the date_diff() function
http://php.net/manual/en/function.date-diff.php
Something like...
<?php
$now = time();
$then = $posttime;
$diff = date_diff($now,$then);
echo $diff->format('%R%d days'); #change format for different timescales
?>
edit --
I actually solve this issue on one of my twitter apps using this function...
function time_since ( $start )
{
$end = time();
$diff = $end - $start;
$days = floor ( $diff/86400 ); //calculate the days
$diff = $diff - ($days*86400); // subtract the days
$hours = floor ( $diff/3600 ); // calculate the hours
$diff = $diff - ($hours*3600); // subtract the hours
$mins = floor ( $diff/60 ); // calculate the minutes
$diff = $diff - ($mins*60); // subtract the mins
$secs = $diff; // what's left is the seconds;
if ($secs!=0)
{
$secs .= " seconds";
if ($secs=="1 seconds") $secs = "1 second";
}
else $secs = '';
if ($mins!=0)
{
$mins .= " mins ";
if ($mins=="1 mins ") $mins = "1 min ";
$secs = '';
}
else $mins = '';
if ($hours!=0)
{
$hours .= " hours ";
if ($hours=="1 hours ") $hours = "1 hour ";
$secs = '';
}
else $hours = '';
if ($days!=0)
{
$days .= " days ";
if ($days=="1 days ") $days = "1 day ";
$mins = '';
$secs = '';
if ($days == "-1 days ") {
$days = $hours = $mins = '';
$secs = "less than 10 seconds";
}
}
else $days = '';
return "$days $hours $mins $secs ago";
}
You pass it in a unix timestamp of the time to check (the post time) and it returns the various string.
As billythekid said, you can use the date_diff() function if you are using PHP5.3+, if you are not then there are various methods. As shown by other posters. The quickest method in MySQL if you want to know the time split in to the "hours:mins:secs" hierarchy is to use the TIMEDIFF() function.
SELECT TIMEDIFF(NOW(), '2010-11-26 12:00:00');
If you want it as seconds, use the unix timestamp features in MySQL or in PHP, you can convert MySQL dates to PHP quickly using strtotime().
Usually, you do this kind of thing in a query, but MySQL isn't very good with intervals (it would be very easy with PostgreSQL). You could convert it to unix timestamp, then it would give the number of seconds between the two dates :
SELECT UNIX_TIMESTAMP() - UNIX_TIMESTAMP(your_datetime_column);
I thought about DATEDIFF, but it only returns the number of days between the two dates.
You can do it in PHP, for instance, with DateTime class :
$date1 = new DateTime();
$date2 = new Datetime('2010-11-26 12:00:00');
var_dump($date1->diff($date2));
(There's a procedural way to do this, if you're not a fan of OOP.)
This is definitely the solution I'd use if I can't do it with the RDBMS. DateTime::diff returns a DateInterval object, which contains the number of seconds, minutes, hours, days, etc. between the two dates.
You could also do it with timestamps in PHP :
$num_sec = time() - strtotime('2010-11-26 12:00:00');
Which would return the same thing as the SQL query.
An easy solution is possible from within the SQL Query:
SELECT UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(post_date) AS seconds_ago FROM posts
Documentation here: MySQL Ref
I actually needed to do this in PHP myself and while billythekid's post was in the right direction it fell short. I've minimized the code though it should be clear that the second parameter is from a database with a DATETIME column type.
<?php
$interval = date_diff(date_create(date('Y-m-d H:i:s')), date_create($row1['date']));
echo $interval->format('%R%a days');
//Database: 2019-02-22
//PHP's date: 2018-07-07
//Result: +306 days
?>
A reminder of the obvious: you can also just use substr($interval->format('%R%a days'),1) if you need just the integer.

Categories