I m trying to calculate time from an array where time is stored in HH:mm:ss format, i m making time array from this code,
$result=[];
foreach ($playerTimes as $playerTime) {
$playerStartTime = (isset($playerTime->start_time))? $playerTime->start_time: '00:00:00';
$playerEndTime = (isset($playerTime->End_time))? $playerTime->End_time: '00:00:00';
$result[] = \Carbon\Carbon::parse($playerStartTime)->diff(\Carbon\Carbon::parse($playerEndTime))->format('%H:%I:%S');
}
and I get this array
array:3 [0 => "08:44:14" 1 => "10:46:16" 2 => "12:48:18"]
the result I m trying to achieve after the addition is 32:18:48
I have tried this, however the result I got is 08:18:48 which is not what i need,
$result[] = \Carbon\Carbon::parse($playerStartTime)->diffInSeconds(\Carbon\Carbon::parse($playerEndTime));
dd(gmdate("H:i:s", array_sum($result)));
The problem you are running into is that the H:i:s format does just not support what you are trying to achieve here, as H can never be greater than 23, nor smaller than 0.
There are two possible solutions: you can use Y-m-d H:i:s, to show the difference in years, months and days also, or you can use these values to convert them back to hours, or calculate the hours from the seconds difference (so seconds difference / 60 / 60 = hours), and work from there.
Related
I would like to know if a date is older than 1 day using Carbon.
I have tried:
$date = Carbon::parse($loggedUser->exchange_keys_last_time);
$now = Carbon::now();
var_dump($date);
var_dump($now);
dd($date->diffInDays($now));
$loggedUser->exchange_keys_last_time = 2018-04-04 00:00:00.000000 and $now = 2018-04-02 15:16:18.902924 and I'm getting this weird result saying that the diffInDays() = 1 which in my mind doesn't make sense since these dates are two days apart.
Any suggestion to get if $date is older than 1 day comparing to $now?
If you're not concerned about anything smaller than a second (it seems you're not), you can simply compare the difference in seconds against a known value (seconds in a day).
$secondsInDay = 86400; // 3600 * 24
$expired = $date->diffInSeconds($now) > $secondsInDay;
Do note that this probably won't work with DST change and you should look into other solutions if that's a concern for you.
I have a script that a user can setup a frequency as to when they want it to run.
They specify
The month they want it to run
The day of the month
The time (24 hour format)
They do not specify the year, the script needs to find the next closest date that matches.
PHP
The way I propigate the dates is through an array of months the user chooses and I can output all the dates into a nice array
$scheduler_months = unserialize($row['scheduler_months']);
foreach ($scheduler_months as $scheduler_month) {
$next_date[] = $scheduler_month."/".$row['scheduler_date']." ".$row['scheduler_time'];
}
which will out put
Array ( [0] => 2/28 12:00 [1] => 4/28 12:00 [2] => 12/28 12:00 )
So now at this point I need to figure out what the next closest date based on today as the starting point will be, obviously if the next closest date is in the next year it needs to be smart enough to figure that out. I just have no idea how to find the next closest date based on the dates in the array.
It's quite easy to figure out the year of the dates - if you were to convert them to unix time using strtotime you can determine if this year's date was in the past or not and if it were, you can assign that date next year.
$scheduler_months = unserialize($row['scheduler_months']);
$now = strtotime("now"); # get the unix time in seconds 'now'
foreach ($scheduler_months as $scheduler_month) {
# $tmp will be holding the date in the form of YYYY-MM-DD HH:MM
$tmp = date("Y")."-".$scheduler_month."-".$row['scheduler_date']." ".$row['scheduler_time'];
if(strtotime($tmp) - $now < 0) # if date is in the past, assign it to the next year
$tmp = (date("Y")+1)."-".$scheduler_month."-".$row['scheduler_date']." ".$row['scheduler_time'];
$next_date[] = $tmp;
}
# Initialize $smallest and $smallest_key
$smallest = strtotime($next_date[0])-$now;
$smallest_key = 0;
foreach($next_date as $key => $val) {
$time_diff = strtotime($val) - $now;
if($time_diff < $smallest) {
$smallest_key = $key;
$smallest = $time_diff;
}
}
In the first part, I've modified your foreach loop to determine the correct year based on unix time. I've changed the date format to YYYY-MM-DD HH:MM. If the date's unixtime is less than the current unix time, then the next closest date is next year.
In the second part I initilize two variables - $smallest, which holds the smallest time in seconds relative to now and $smallest_key, which holds the array key for the smallest time.
Then I loop over $next_date and I look for the smallest time in seconds from now to either of the dates.
I have a problem with my script and I dont understand where is the problem. So I have this code :
$i_now = strtotime(date('Y-m-d'));
$i_date_last_bonus = strtotime($o_member->date_last_bonus);
$i_datediff = round(abs($i_now - $i_date_last_bonus) / 86400);
print_r("Date Now :".date('Y-m-d'));
print_r("Last Win :".$o_member->date_last_bonus);
I get the $i_datediff = 1 and I dont understand why because in the print_r I have Date Now :2015-12-04 and Last Win:2015-12-03
Can you help me please where I make the error ? Thx in advance and sorry for my english
In one day there are 24 Hrs, in each hour there are 60Min, in each min there are 60sec. Hence, there are 24*60*60 = 86400sec in one day.
Now, The strtotime() function parses an English textual datetime into a Unix timestamp (the number of seconds since January 1 1970 00:00:00 GMT). Means it returns seconds.
so, i_now = 1449187200 andi_date_last_bonus = 1449100800
Difference is 86400sec.
Now $i_datediff = round(abs($i_now - $i_date_last_bonus) / 86400); this is converting seconds in days.
And Difference is 86400 / 86400 = 1
means 1 day.
This result is correct as you get the number of seconds between two dates first and then you divide it by the number of seconds in 24 hours (86400) which gives you 1 (day) as a result.
I have created an array with 10 timestamps each 1 day apart:
$data_points = array();
$now = time();
$one_day = 60 * 60 * 24;
for($i = 1; $i <= 10; ++$i) {
$key = $now - ($one_day * $i);
$data_points[$key] = 0;
}
print_r($data_points);
Array
(
[1328642414] => 0
[1328556014] => 0
[1328469614] => 0
[1328383214] => 0
[1328296814] => 0
[1328210414] => 0
[1328124014] => 0
[1328037614] => 0
[1327951214] => 0
[1327864814] => 0
)
Now I have a array of tasks that have started at various times in the last 10 days, I want to see which day my task fell into.
I was going to loop through each $data_point and see if the start time is greater than the current day and less than the next, then increment that data point
is there a better way to do this?
Thanks
Well, to reduce your search time you could put your data into a binary search tree rather than a simple array.
Whether or not that's worth the trouble depends on how big your data set is. Of course, you'd also have to re-balance your tree every so often as you add new dates.
I think there's a better method.
Assuming you have task starting timestamps in an array, the algorithm will be something like :
for each task starting timestamp
timestamp <- $now - timestamp // you will obtain task age in seconds
timestamp <- timestamp / (60*60*24) // you will obtain task age in days
// round resulting timestamp with a precision of 0 if you want to obtain the task age in integer days.
end for each
In this way you will loop on only one array. This will be less expensive than your method.
Obviously, if your tasks come from a SQL database, there will be a greater solution in SQL.
You can use DateTime class
$now = new DateTime();
$task = new DateTime('2012-02-20');
$interval = $taks->diff($now);
echo 'Here is the position you need:' . $interval->format('%R%a days');
** Updated to avoid use of DateTime as asked in comment **
$now = date('Ymd');
$task = date('Ymd',$tasktime);
$interval = $task - $now;
The interval is the number you expect.
I know this question is old, but since there are no accepted answers, and it seems like a fun question to answer - here we go!
Based on your question, your algorithm has the Big O of O(10n) where n is the number of tasks. This means, that it is fairly efficient compared to a lot of things. As pointed out, a binary search tree would be faster having O(log(n)), however implementing it wouldn't really be worth the saved time during processing. Though, you can make it slightly more efficient and have a resulting O(n) by using something like:
$now = time();
$oneDay = 86400; //60 * 60 * 24
foreach($tasks as $task) {
//assuming now that $task is the timestamp of the task
//extra paranthesis added for easier reading
$dif = $now - ($oneDay * ceil(($now - $task) / $oneDay));
$data_points[$dif]++;
}
The math in the diff is as follows. $now-$task is the difference between the two timestamps in seconds, we divide by $oneDay to get the number of days in the past the task occurred. Now, assuming that $now is the start of a new day, and if an event happened just 12 hours ago it was 'yesterday', we use ceil to round it to the next integer so '.5' becomes '1'. From there, we multiply by $oneDay to get the number of seconds of the days that have passed - to work with the $data_points array that you previously created. We then take that result and subtract it from $now, again to work with your $data_points array. That result gives us a time stamp that we can use that matches those in the array you created, and we use it as the 'key' for it and increment accordingly.
This will prevent you from having to loop through the entire $data_points array for each task, and thus reducing its complexity from O(10n) to O(n).
Anyways, I hope that answer helps explain why your formula isn't that inefficient, but shows how to make it ever so slightly more efficient.
I'm using PHP + mongoDB.
How can I get a time difference between two time values?
I have a real time value which is string
$realtime = "2010-01-01 12:00:00";
and another value which is unixstamp time,
$mongotime = new Mongodate(strtotime($realtime));
So I can use either a string time value or unix time stamp.
But I'm not sure the way to get time difference between two values.
Should I just subtract two $mongotime values and does it give me a time difference in seconds?
If you have 2 unix timestamps...
$date = $item['pubdate'];
(etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now - $result) / 60);
$min = round($unix_diff_min);
This will give number of mins between the 2 timestamps...