MySQL & PHP : Time() to Decimal Hour - php

I have in my MySQL database two Time() saves: start and end.
I would like to have a decimal result of the interval between my two times in my PHP code.
for exemple, if :
start = 15:00:00
end = 16:00:00
result = 1
and if
start = 15:30:00
end = 16:00:00
result = 0,5
Is it possible to get this result using MySQL? If it isn't possible, how could I convert a time format to decimal interval please?
Thanks a lot for reading my issue.

Very straightforward solution would be to take this two values, convert them to time and then make it to hours.
$start = "15:00:00";
$end = "16:00:00";
$result = (strtotime($end) - strtotime($start))/3600;
That gives you $result = 1
For values 15:30:00 and 16:00:00 $result will be 0.5.

Okay,
So I think it is easy. Just follow these steps:
You need to separate those numbers. Make 3 variables. For this example we'll use $hours, $minutes, $seconds (you can achieve these by separating the main time using REGEX. I recommend reading about how to do it first)
Now you have these numbers, for example like so:
$start = "15:30:00";
$start_hours = "15"
$start_minutes = "30"; //or just 0
$start_seconds = "00"; //or just 0
$end = "16:00:00";
$end_hours = "15"
$end_minutes = "00"; //or just 0
$end_seconds = "00"; //or just 0
So... this is briefly how you need to separate those numbers.
Now about the counting...
$result_hours = $end_hours - $start_hours //there you get 1
So hours are easy... For the minutes we need to think about time it self. Cause time values are always in 60 and we need "percents" which are in 100. We'll solve this doing:
$result_minutes = $end_minutes + $start_minutes; //you get 30.. which obviously is NOT what we want.. easily fixed by://
$right_minutes = 100 / 60 * $result_minutes; // gives you 50, which is great.
So far, we have 1,50 (If you'll take enough effort you can simply devide 50 by 10.. you'll get 5)
$result_seconds = $end_seconds + $start_seconds;
$right_seconds = 100 / 60 * $result_seconds;
Now we need to realize that we are dealing with seconds, so the number will be percentage of MINUTES not hours, we can fix this using:
$best_seconds = 100 / 60 * (0.$right_seconds) //now we have all right.
$right = $right_minutes + $best_seconds;
$result = $result_hours.",".$right;
.........................
And that should be it. Hope it will help you figure out the best solution, this is just how I thought it might work.
Try. Change. Try. And Done.
Good Luck

Related

Laravel Carbon - How to add minutes

I have a form where I ask 4 hours, It's morning start and end hour and the same for afternoon.
I'm using Carbon but it returns me 0 if I put 30 minutes, it rounds to down.
I try with diffInHours and diffInMinutes but it rounds always down in both ways.
This is my code example:
$startTime1 = Carbon::createFromFormat('H:s', '09:00');
$startTime2 = Carbon::createFromFormat('H:s', '10:30');
$startTime3 = Carbon::createFromFormat('H:s', '14:00');
$startTime4 = Carbon::createFromFormat('H:s', '16:00');
$morningTime = $startTime2->diffInHours($startTime1);
$afternoonTime = $startTime4->diffInHours($startTime3);
$total = $morningTime + $afternoonTime;
In $morningTime it returns 1 and should return 1,30.
In $afternoonTime it returns 2 and it's correct.
If I use with diffInMinutes it put 60 in $morningTime and 120 in $afternoonTime. It's wrong again in morning time.
How can I solve that?
Thank you
You are assigning seconds H:s in the Carbon format, use H:i:
$startTime1 = Carbon::createFromFormat('H:i', '10:30');
And You can use format() method to format the difference in time
$morningTime = $startTime2->diff($startTime1)->format('%H:%I');
Edit: there is no way to combine dateInterval instance, but you still can use timestamp:
$total_in_seconds = ($startTime2->timestamp - $startTime1->timestamp) + ($startTime4->timestamp - $startTime3->timestamp);
$total = Carbon::createFromTimestamp($total_in_seconds)->format('h:i');

Percentage Increase or Decrease Between timestamps

