Why I can't successfully subtract two datetime values in php? - php

I have the following code:
echo "first row " . $firstRow["begin_date"];
echo " super beg " . $superbegintime;
echo " duration " . $duration;
if(($firstRow["begin_date"] - $superbegintime) >= $duration)
{
echo "it works!";
}
$firstRow["begin_date"] is a DATETIME type field taken from database
$superbegintime is created as follows:
$date = new DateTime();
$superbegintime= $date->add(DateInterval::createFromDateString('10 minutes'))->format('Y-m-d H:i:s');
and $duration is a field $duration = 15; that should represent number of seconds.
I cannot enter the if statement and print the it works! message, what am I doing wrong here?

You are comparing and doing math with strings which can be problematic and not get you the right results especially when you compare them to integers (and don't specify what that number actually means). DateTime objects allow you to do the math and then compare the difference with the duration. The difference and the duration are both DateInterval objects which are comparable.
$beginDate = new DateTime($firstRow["begin_date"]);
$superbegintime = new DateTime($superbegintime);
$duration = DateInterval::createFromDateString('15 seconds');
$diff = $beginDate->diff($superbegintime);
if($diff >= $duration)
{
echo "it works!";
}
Demo

Related

NTUSER.dat - No of 100 ns intervals since 1.1.1601 UTC+0 using PHP

I am parsing UserAssist files from Windows registry NTUSER.dat. From the registry I get a field named "Last Executed" which has the explanation "Number of 100 ns intervals since 1.1.1601 UTC+0".
My decimal number is 131955686641390000, and I have to make this to a human readable format. I want to do this by using PHP.
I have figured out that there is a function called add(new DateInterval('XXXX')); that I think I can use, but I need some help to figure out what should be the input to the function. The manual is here; https://www.php.net/manual/en/class.dateinterval.php
This is my code:
$nanoseconds = "131955686641390000";
$date = new DateTime('1601-01-01');
for($i=0;$i<100;$i++) {
$date->add(new DateInterval('P1s'));
}
$date_print = $date->format('Y-m-d H:i:s');
echo"
<p><b>Date:</b> $date_print</p>
";
I tried this but it failed:
$nanoseconds = "131955686641390000";
$seconds = $nanoseconds/1000000000;
$add = "PT" . $seconds . "S";
$date = new DateTime('1601-01-01');
for($i=0;$i<100;$i++) {
$date->add(new DateInterval($add));
}
$date_print = $date->format('Y-m-d H:i:s');
echo"
<p><b>Date:</b> $date_print</p>
";
Fatal error: Uncaught Exception: DateInterval::__construct(): Unknown
or bad format (PT131955686.64139S) in
C:\Users\user\wamp64\www\x.php:257
DateInterval->__construct('PT131955686.641...') #1 {main} thrown in
Unix epoch time is the number of seconds since Jan 1st, 1970. It consists of ten digits.
Your number is in hundreds of nano seconds, so that would work out as 11 digits.
So you can strip off everything after the first 11 digits, and pass that into a DateTime starting in 1601, like so:
<?php
$nano = '131955686641390000';
$seconds = substr($nano, 0, 11);
$date = new DateTime('1601-01-01');
$date->modify('+' . $seconds . ' seconds');
echo $date->format('Y-m-d H:i:s');
Which gives 2019-02-25 11:44:24.
You can see this here https://3v4l.org/fYpSJ
Alternatively, you can subtract the number of seconds being the difference from Jan 1st 1970, to get the same result.
<?php
$nano = '131955686641390000';
$seconds = ((int) substr($nano, 0, 11)) -11644474772;
$date = new DateTime('#' . $seconds);
echo $date->format('Y-m-d H:i:s');
That's a little shorter and cleaner in my opinion. Looks like -11644474772 is a useful number to remember!

Milliseconds compare in php

$date1 = "2017-04-13 09:09:80:300"
$date2 = "2017-04-13 09:09:80:400"
how can I check if the date2 is more or less 100 milliseconds then $date 1 in and false if not (101 - more or less)
Your question, while deceptively appearing simple, is actually fairly ugly, because it is the case that PHP's strtotime() function truncates milliseconds from a timestamp. Actually, it won't even correctly process the timestamps $date1 and $date2 which you have in your question. One workaround is to trim off the millisecond portion of the timestamp, use strtotime() to get milliseconds since the epoch, then use a regex to obtain and add the millisecond portion to this amount.
$date1 = "2017-04-13 09:09:40:300";
$date2 = "2017-04-13 09:09:40:400";
preg_match('/^.+:(\d+)$/i', $date1, $matches);
$millis1 = $matches[1];
$ts1 = strtotime(substr($date1, 0, 18))*1000 + $millis1;
preg_match('/^.+:(\d+)$/i', $date2, $matches);
$millis2 = $matches[1];
$ts2 = strtotime(substr($date2, 0, 18))*1000 + $millis2;
if (abs($ts1 - $ts2) < 100) {
echo "within 100 millseconds";
}
else {
echo "not within 100 millseconds";
}
Demo here:
Rextester
If you get your time in such format (I changed 09:09:80 to 09:09:40 as it was incorrect format)
$date1 = "2017-04-13 09:09:40:300"
$date2 = "2017-04-13 09:09:40:400"
create custom function since strtotime doesn't support ms
function myDateToMs($str) {
list($ms, $date) = array_map('strrev', explode(":", strrev($str), 2));
$ts = strtotime($date);
if ($ts === false) {
throw new \InvalidArgumentException("Wrong date format");
}
return $ts * 1000 + $ms;
}
now just check does difference is less than 100
$lessOrEqual100 = abs(myDateToMs($date1) - myDateToMs($date2)) <= 100;
According to the php manual for strtotime fractions of a second are allowed, although currently ignored by the strtotime function.
This means you could express your dates like this 2017-04-13 09:00:20.100 to have them parsed by strtotime without error (keeping them futureproofed) and then use a custom function to compare just the millisecond portion of the dates if the timestamps are the same
The below function will return true if the dates are within 100 milliseconds, false otherwise. You can pass in the amount to compare them by as an argument.
<?php
date_default_timezone_set ( "UTC" );
$date1 = "2017-04-13 09:00:20.100";
$date2 = "2017-04-13 09:00:20.300";
// pass date1, date2 and the amount to compare them by
$res = compareMilliseconds($date1,$date2,100);
var_dump($res);
function compareMilliseconds($date1,$date2,$compare_amount){
if(strtotime($date1) == strtotime($date2)){
list($throw,$milliseond1) = explode('.',$date1);
list($throw,$milliseond2) = explode('.',$date2);
return ( ($milliseond2 - $milliseond1) < $compare_amount);
}
}
?>
PHP 7.1 lets you do it with DateTime objects...
Be sure to test all other answers with a change of day as a true indicator of a successful process.
Demo
Code:
$dt1 = DateTime::createFromFormat('Y-m-d H:i:s:u e', "2017-04-14 0:00:00:000 UTC");
$dt2 = DateTime::createFromFormat('Y-m-d H:i:s:u e', "2017-04-13 23:59:59:999 UTC");
var_export($dt1->format('Y-m-d H:i:s:u'));
echo "\n";
var_export($dt2->format('Y-m-d H:i:s:u'));
echo "\n";
//var_export($dt1->diff($dt2));
echo "\n";
$diff=$dt1->diff($dt2);
// cast $diff as an array so array_intersect_assoc() can be used
if(sizeof(array_intersect_assoc(['y'=>0,'m'=>0,'d'=>0,'h'=>0,'i'=>0],(array)$diff))==5){
// years, months, days, hours, and minutes are all 0
var_export($micro=round(abs($diff->s+$diff->f),3));
// combine seconds with microseconds then test
echo "\n";
if($micro>.1){
echo "larger than .1";
}else{
echo "less than or equal to .1";
}
}else{
echo "too large by units larger than seconds";
}
Outputs:
'2017-04-14 00:00:00:000000'
'2017-04-13 23:59:59:999000'
0.001
less than or equal to .1

Check if 1 timestamp is later then current timestamp

I have a script that counts delivery time... so... timestamp of the orderdate - current timestamp shows a time...
this all works fine. But sometimes there are orderd where the client can set a time or date in the future..
so for those orders i dont want to show the counter but what to do something like this (all timestamps are 0000-00-00 00:00:00)
$time1 = date($orderItem->elapsed_time); //now
$time2 = date($orderItem->orderdate);
if ($orderItem->later_order_date LATER THEN $time1) {
$elapsed = "not started"
}
else {
$elapsed = $elapsedTime->getElapsedTimeOld($time1,$time2);
}
What is the best way to do this ?
DateTime() objects are comparible which makes this easy:
$time1 = new DateTime(); // No need to pass it anything to represent now
$time2 = new DateTimedate($orderItem->orderdate);
if ($time2 > $time1) {
$elapsed = "not started"
}
else {
$elapsed = $elapsedTime->getElapsedTimeOld($time1,$time2);
}
You can use the the strtotime() function which will convert your formatted date from YYYY-mm-dd HH:ii:ss to a unix timestamp, which is just a number you can compare with regular comparison operators:
if (strtotime($orderItem->later_order_date) > strtotime($time1)) {
$elapsed = 'not started';
}

Start Date and Start Time Less than End Date and End Time Validation

Start Time, End Date and End Time variables.
The Date Variables are formatted yyyy-mm-dd
The Time Variables are formatted hh-mm (however only on hour numbers are usable, e.g Minutes is always 00)
I can insert these variables into my database no problem, however before I do I want to check that the start date and time is before the end date and time. I know how to check if the time is earlier, and the date is earlier, but I cannot check the time and date together and I would appreciate any help?
$_POST['start_time']
$_POST['end_time']
$_POST['start_date']
$_POST['end_date']
are the variables and how I am grabbing them.
Use DateTime objects to make life simple for yourself:
<?php
// assuming the following values...
$_POST['start_time'] = '06:00';
$_POST['end_time'] = '10:00';
$_POST['start_date'] = '2012-01-01';
$_POST['end_date'] = '2013-06-02';
//set up two DateTime objects
$start = DateTime::createFromFormat('Y-m-d H-i', $_POST['start_date'] . ' ' . $_POST['start_time']);
$end = DateTime::createFromFormat('Y-m-d H-i', $_POST['end_date'] . ' ' . $_POST['end_time']);
// check if they're valid
if ($start < $end) {
echo 'We are good...';
} else {
echo 'Something bad happened...';
}
Bear in mind that this assumes that your $_POSTed values are valid. If you haven't sanitized them already, wrap it in a try/catch at least.
function getTime ($ymd, $hi) {
return strtotime($ymd." ".$hi);
}
if (getTime($_POST['start_date'], $_POST['start_time']) < getTime($_POST['end_date'], $_POST['end_time'])) {
echo "Ok!";
}
Simply convert it to an Unix-timestamp and then compare.
I would use DateTime::createFromFormat() for it. Like this:
$start = DateTime::createFromFormat('Y-m-d H-i',
$_POST['start_date'] . ' ' . $_POST['start_time']);
Try exploding the arrays and then using mktime() function to pass the date to seconds. Then, just compare both dates, the bigger in seconds is the later.
list($strHour, $strMin) = explode('-', $_POST['start_time']);
list($endHour, $endMin) = explode('-', $_POST['end_time']);
list($strYear, $strMonth, $strDay) = explode('-', $_POST['start_date']);
list($endYear, $endMonth, $endDay) = explode('-', $_POST['end_date']);
$startSeconds = mktime($strHour, $strMin, 0, $strMonth, $strDay, $strYear);
$endSeconds = mktime($endHour, $endMin, 0, $endMonth, $endDay, $endYear);
if ($startSeconds > $endSeconds) {
echo 'Start is bigger';
}

How to compare two time in PHP

I had two times in the format like 7:30:00 and 22:30:00 stored in the variables $resttimefrom and $resttimeto respectively.
I want to check whether the current time is between these two values. I am checking this with the code
$time = date("G:i:s");
if ($time > $resttimefrom and $time < $resttimeto ){
$stat = "open";
} else {
$stat = "close";
}
But I am always getting the $stat as Close. What may cause that?
you can try using strtotime
$st_time = strtotime($resttimefrom);
$end_time = strtotime($resttimeto);
$cur_time = strtotime(now);
then check
if($st_time < $cur_time && $end_time > $cur_time)
{
echo "WE ARE CLOSE NOW !!";
}
else{
echo "WE ARE OPEN NOW !!";
}
i hope this may help you..
A simple yet smart way to do this is to remove the ':' from your dates.
$resttimefrom = 73000;
$resttimeto = 223000;
$currentTime = (int) date('Gis');
if ($currentTime > $resttimefrom && $currentTime < $resttimeto )
{
$stat="open";
}
else
{
$stat="close";
}
$today = date("m-d-y ");
$now = date("m-d-y G:i:s");
if (strtotime($today . $resttimefrom) < $now && $now > strtotime($today . $resttimeto)) {
$stat = 'open';
else
$stat = 'close
Try reformatting them into something that you can compare like that. For example, numbers:
$resttimefrom = mktime(7,30,0);
$resttimeto = mktime(22,30,0);
$time = mktime(date('H'),date('i'),date('s'));
You are comparing strings.
Convert the Time Strings to timestamps with strtotime().
Then compare against time().
Just convert your dates to a Unix Timestamp, compare them, you have your results! It might look something like this:
$time =date("G:i:s");
$time1 = strtotime($time);
$resttimefrom1 = strtotime($resttimefrom );
$resttimeto1 = strtotime($resttimeto );
if ($time1 >$resttimefrom and $time1 <$resttimeto)
{
$stat="open";
}
else
{
$stat="close";
}
The date function returns a string, so the comparison you're making would be a string comparison - so 7:30 would be more than 22:30
It would be much better to use mktime, which will return a Unix timestamp value (integer) so it would make for a better comparison
$currentTime = mktime();
$resttimefrom = mktime(hour,min,second);
http://php.net/mktime
The trick to manipulating and comparing dates and times in PHP is to store date/time values in an integer variable and to use the mktime(), date() and strtotime() functions. The integer repesentation of a date/time is the number of seconds since midnight, 1970-Jan-1, which is referred to as the 'epoch'. Once your date/time is in integer form you'll be able to efficiently compare it to other dates that are also in integer form.
Of course since you'll most likely be receiving date/time values from page requests and database select queries you'll need to convert your date/time string into an integer before you can do any comparison or arithmetic.
Assuming you are sure that the $resttimefrom and $resttimeto variables contain properly formatted time you can use the strtotime() function to convert your string time into an integer. strtotime() takes a string that is formatted as a date and converts it to the number of seconds since epoch.
$time_from = strtotime($resttimefrom);
$time_to = strtotime($resttimeto);
Side note: strtotime() always returns a full date in integer form. If your string doesn't have a date, only a time, strtotime() return today's date along with the time you gave in the string. This is not important to you, though, because the two dates returned by strtotime() will have the same date and comparing the two variables will have the desired effect of comparing the two times as the dates cancel each other out.
When you compare the two integers keep in mind that the earlier the date/time is, the smaller its integer value will be. So if you want to see if $time_from is earlier than $time_to, you would have this:
if ($time_from < $time_to)
{
// $time_from is ealier than $time_to
}
Now to compare a date/time with the current system date/time, just use mktime() with no parameters to represent the current date/time:
if ($time_from < mktime())
{
// $time_from is in the past
}
$firstTime = '1:07';
$secondTime = '3:01';
list($firstMinutes, $firstSeconds) = explode(':', $firstTime);
list($secondMinutes, $secondSeconds) = explode(':', $secondTime);
$firstSeconds += ($firstMinutes * 60);
$secondSeconds += ($secondMinutes * 60);
$difference = $secondSeconds - $firstSeconds;
$Time1 = date_parse($time);
$seconds1 = $Time1['hour'] * 3600 + $Time1['minute'] * 60 + $Time1['second'];
$Time2 = date_parse($current_time);
$seconds2 = Time2['hour'] * 3600 + Time2['minute'] * 60 + Time2['second'];
$actula_time = $seconds1 - $seconds2;
echo floor($actula_time / 3600) .":". floor(($actula_time / 60)%60) .":". $actula_time%60;
As Col. Shrapnel Said i am doing by converting all the time in to seconds and then compare it with current time's total seconds

Categories