Find how much time exists within two unix timestamps - php

I need to find how many seconds exist between two different unix timestamps within a certain range.
For example:
Travel Start: 05:00
Site Arrival: 07:00
Standby Hours: 06:00 - 09:00
I need to find how many seconds the user is traveling and how many seconds he spends on standby.
The above result should output:
Travel = 3600 seconds (05:00 - 06:00)
Standby = 3600 seconds (06:00 - 07:00)
Another example:
Travel Start: 10:00
Site Arrival: 11:30
Standby Hours: 06:00 - 09:00
Travel = 5400 seconds (10:00 - 11:30)
Standby = 0 seconds
Example code which I do not think is correct:
if($travel_start_time >= $standby_start_time)
{
if($first_site_arrival <= $standby_end_time)
{
$travel_during_standby = max($first_site_arrival-$travel_start_time, 0);
}
elseif($first_site_arrival >= $standby_end_time)
{
$travel_during_standby = max($first_site_arrival-$standby_end_time, 0);
}
}
else
{
$travel_during_standby = max($first_site_arrival-$standby_start_time, 0);
}

I think you're asking 'How much time is common to two possibly overlapping Unix timestamp ranges ?'
From a 'Logic' point of view...
Given that your times are already converted into Unix timestamps, as T1 and T2 for travel, and S1 and S2 for standby.
Travel time is T2-T1
Standby time is S2-S1
There will be an overlap if ((S1<T2) && (S2>T1))
If there's an overlap,then the travel during standby will be (Min(T2,S2) - Max(T1,S1))
Translating the logic into PHP is fairly straightforward...
$travel_during_standby = ((($standby_start_time < $travel_end_time)&&($standby_end_time > $travel_start_time)))? (Min($travel_end_time,$standby_end_time) - Max($travel_start_time,$standby_start_time)) : 0;
An alternative blunter approach would be to blindly calculate the overlap and ignore any negative results...
$travel_during_standby = Max( (Min($travel_end_time,$standby_end_time) - Max($travel_start_time,$standby_start_time)) , 0 );

Related

Calculate nearest hours to 00:00 in PHP

How can I calculate the nearest hours to midnight time 00:00 regardless of date in PHP. For example:
If time is 22:00 then 2 hours are required to reach 00:00
If time is 04:00 then -4 hours are the nearest to reach 00:00
Currently I have the following PHP function:
<?php
$ts1 = strtotime('00:00');
$ts2 = strtotime('04:00');
$diff = ($ts1 - $ts2) / 3600;
?>
But this won't be helpful much in the above.
If you have the php Datetime class available you can calculate the difference between two DateTimes.
$time1 = new \DateTime('00:00');
$time2 = new \DateTime('04:00');
$diff = $time1->diff($time2, true);
$hourDifference = 0;
if ($diff->h < 12) {
$hourDifference = -$diff->h;
} elseif ($diff->h > 12) {
$hourDifference = 24 - $diff->h;
} else {
$hourDifference = 12; // kann be positive or negative
}
And you'll get a DateInverall object where you can access, hours, minuts, seconds and compare them with normal php operators.
If you'r not too interested in minutes;
1. Extract minutes.
check if minutes is > or <=30
if greater, 'store' 1
2. Extract hour
check if hour is greater than 12
if not, add 12 (store flag also to say it will be minus)
3. if greater (ref. Step 1), add 1 to extracted hour.
4. 24 - extracted hour is your interval.
Please note, this may be reduced/ simplified greatly.
Your interval (should) be correct to the nearest half hour
The answer depends on the date (not only the time). This is because of daylight saving time changes. For example might 02:59 being closer to 00:00 then 21:01 on the time where daylight saving time will set back hour.

Populate Drop Down with Time using Time Range from Database

