How to get millisecond between two DateTime objects?
$date = new DateTime();
$date2 = new DateTime("1990-08-07 08:44");
I tried to follow the comment below, but I got an error.
$stime = new DateTime($startTime->format("d-m-Y H:i:s"));
$etime = new DateTime($endTime->format("d-m-Y H:i:s"));
$millisec = $etime->getTimestamp() - $stime->getTimestamp();`
I get the error
Call to undefined method DateTime::getTimestamp()
In the strict sense, you can't.
It's because the smallest unit of time for the DateTime class is a second.
If you need a measurement containing milliseconds then use microtime()
Edit:
On the other hand if you simply want to get the interval in milliseconds between two ISO-8601 datetimes then one possible solution would be
function millisecsBetween($dateOne, $dateTwo, $abs = true) {
$func = $abs ? 'abs' : 'intval';
return $func(strtotime($dateOne) - strtotime($dateTwo)) * 1000;
}
Beware that by default the above function returns absolute difference. If you want to know whether the first date is earlier or not then set the third argument to false.
// Outputs 60000
echo millisecsBetween("2010-10-26 20:30", "2010-10-26 20:31");
// Outputs -60000 indicating that the first argument is an earlier date
echo millisecsBetween("2010-10-26 20:30", "2010-10-26 20:31", false);
On systems where the size of time datatype is 32 bits, such as Windows7 or earlier, millisecsBetween is only good for dates between 1970-01-01 00:00:00 and 2038-01-19 03:14:07 (see Year 2038 problem).
Sorry to digg out an old question, but I've found a way to get the milliseconds timestamp out of a DateTime object:
function dateTimeToMilliseconds(\DateTime $dateTime)
{
$secs = $dateTime->getTimestamp(); // Gets the seconds
$millisecs = $secs*1000; // Converted to milliseconds
$millisecs += $dateTime->format("u")/1000; // Microseconds converted to seconds
return $millisecs;
}
It requires however that your DateTime object contains the microseconds (u in the format):
$date_str = "20:46:00.588";
$date = DateTime::createFromFormat("H:i:s.u", $date_str);
This is working only since PHP 5.2 hence the microseconds support to DateTime has been added then.
With this function, your code would become the following :
$date_str = "1990-08-07 20:46:00.588";
$date1 = DateTime::createFromFormat("Y-m-d H:i:s.u", $date_str);
$msNow = (int)microtime(true)*1000;
echo $msNow - dateTimeToMilliseconds($date1);
DateTime supports microseconds since 5.2.2. This is mentioned in the documentation for the date function, but bears repeating here. You can create a DateTime with fractional seconds and retrieve that value using the 'u' format string.
<?php
// Instantiate a DateTime with microseconds.
$d = new DateTime('2011-01-01T15:03:01.012345Z');
// Output the microseconds.
echo $d->format('u'); // 012345
// Output the date with microseconds.
echo $d->format('Y-m-d\TH:i:s.u'); // 2011-01-01T15:03:01.012345
// Unix Format
echo "<br>d2: ". $d->format('U.u');
function get_data_unix_ms($data){
$d = new DateTime($data);
$new_data = $d->format('U.u');
return $new_data;
}
function get_date_diff_ms($date1, $date2)
{
$d1 = new DateTime($date1);
$new_d1 = $d1->format('U.u');
$d2 = new DateTime($date2);
$new_d2 = $d2->format('U.u');
$diff = abs($new_d1 - $new_d2);
return $diff;
}
https://www.php.net/manual/en/class.datetime.php
Here's a function to do that + tests.
https://gist.github.com/vudaltsov/0bb623b9e2817d6ce359eb88cfbf229d
DateTime dates are only stored as whole seconds. If you still need the number of milliseconds between two DateTime dates, then you can use getTimestamp() to get each time in seconds (then get the difference and turn it into milliseconds):
$seconds_diff = $date2.getTimestamp() - $date.getTimestamp()
$milliseconds_diff = $seconds_diff * 1000
Related
This is my code:
$d2 = new DateTime("2019-01-01 02:24:19.769002");
echo $d2->format("Y-m-d H:i:s.u");
$tBefore = microtime(true);
// GET ANOTHER DATA
$tAfter = microtime(true);
$d2->modify('+'.($tAfter-$tBefore).' microsecond');
echo $d2->format("Y-m-d H:i:s.u");
But my code return wrong date for milliseconds.
I want to add seconds with milliseconds to first date and get times of ANOTHER DATA.
Actually if ANOTHER DATA take 0.100 milliseconds, my result should be 2019-01-01 02:24:19.869002
You can use DateTime and DateInterval:
<?php
$d2 = new DateTime('2019-01-01 02:24:19.769002');
$tBefore = new DateTime();
// `sleep` to simulate work done between `$tBefore` and `$tAfter`
sleep(1);
$tAfter = new DateTime();
$d2->add($tBefore->diff($tAfter));
print_r($d2);
https://www.php.net/manual/en/class.dateinterval.php
https://www.php.net/manual/en/datetime.add
https://www.php.net/manual/en/datetime.diff
As of PHP 7.1, microseconds can also be easily added to DateTime using the modify method. The microsecond value must be an integer and cannot be a float. microtime (true) also delivers seconds as float and not microseconds.
$date = new DateTime("2019-01-01 02:24:19.769002");
$seconds = 0.100;
$intMicroseconds = intval($seconds * 1000000);
$date->modify($intMicroseconds.' microseconds');
echo $date->format("Y-m-d H:i:s.u");
//2019-01-01 02:24:19.869002
I'm trying to find the current date and time, convert to a unix timestamp, and then subtract a previous time. I've tried multiple approaches and have received errors or incorrect values. So far here is my code:
// Current date and time
$currentTime = date("Y-m-d H:i:s");
// Convert datetime to Unix timestamp
$currentTimestamp = strtotime($currentTime);
// Create previous date and time
$previousTime = new DateTime("2021-04-17 13:00:00");
// Specify display format
$previousTime->format('Y-m-d H:i:s');
// Convert to Unix timestamp
$previousTimestamp = strtotime($previousTime);
// Subtract previous time from current time
$time = $currentTimestamp - $previousTimestamp;
// Display result
echo $time;
So how it should work is if the current date and time is for example: 2021-04-17 14:00:00 and the previous date and time is 2021-04-17 13:00:00, then the result should be 3600. Or if there is a two hour gap, then it's 7200, etc. With this current code, the error I'm getting is:
Uncaught TypeError: strtotime(): Argument #1 ($datetime) must be of
type string, DateTime
And other code I have tried doesn't return the correct time difference or other errors are thrown. How do I get the correct time difference?
You need to read the docs about what each function expects as an argument and what each returns. You're mixing a timestamp (an integer) with a DateTime object. If you want to do date calculations, you'll need to use the same format for both. Since you're looking for the number of seconds difference, it's probably simpler to use timestamp integers.
This code gives you an integer timestamp:
$currentTime = date("Y-m-d H:i:s");
$currentTimestamp = strtotime($currentTime);
But note that "now" is the default return value for the time() function, so you can just do this instead:
$currentTimestamp = time();
And you don't need this:
// This gives you a DateTime object
$previousTime = new DateTime("2021-04-17 13:00:00");
// This doesn't change the internal representation,
// it just returns a value that you're not using.
$previousTime->format('Y-m-d H:i:s');
// This function expects a string, but you're giving an object.
$previousTimestamp = strtotime($previousTime);
Instead, you can just pass your formatted date string directly to strtotime() and it will return an integer timestamp:
$previousTimestamp = strtotime("2021-04-17 13:00:00");
Now you have two integers representing seconds, so you can just subtract them to get the number of seconds between. Your prog becomes:
$currentTimestamp = time();
$previousTimestamp = strtotime("2021-04-17 13:00:00");
$diff = $currentTimestamp - $previousTimestamp;
echo $diff;
Or just:
echo time() - strtotime("2021-04-17 13:00:00");
What is the "cleanest" way to add a date and a time string in PHP?
Albeit having read that DateTime::add expects a DateInterval, I tried
$date = new \DateTime('17.03.2016');
$time = new \DateTime('20:20');
$result = $date->add($time);
Which was no good and returned nothing to $result.
To make a DateInterval from '20:20', I only found very complex solutions...
Maybe I should use timestamps?
$date = strtotime($datestring);
$timeObj = new \DateTime($timestring);
// quirk to only get time in seconds from string date
$time = $timeObj->format('H') * 3600 + $timeObj->format('i') * 60 + $timeObj->format('s');
$datetime = $date+$time;
$result = new \DateTime;
$result->setTimestamp($datetime);
In my case, this returns the desired result, with the correct timezone offset. But what do you think, is this robust? Is there a better way?
If you want to add 20 hours and 20 minutes to a DateTime:
$date = new \DateTime('17.03.2016');
$date->add($new \DateInterval('PT20H20M'));
You do not need to get the result of add(), calling add() on a DateTime object will change it. The return value of add() is the DateTime object itself so you can chain methods.
See DateInterval::__construct to see how to set the intervals.
DateTime (and DateTimeImmutable) has a modify method which you could leverage to modify the time by adding 20 hours and 20 minutes.
Updated
I've included examples for both DateTime and DateTimeImmutable as per the comment made, you don't need to assign the outcome of modify to a variable because it mutates the original object. Whereas DateTimeImmutable creates a new instance and doesn't mutate the original object.
DateTime
<?php
$start = new DateTimeImmutable('2018-10-23 00:00:00');
echo $start->modify('+20 hours +20 minutes')->format('Y-m-d H:i:s');
// 2018-10-23 20:20:00
Using DateTime: https://3v4l.org/6eon8
DateTimeImmutable
<?php
$start = new DateTimeImmutable('2018-10-23 00:00:00');
$datetime = $start->modify('+20 hours +20 minutes');
var_dump($start->format('Y-m-d H:i:s'));
var_dump($datetime->format('Y-m-d H:i:s'));
Output
string(19) "2018-10-23 00:00:00"
string(19) "2018-10-23 20:20:00"
Using DateTimeImmutable: https://3v4l.org/oRehh
I have a PHP DateTime object with microseconds created as follows:
$time = microtime(true);
$microseconds = sprintf('%06d', ($time - floor($time)) * 1000000);
$dt = new DateTime(date('Y-m-d H:i:s.' . $microseconds, $time));
How can I modify the microseconds value of $dt, without creating a completely new DateTime instance?
You can't.
There are three methods that can modify the value of a DateTime instance: add, sub and modify. We can rule out add and sub immediately because they work in terms of a DateInterval which does not have sub-second precision.
modify accepts a string in one of the standard recognized formats. Of those formats, only the relative ones are of interest here because the other ones work in an absolute manner; and there is no relative format that allows tweaking the msec part (that unit is not recognized).
as of PHP 7.1
DateTime::setTime() supports microseconds.
This seems to have been available since 7.1.0-rc4
$dt = new DateTime('2020-01-01 0:00');
$dt->modify('+500 ms'); // Milliseconds.
$dt->modify('+123456 usec'); // Microseconds.
$dt->modify('+123456 microseconds'); // This works too.
It's mentioned here in the manual.
Manually creating a DateTime object with micro seconds:
$d = new DateTime("15-07-2014 18:30:00.111111");
Getting a DateTime object of the current time with microseconds:
$d = date_format(new DateTime(),'d-m-Y H:i:s').substr((string)microtime(), 1, 8);
Difference between two DateTime objects in microseconds (e.g. returns: 2.218939)
//Returns the difference, in seconds, between two datetime objects including
//the microseconds:
function mdiff($date1, $date2){
$date1sec = strtotime($date1->format('d-m-Y H:i:s.u'));
$date2sec = strtotime($date2->format('d-m-Y H:i:s.u'));
//Absolute val of Date 1 in seconds from (EPOCH Time) - Date 2 in seconds from (EPOCH Time)
$secdiff = abs($date1sec-$date2sec);
//Creates variables for the microseconds of date1 and date2
$micro1 = $date1->format("u");
$micro2 = $date2->format("u");
if (($date1sec<$date2sec && $micro1>$micro2)||($date1sec>$date2sec && $micro1<$micro2)){
$microdiff = abs(1000000 - abs($micro1-$micro2));
$secdiff = $secdiff - 1;
} else {
$microdiff = abs($micro1 - $micro2);
}
//Creates the variable that will hold the seconds (?):
$difference = $secdiff.".".$microdiff;
return $difference;
}
Essentially it finds the difference for the DateTime Objects using strtotime and then adding the extra microseconds on.
Do you need me to create add and sub?
i had a similar problem and ended up having to wrap the whole thing
https://gist.github.com/chandeeland/9817516
For the people only in need to zero-out microseconds (I had to because of database layer) here's the snippet I ended up using:
$format = "Y-m-d H:i:s e";
$now = (new \DateTime())->format($format);
$dateTime = \DateTime::createFromFormat($format, $now);
Note that using $format = 'c', ISO 8601, will not work, as explained here (https://stackoverflow.com/a/10478469/8119317).
I need to compare bentween a time taken from a database to the current time.
$DBtime = "2013-10-29 17:38:55";
this is the format of the arrays in the database.
How can I compare it with the current time?
Im not sure how, but maybe converting DBtime to Unixtime then:
(CurrentUnixTime - dbUnixTime) = x
Or maybe, we can take the 17:38 and compare it somehow with date("G:i");
Thank you! I hope you understand what I mean.
You can transform it into a UNIX timestamp using strtotime and then subtract the current timestamp by it.
$DBtime = "2013-10-29 17:38:55";
$db_timestamp = strtotime($DBtime);
$now = time();
$difference = $now - $db_timestamp;
echo $difference;
This will give you the difference in seconds.
You can convert the DBtime string to a unix timestamp in PHP using strtotime. In MySQL, you can use UNIX_TIMESTAMP when querying the column.
time() - strtotime($DBtime)
$date1 = new DateTime('2013-10-29 17:38:55');
$date2 = new DateTime('2013-11-29 18:28:21');
$diff = $date1->diff($date2);
echo $diff->format('%m month, %d days, %h hours, %i minutes');
$DBtime = "2013-10-29 17:38:55";
// Set whatever timezone was used to save the data originally
date_default_timezone_set('CST6CDT');
// Get the current date/time and format the same as your input date
$curdate=date("Y-m-d H:i:s", time());
if($DBtime == $curdate) {
// They match, do something
} else {
// They don't match
}