This supposed to be easier to solve or google the answer, but I just can't get it well done. May be I'm just stuck:
This is what I tried:
$now = time();
// i.e Improve police arriving time from 15 mins to 10 mins
$array_ini = explode(':',$ini_value); // "00:15:00" in my example (15 mins)
$array_desired = explode(':',$desired_value); // "00:10:00" in my example
$ini = $now-mktime($array_ini[0],$array_ini[1],$array_ini[2]);
$des = $now-mktime($array_desired[0],$array_desired[1],$array_desired[2]);
$percent = (1-$ini/$des)*100;
But all I get is .47% as improvement and my logic says that it really is a 33% improvement.
What am I doing wrong?
It's much easier to just deal with minutes:
$ini_mins = 15;
$desired_mins = 10;
$improvement_mins = $ini_mins - $desired_mins;
$percent = ($improvement_mins / $ini_mins) * 100;
print_r($percent);
It is indeed straight forward and easier to just deal with minutes, as Ryan said in his answer.
But to add to it, what you are doing wrong - you are deducting unix time of 01 Jan 1970 00:10:00 and 01 Jan 1970 00:15:00 from say unix time of 15 Sep 2015 19:00:00. Of course the percentage difference between these two numbers would be small. You are doing something like this
num1 = 100000 - 10
num2 = 100000 - 15
percentage num1/num2 is wrong way to find percentage diff between 10 and 15; and also it is going to be much smaller than 33%.
plus you have a code bug. The array is called $array_desired but you reference $array_des in mktime.
Ok. I guess that Amit opened my mind.
Based on his comment, I post the right answer:
// This line is not needed any more
//$now = time();
// i.e Improve police arriving time from 15 mins to 10 mins
$array_ini = explode(':',$ini_value); // "00:15:00" in my example (15 mins)
$array_desired = explode(':',$desired_value); // "00:10:00" in my example
// Time must to be based on Jan, 1 1970
// Hours are from 1 to 23, so must be increased by 1
$ini = mktime($array_ini[0]+1,$array_ini[1],$array_ini[2],1,1,1970);
$des = mktime($array_desired[0]+1,$array_desired[1],$array_desired[2],1,1,1970);
$percent = (1-$des/$ini)*100;

PHP // Converting/Calculating DATE

Im trying to solve this since two days without success...
First of all my code:
PHP-Version: 5.4
SCRIPT1:
query = "SELECT start, end FROM timetable WHERE ........";
$result = mysql_query($query, $db) or die(mysql_error());
$sqlarr = mysql_fetch_array($result, MYSQL_ASSOC);
$times = array($sqlarr['start'], $sqlarr['end']);
$calced = strtotime($times[1]) - strtotime($times[0]);
$total = date("H:i:s", $calced-3600); //<-- -3600 Fixed it
echo "<br>Total: ".$total;
The start and end times are in format 00:00:00. Everytime this script calculates it appends 1 hour to the result. So if im going for a result of 5 minutes i´ll get 01:00:05.
Why???
This one is even more strange.
SCRIPT2:
while($row = mysql_fetch_array($result, MYSQL_ASSOC)){
echo " | ".$row['total']."<br>";
$add += strtotime($row['total']);}
echo $add;
The first script calculates the total time from start to end. The second one should get the total-times out of the db and calculate the sum of all entries. For every entry the second script substracts 2 hours.
Example:
Database => Start = 12:32:00 End = 12:32:15
Script1 Result1 = 01:00:15 (Where is this extra hour coming from?) FIXED
Every Result1 is stored in the same table(db). Script2 is loading all this rows and handling them by a while-loop.
According to how many entries there are the script subtracts serval hours.
0 Entries => Total: 00:00:00
1 Entry => Total: 23:00:xx
2 Entries => Total: 20:00:xx
3 Entries => Total: 18:00:xx
4 Entries => Total: 16:00:xx
So, with 2 entries it continues subtracting 2 hours from every total-calculation which isnt correct, abviously.
Thanks to you guys. Using DateTime made this simple and bugfree!
I am not really sure of your case with using strtotime function, but I've tried this solution and it worked, if you have php > 5.2:
You can use the DateTime class and date_diff function to get the difference date, read more here: http://us3.php.net/manual/en/datetime.diff.php
Example:
// start date
$start = new DateTime("09:23:38");
// end date
$end = new DateTime("09:23:54");
// calculate difference
$calc = date_diff($start, $end);
// prints 00:00:16
echo $calc->format('%h:%i:%s');
According to this answer It seems like by default date starts from 1:00:00 so you could subtract your date by 3600 seconds (1 hour) like this:
$start = strtotime("11:23:38");
$end = strtotime("11:23:54");
$calc = $end - $start;
echo date('H:i:s', $calc - 3600);
The problem comes from :
echo date('H:i:s', $calc);
$start - $end gives you the expected value in seconds. It depends on what value date('H:i:s', 0) is. On my computer, it's not midnight on 1 jan. 1970 !
This link as example : http://sandbox.onlinephpfunctions.com/code/81e56cbce16f6dacfedd2cb376b946a540bce36d.
You might consider substracting date('H:i:s', 0) from your result to get correct value.
Or using DateTime as #Ben Beri suggested you to do as it is (I think) the best way to do.