I am trying to populate a drop-down menu with time in 30 minute intervals (ability to change to different intervals would be nice too).
I am currently using the following code to populate the drop down (Scrounged this up online from searching around).
$sqlHours = "SELECT Open, Close FROM TimeTable";
$rsSQLHours = odbc_exec($conn, $sqlHours);
$strOpen = trim(odbc_result($rsSQLHours, "Open"));
$strClose = trim(odbc_result($rsSQLHours, "Close"));
$DeliHourOpen = substr($strOpen, 0, 2);
$DeliMinOpen = substr($strOpen, 3, 2);
$DeliHourClose = substr($strClose, 0, 2);
$DeliMinClose = substr($strClose, 3, 2);
for($hours=$DeliHourOpen; $hours<=$DeliHourClose; $hours++)
for($mins=$DeliMinOpen; $mins<60; $mins+=30)
echo '<option value='.$hours.':'.$mins.'>'.date('h:i A', strtotime($hours.':'.$mins)).'</option>'; ?>
Edit: I am storing the times in the database in 24h format, such as 08:00:00 or 22:00:00. I am using the date() just to format the displayed output in an AM/PM fashion for ease of use by users.
I am having issues when the Close Time is 20:00 it will go up to 8:30 PM in the drop-down. If I remove the = from <=$DeliHourClose then it will only display 7:30 PM. I need it to Display up to whatever the Close Time is.
The fields in the database are 'Time' in the in format 'H:i:s'.
Also, although the drop-down can be populated with a range of times from Open to Close, I need it to start at whatever the current time is + 30 minutes.
So if the Open Time is 8:00 AM, and it is 7:00 AM I want to see 8:00 AM as the first time in the drop-down. But if it is 9:00 AM, the first option in the drop-down needs to be 9:30 AM.
I have the general idea that it needs some sort of if/else to compare current time to the times in the drop-down, but I am not sure how to go about it, with the format I am using now for the drop-down.
I would prefer to have a more manageable format if possible.
Is there an easier/better way to generate a range of times with intervals that may be changed? And then populate the drop-down with the appropriate times?
Any help or suggestions would be greatly appreciated.
Using a Microsoft SQL Database.
Edit: There are multiple locations that will be stored in the table. I will add a WHERE Location = XXX clause once I get it working and add more locations to the table. Currently there is only one location, so no WHERE clause.
I am using time datatype instead of datetime as I do not want a y/m/d attached to the open/close times.
You need to generate your time stamp using time() so you can get the unix timestamp and then convert it as you wish, this way you'll be able to do time addition and add seconds straight to the given unix timestamp.
Ressource : http://fr.php.net/time
Edit : Just so we're clear and to explain it further : UNIX timestamp is the number of seconds since the 1st of january 1970, so echo time(); will return 1390934768, you just need to process it from there as the docs shows.
This code whille return this as an array : 8
8.5
9
9.5
10
10.5
11
11.5
12
12.5
13
13.5
14
14.5
15
15.5
16
16.5
17
17.5
18
18.5
19
<?php
//Function returning unix time from simple time stamp (8 or 17.5 or whatever)
function ttounix($t) {
$tunix = $t * 60 * 60;
return $tunix;
}
//Function returning simple timestamp from unix timestamp
function unixtot($u) {
$tt = $u / 60 / 60;
return $tt;
}
$gap = 30 * 60; //gap in seconds
$t1 = 8; //opening time from db
$t2 = 19; //closing time from db
//setting vars
$n = 0;
$count = array();
//Getting processed time stamps into vars
$o = ttounix($t1);
$c = ttounix($t2);
//Populating the array
while ( $o <= $c ) {
$count[$n] = $o;
$o += $gap;
$n++;
}
//Output
foreach ($count as $output) {
echo unixtot(intval($output)) . '<br />';
}
?>

Extract time frames from time period