Calculating different bands of overtime in php

This is my first time posting here so I'm sorry if I get something wrong. I'm trying to calculate how many hours overtime a worker has worked based on when they signed in. The problem is that we have different bands of overtime:
If the worker works between 5 and 7 then it's 25% extra per hour
If they worked between 7pm and 10pm then its 50% extran for each hour
If the worker works between 10 and 12 then it's 75% extra
If the worker works between 12am and 7am is 100% more
I need to count how many hours they worked at each of the overtime bands
$number_of_25_percent_hours=0;
$number_of_50_percent_hours=0;
$number_of_75_percent_hours=0;
$number_of_100_percent_hours=0;
$clockInTime=$arr['4'];
$clockOutTime=$arr['5'];
$startingPieces=explode(':',$clockInTime);
$startingHour=$startingPieces[0];
$finishingPieces=explode(':',$clockInTime);
$finishingHour=$finishingPieces[0];
//Regular hours are between 7am and and 5pm
//If the worker works between 5 and 7 then it's 25% extra per hour
if(($startingHour<=5)&&($finishingHour>=6)){$number_of_25_percent_hours++;}
if(($startingHour<=6)&&($finishingHour>=7)){$number_of_25_percent_hours++;}
The problem with using the lines above is that it does not work if for example they worked an hour from 6:30 to 7:30.
I'm interested in finding other ways to do this.
you need to store the data more exactly. From your script it looks as if you were only saving the starting hour - which propably is a full number (1,2,3,4 whatsoever)
You script however needs a exact time representation. There are surely many ways to do this but for the sake of a better Script (and as you will propably be able to use some of these more exact values later on) I'd recommend you to store it as a UNIX Timestamp, then get the hour of the Timestamp :
$startingHour = date('H' $timeStampStored)
and check if it's in any of your "bonus" segments. If the user started working at 6:30, the value will hold 6.
This code is completely off the top of my head, untested etc. It's intended as a suggestion of one method you might use to solve the problem, not as a robust example of working code. It uses integers instead of dates, relies on array data being entered in order etc, and probably wouldn't even run.
The basic idea is to set up the scales for each level of overtime multiplier, as well as the hours for non-overtime pay in an array, then loop through that array checking how many hours of each level of overtime have been worked between the inputted times, meanwhile keeping track of a total billable hours value.
$PayMultipliers = array();
$PayMultipliers[0] = array(17,19,1.25);
$PayMultipliers[1] = array(19,22,1.5);
$PayMultipliers[2] = array(22,24,1.75);
$PayMultipliers[3] = array(0,7,1.5);
$PayMultipliers[4] = array(7, 17, 1);
$Start = 3;
$End = 11;
$TotalHours = 0;
for($i = 0; $i <= count($PayMultipliers); $i++)
{
if($Start > $PayMultipliers[$i][0] && $Start < $PayMultipliers[$i][1])
{
$TotalHours += ($PayMultipliers[$i][1] - $Start) * $PayMultipliers[$i][2];
$Start = $PayMultipliers[$i][1];
}
}
echo $TotalHours;
If you want to calculate from 6:30 to 7:30 you'll have to caclulate in minutes, not hours. You can convert the hours and minutes to timestamps, check each time period, and then convert the seconds back to hours.
<?php
$number_of_overtime_hours = array();
$clockInTime = "18:30:00";
$clockOutTime = "19:30:00";
$startingPieces = explode(':',$clockInTime);
$finishingPieces = explode(':',$clockOutTime);
//Timestamps
$startTimestamp = mktime($startingPieces[0],$startingPieces[1],$startingPieces[2]);
$finishTimestamp = mktime($finishingPieces[0],$finishingPieces[1],$finishingPieces[2]);
//finish after 0h
if ($finishTimestamp < $startTimestamp){
$finishTimestamp += 3600 * 24;
}
//set starting and ending points
$overtimePeriods = array(
25 => array (17,19),
50 => array (19,22),
75 => array (22,24),
100 => array (24,31)
);
$overtimeWork = array();
foreach ($overtimePeriods as $key => $val){
//create Timestamps for overtime periods
$beginTimestamp = mktime($val[0],0,0);
$endTimestamp = mktime($val[1],0,0);
//calculate hours inside the given period
$overtimeWork[$key] = (min($finishTimestamp,$endTimestamp) - max($startTimestamp,$beginTimestamp)) / 3600;
//negative values mean zero work in this period
if ($overtimeWork[$key] < 0) $overtimeWork[$key] = 0;
}
var_dump($overtimeWork);