I am creating an application that charges a client based on time usage of a service. The problem is that the services can have double charge for a pre-specified time period of the day.
So let's say we have a service for printing documents and the charge for using the printer is 5€ per hour and 10€ between 23:00 and 02:00 in the morning. Also a client can rent the printer for as much time as he likes. This can be from 1 minute to months or even years.
Now the specific problem:
Let's say a client comes in my office to rent the printer for 55 hours. Also the rent starts at 20:00 at night.
So the charge must be for 43 hours in single charge and for 12 hours in double charge. Here are two example images:
Now, let me give you some extra info about the hours. In programming, each hour has a timestamp that it is time passed from January 1, 1970 00:00:00 to the time in seconds.
So the date July 05 2012 11:15:40 has the timestamp 1373022940 and the date July 05 2012 11:15:50 has the timestamp 1373022950
In the above example lets say that the first example placed in the date May 1, 2013, so the timestamp for 23:00 will be 1367449200 and the time stamp for three days later at the 02:00 the morning is 1367546400
Now the question:
Is there a way to extract the time duration of the double charged hours from a time frame? If so, what is the process?
Of course there is. You just need to count the interval between dates.
Let's say someone started using service since 8:00 and ended in 16:00.
Price from 8:00 - 16:00 = 2$
Price from 16:00 - 8:00 = 1$
So you need to convert the start of usage time and end of usage time to timestamp
date_default_timezone_set('UTC');
$day_start = '2011-06-22';
$day_end = '2011-06-22';
$start_usage = strtotime($day_start.' 8:00');
$end_usage = strtotime($day_end.' 17:00');
$price_low_rate = 1; //price for using service 16-8
$price_high_rate = 2; // price for using service since 8-16
$fee_for_eight_sixteen = 0; // total price for using service since 8-16
$fee_for_sixteen_eight = 0; // total price for using service 16-8
if($end_usage >strtotime($day_start.' 16:01'))
{
$fee_for_sixteen_eight = ($end_usage - strtotime($day_end.' 16:00'))/3600 * $price_low_rate;
}
if($start_usage >= strtotime($day_start.' 8:00'))
{
$fee_for_eight_sixteen = (strtotime($day_end.' 16:00') - $start_usage)/3600 * $price_high_rate;
}
echo $fee_for_eight_sixteen.' - '.$fee_for_sixteen_eight;
I've tested it and it works. Hope it helps.
Haven't tested this, but I hope it gets you on the right track:
<?php
$price = 0;
$start_timestamp = 1367449200;
$end_timestamp = 1367546400;
$start_time_of_day = 1367449200 % (24*60*60); // Number of seconds from start of the day
$end_time_of_day = 1367546400 % (24*60*60); // Number of seconds from start of the day
// How much time the time period spends in the first day (in seconds)
$first_day_time = (24*60*60) - $start_time_of_day;
// How much time the time period spends in the last day (in seconds)
$last_day_time = (24*60*60) - $end_time_of_day;
$full_days_time = $end_timestamp + $last_day_time - ($start_timestamp + $first_day_time);
$full_days = round($full_days_time/(24*60*60));
// You can calculate by hand how much one full 24-hour day from 00:00 to 00:00 costs
$price += $full_days * (2*10 + 21*5 + 1*10);
// so now the difficulty is the pieces of time on the first day and the last day.
$expensive_time = 0; // Expensive time spent on the first and last day
$cheap_time = 0;
if ($start_time_of_day<2*60*60)
{
// Renting starts before 02:00
$expensive_time += 2*60*60 - $start_time_of_day;
$cheap_time += 21*60*60; // Full 21 hours of cheap time
$expensive_time += 1*60*60; // 1 hour of expensive time from 23:00 to midnight
}
elseif ($start_time_of_day<23*60*60)
{
// Renting starts after 02:00 and before 23:00
$cheap_time += 23*60*60 - $start_time_of_day;
$expensive_time += 1*60*60; // 1 hour of expensive time from 23:00 to midnight
}
else
{
// Renting starts after 23:00
$expensive_time += 24*60*60 - $start_time_of_day;
}
// !! Use a similar strategy for the $end_time_of_day here
$price += ceil($expensive_time/60/60) * 10;
$price += ceil($cheap_time/60/60) * 5;
echo $price." euro";
?>

PHP : How to calculate the remaining time in minutes?

Suppose the target time is 4.30 pm and the current time is 3.25 pm , how will i calculate the minutes remaining to reach the target time ? I need the result in minutes.
session_start();
$m=30;
//unset($_SESSION['starttime']);
if(!$_SESSION['starttime']){
$_SESSION['starttime']=date('Y-m-d h:i:s');
}
$stime=strtotime($_SESSION['starttime']);
$ttime=strtotime((date('Y-m-d h:i:s',strtotime("+$m minutes"))));-->Here I want to calcuate the target time; the time is session + 30 minutes. How will i do that
echo round(abs($ttime-$stime)/60);
Krishnik
A quick calculation of the difference between two times can be done like this:
$start = strtotime("4:30");
$stop = strtotime("6:30");
$diff = ($stop - $start); //Diff in seconds
echo $diff/3600; //Return 2 hours. Divide by something else to get in mins etc.
Edit*
Might as well add the answer to your problem too:
$start = strtotime("3:25");
$stop = strtotime("4:30");
$diff = ($stop - $start);
echo $diff/60; //Echoes 65 min
Oh and one more edit:) If the times are diffent dates, like start is 23:45 one day and end is 0:30 the next you need to add a date too to the strtotime.

Seconds to Year