Multiple hour by a number

I have something like that for example: 01:06:22 this represents 1hour, 6minutes and 22seconds. I want to take that, and multiple it by 6 and add it to some other hour such as 04:23 which is 4AM and 23Minutes not 4hours and 23 minutes.
Basically, as a result I expect that:
01:06:22
* 6 = 6hours 38minutes canceling the remaining seconds which are 12 in this case
Now, I want to take that and append it to other hour, 04:23 in this case, so the result would be:
11:01.
I have no clue how to start and do it, unfortunately.
Any help is appriciated!
Clarifications
The time that I have to multiple by 6 will never exceed 2 hours.
All the times are in the same format.
With DateTime it is simple:
$time = '01:06:22';
$dateSeconds = new DateTime("1970-01-01 $time UTC");
$seconds = $dateSeconds->getTimestamp() * 6;
$interval = new DateInterval('PT'.$seconds.'S');
$date = new DateTime('1970-01-01 04:23:00 UTC');
$date->add($interval);
echo $date->format('H:i:s');
Other solution with strtotime and gmdate. (Similar to Suresh but working):
$date = strtotime('1970-01-01 01:06:22 UTC');
$add = strtotime('1970-01-01 04:23:00 UTC');
$date = (($date*6)+$add);
echo gmdate('H:i:s', $date);
This is a solution if you want to implement it yourself.
The thing about timecode is that it can become really heavy with the if the if conditions etc if you don't do it right.
The best Way I thought of to deal with this is to convert everything to second.
so 01:06:22 would become:
numberOfSecond = 22 + 06 * 60 + 01 * 60 * 60
How to get the 22, 06 etc from the String? You can use Regex.
What you will need:
a function to extract the different values (hours, minute, second)
a function to convert the timecode into second
a function to convert back into timecode
the functions to multiply, add etc...
You might want to create a class for it.
You can try like this:
$date = strtotime('01:06:22');
$add = strtotime('00:04:23');
$date = ($date*6)+$add;
echo date('H:i:s', $date);
Note: Code is not tested.
First of all you want to multiply a time span by a factor. The easiest way to do this is to convert the span to seconds and do a straight multiply:
$date =DateTime::createFromFormat('!H:i:s', '01:06:22', new DateTimeZone('UTC'));
$seconds = $date->getTimestamp();
This code works by pretending that the time is a moment during the Unix epoch start so that it can then get the number of seconds elapsed since the epoch (the timestamp). That number is equal to the duration of the time span in seconds. However, it is vitally important that the input is interpreted as UTC time and not as something in your local time zone.
An equivalent way of doing things (as long as the input is in the correct format) which is lower-tech but perhaps less prone to bugs would be
list($h, $m, $s) = explode(':', '01:06:22');
$seconds = $h * 3600 + $m * 60 + $s;
Now the multiplication:
$seconds = $seconds * 6;
If you want to only keep whole minutes from the time you can do so at this stage:
$seconds = $seconds - $seconds % 60;
The final step of adding the result to a given "time" is not clearly specified yet -- does the reference time contain date information? What happens if adding to it goes over 24 hours?
Self explanatory :
$initialTime = '01:06:22';
$timeToAdd = '04:23';
$initialTimeExploded = explode( ':' ,$initialTime );
$initialTimeInMintues = ( $initialTimeExploded[0] * 60 ) + $initialTimeExploded[1];
$initialTimeInMintuesMultipliedBySix = $initialTimeInMintues * 6;
$timeToAddExploded = explode( ':' ,$timeToAdd );
$timeToAddExplodedInMintues = ( $timeToAddExploded[0] * 60 ) + $timeToAddExploded[1];
$newTimeInMinutes = $initialTimeInMintuesMultipliedBySix + $timeToAddExplodedInMintues;
$newTime = floor( $newTimeInMinutes / 60 ) .':' .($newTimeInMinutes % 60);
echo $newTime;
Result :
10:59

Categories