Basically, I am trying to recreate PHP date's year functionality. Using the number of seconds since 1 January 1970, I am trying to get the year with out using a built in function. I had a an idea, but it did not work because of leap years. Can anyone give me a working formula that takes the seconds since 1970 and gets a year from it?
To find the year you need to deal with leaps.
The years from 1 are ordered as blocks of 4 years been the last of them one day longer, right? So you have blocks of:
seconds_block = 365*3 + 366 days = 126230400 seconds
seconds_year = 365 days = 31536000 seconds
1970 is the second year of its block so with this:
<?php
//test_year.php
$given_seconds = $argv[1];
$seconds_year = 31536000;
$seconds_block = 126230400;
$total_blocks_to_1968 = 492;
$actual_block = floor((($given_seconds + $seconds_year) / $seconds_block)) + $total_blocks_to_1968;
$actual_offset_from_last_block = ($given_seconds + $seconds_year) % $seconds_block;
$actual_year_of_the_block = min(floor($actual_offset_from_last_block / $seconds_year) + 1, 4);
$actual_year = $actual_block * 4 + $actual_year_of_the_block;
echo $actual_year;
Testing it...
$ php test_year.php 0
1970
$ php test_year.php 1
1970
$ php test_year.php -1
1969
$ php test_year.php 31536000
1971
$ php test_year.php 31535999
1970
$ php test_year.php 126230400
1974
$ php test_year.php 126230399
1973
More:
One year is leap if is divisible by 4 except those divisible by 100 (but not by 400).
function isLeap(year){
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)
}
EDIT: pseudocode formula
x = input // number of seconds since 1970
sy = 31536000 // seconds a non leap year
sb = 126230400 // seconds a block of 3 non leap years and one that is
actual_year = (floor(((x + sy) / sb)) + 492) * 4 +
(min(floor(((x + sy) % sb) / sy) + 1, 4));
Cheers
You can't ignore leap years.
You have year = 1970
Add numSecsInYear to that, increment the year
if year is leap, then 'eat' one more sec.
... until there is less that 1 year of seconds
then go month by month, day by day, hour by hour, min by min
also, year is leap if
- if ends with 00, if it gives no rest after dividing by 400
- else if it gives no rest after dividing by 4
You figure out the code :)
And yes, this isn't very much optimized :)
p.s. obviously, when going month by month, keep in mind that february has 29 days if year is leap :)
This is actually wrong, but a good enough approximation if you don't need the year to change exactly at the time of the new year. The idea is, the number of days in a year, in order for there to be leap years every 4 years, is 365.25 days.
$a = time();
$y = 1970 + floor($a / 60 / 60 / 24 / 365.25);
If you are using a UNIX-like system, you can use the system's date functionality to format times instead of reimplementing the PHP function:
date +%Y
gives the current year. You can then use the -d switch to format a custom date, rather than the current date:
date -d "UTC 1970-01-01 1287946333 secs +%Y"
gives "2010".
For years 1970 - 2038, you can use these equivalents (+/- a few minutes for the months and years):
Human readable time Seconds
1 minute 60 seconds
1 hour 3600 seconds
1 day 86400 seconds
1 week 604800 seconds
1 month (30.44 days) 2629743 seconds
1 year (365.24 days) 31556926 seconds
You can test your formulae here These equivalents can be off by enough minutes on key days (ie, Dec 31 / Jan 1) and are only good for epoch times away from boundaries.
If you want to be exact you need to deal with each and every leap year; either through a formula or through iteration.
This Perl code calculates the year from epoch seconds for any year +/- 130 or more years from 1970 (the Unix epoch). You need to know on your platform how big (32 bit or 64 bit) the epoch number is to know the span:
sub days_in_year {
my $year=shift;
my $leap =
($year % 400 == 0) ? 1
: ($year % 100 == 0) ? 0
: ($year % 4 == 0) ? 1
: 0
;
return (365+$leap);
}
sub epoch_to_year {
use integer;
my $t=shift;
my $ey=1970;
my $secs=$t;
if($t<0) {
while($secs<0) {
$secs+=days_in_year(--$ey)*24*60*60;
}
return $ey;
}
else {
while($secs>0) {
$secs-=days_in_year($ey++)*24*60*60;
}
return $ey if ($secs==0);
return $ey-1;
}
}
It is SLOW and you should use a library, but it you do not have one it will work. It is trivial to translate that to PHP. (sub => function, delete my, etc)

Categories