I have a bug reported whereby the user selects a date frame from a dropdown, hours, days, months and enter a freetext number.
When it's saved this is converted to a number of seconds.
I need to display this field as currently it's not being displayed. How can I work out how to make it into the same value they entered? We do not store the value of the dropdown for some strange reason.
Is there a way to just convert it to the maximum number of time block available for that number of seconds, or shall I just store the dropdown field, which is what I'm likely going to do.
Converting is not an option, since you don't know anything about what the user meant. For example, when I input the number '3', you can't determine if I meant 3 days or 3 months.
Let me elaborate a bit: if I input '3' and select 'days', the time in seconds is: 60 * 60 * 24 * 3 = 259200 seconds. When displaying, you could divide it so that the output is '3 days' again. But what if I inputted '72' and selected 'hours'? You can't tell.
Just store the users choice and you're fine.
If you are looking to split it into chunks dependent such as days/months fairly simple maths operations inside a block should do the trick.
if($seconds > 2629743){
// code for month
}
elseif ($seconds > 86400) {
// code for days
}
Related
I am trying to write a php solution to calculate the planned end time considering the target in business hours.
It shouldn't consider some days (retrieved from setting saved in db) such as holidays.
Also business hours are retrieved from db (morning_from (8:30am), morning_to (1:00pm), evening_from (2:30pm), evening_to (6:30pm)).
I want to develop this script because I want that my page shows the remaining time for technical resolution of an opened ticket every day.
For example:
customer having contract with 10 working hours SLA opens a ticket
today (friday) 31/01/2020 16:00:00, considering that in the
noBusinessDays = array("saturday", "sunday") and businessHours set as mentioned before(8:30-13:00/14:30-18:30), the result will have to
be monday 3/02/2020 17:30:00.
Code example:
$noBusinessDays = array("saturday", "sunday");
$businessHours = array("morning_from" => "8:30", "morning_to" => "13:00", "evening_from" => "14:30", "evening_to" => "18:30");
$SLA = "10"; //hours
$ticketDate = new DateTime();
$ticketDate->setTimestamp(strtotime("31/01/2020 16:00:00"));
// I don't know how to use my arrays to say in this calculation how to use them
$maximumLimit = $ticketDate->add(new DateInterval("PT" . $SLA ."H"));
Thank you in advance.
You may use the following function
// intersection of 2 time intervals
// input - Unix timestamps (start,end)
// output - intersection in seconds
function time_union($b_1,$e_1,$b_2,$e_2)
{
return max(0,$e_1-$b_1 - max(0,$e_1-$e_2) - max(0,$b_2-$b_1));
}
You will start with an empty time interval [X, Y) where X is the timestamp of the ticket creation and Y initially is equal to X.
Then you start adding days to Y - one by one. Each time you expand the time interval to contain another day - you use the above function to check how much of the SLA hours are covered (i.e. overlapping) with the working hours in the day you have just added. If the day is marked as a holiday - you simple skip it and continue with the next date.
If you find out that SLA hours are partially covered with either the morning or evening business hours - you should simply subtract the extra hours.
In the end Y will be equal to the timestamp that you want to show in your application.
I think I'd break down the problem into pieces. After calculating the total number of days in the interval, first dispose of the trivial case that it's all happening in one week.
begin by calculating the number of "whole weeks." Each "whole week" is five business days. Subtract the corresponding interval of time and proceed. Now, look at the day-of-the-week of the start-date: each day adds a certain number of days. Then the day-of-week of the end date, likewise. You can then consider hour-of-the-day as needed.
Holidays are a simple table: if the day falls within the range, subtract one day.
Now ... having said all of that, the very first thing that I would do is to search GitHub and SourceForge! Because I am extremely sure that somebody out there has already done this. :-D
"Actum Ne Agas: Do Not Do A Thing Already Done."
I'm using Lumen to build an API. At first, I want to explain my work a little
bit. My API will provide an content to a user. The user will record the content
and submit it with audio length. (EX: 1min. 22 sec.)
I just store it in my
database. when the user wants to see how many hours he recorded I will return
the total time. okay... that's why i was created a table column
$table->decimal('audio_length');
and store it how user sends request. when the user wants to see the total
time my code will work like:
$point = PointSpeech::where('user_id', Auth::user()->id)->get();
$total_point = 0;
foreach ($point as $value) {
$total_point += $value->points_pending;
}
return response()->json(['status'=> 'Success', 'point_pending' => $total_point], 200);
yeah I know it's a stupid way. Now I looking for a better way to show it as
Hour, Minute and Second. hi, can you guys help me...? please...?
When you're storing the duration in this way, you should always convert to the smallest unit you want to record. In your case, if you don't care about milliseconds (or smaller), you should convert the time given by the user to seconds e.g. 1 minute 22 seconds, would be 82 seconds.
This is the number you should store in the database. If you do care about smaller units such as milliseconds, then that is what you should store in the database. Store an integer value.
Now when pulling your information out of the database, you can do a simple SUM to get the total number of seconds (or milliseconds) and convert that back to display to the user.
Converting to hours, minutes and seconds should be easy enough to do once you have an integer representing seconds. As an example:
$seconds = 176; // This would come from your database query
echo (new DateTime('#0'))
->diff(new DateTime("#$seconds"))
->format('%h hours, %i minutes and %s seconds');
What i want is simple, i have timestamp in my mysql database that records date and time data registers. What i want is to calculate the timediff between timestamp and current time then subtract from 3hours to know time remaining in hh:mm:ss format, please someone help out.
You should use the following part in your query:
SELECT TIME_FORMAT(SEC_TO_TIME(AVG(TIMESTAMPDIFF(SECOND, NOW(), column_with_date_to_compare))), '%H:%i')
You must skip the AVG part if you do not want averages but a result per row (or you have only one row to check) (or use GROUP BY [something])
The part 'then subtract from 3hours', I don't understand. You only want to show the records where the time is less than 3 hours? Just use WHERE TIME(record_to_check) > (NOW() - 10800).
If you want to add, calculate or do other things to influence the result, just do so before SEC_TO_TIME, you can do the math (with seconds) there.
I've interpretted your question as how to calculate the time remaining in a 3 hour period starting at a datetime stored in a DB, to be displayed in HH:MM:SS format...
I generally find it easier to manipulate dates / times in php rather than wihtin an SQL query. So my approach would be to:
read strings from the database
convert them into unix timestamps (ie
number of seconds elapsed since a given epoch)
manipulate them mathematically (ie add on 3 hours and subtract the curent time)
lastly convert the result back into a date / time in your chosen
format.
Assuming $start_str has been read from your DB
$start_str = '08-03-2017 11:10:00';
$start_ts = strtotime("$start_str");
$end_ts = $start_ts + (3 * 60 * 60);
$now_ts = strtotime('NOW');
$remaining_ts = $end_ts - $now_ts;
$remaining_str = ($remaining_ts > 0)? sprintf('%02d:%02d:%02d', ($remaining_ts/3600),($remaining_ts/60%60), $remaining_ts%60) : "None, time's up";
echo ($start_str.'|'.$start_ts.'|'.$end_ts.'|'.$now_ts.'|'.$remaining_ts.'|'.$remaining_str);
Examples...
08-03-2017 11:10:00|1488971400|1488982200|1488983863|-1663|None, time's up
08-03-2017 14:30:00|1488983400|1488994200|1488983982|10218|02:50:18
Obviously in reality you're only interested in the last field, but the others show you what you're playing with during the process.
This seems like there should be a very easy solution, however everything I'm trying is either giving me an error or the wrong result.
I'm pulling data from a MySQL table and the time is stored in the Epoch format in the database. When I make the query on the website it's showing: 3672 (the same number shown in the database). I've tried using the date() function, a number of different str* functions, different arithmetic operations, however nothing is giving me the actual time, which should be showing as: '1:02'.
I'm not trying to pull the date, actual time, etc. I'm just trying to convert an Epoch time string to a traditional 'H:mm' format, because these are for durations, not timestamps.
Any help would be greatly appreciated!
As others already noticed, this is not really any standard epoch time but simply number of seconds since midnight.
Looking at your example, you only need hours and minutes (rounded up). This will give you those:
$h = (int)($number / 3600);
$m = ceil(($number - $h * 3600) / 60);
$result = sprintf('%d:%02d', $h, $m);
Dividing number by 3600 (60 for seconds * 60 for minutes) will give you number of hours. Using your example of 3672 this will give you 1.
To get minutes you just remove hours to get seconds (72) and then divide that by 60 to get minutes (1 minutes and 12 seconds). Since your example specifies 1:02 is result, you can simply take next upper integer (2).
At end result is 1:02, as you specified.
How do I accurately determine the number of seconds in a month using PHP? Is the best way to take the number of seconds in a year and divide by 12?
Multiply the number of days in the month by 60 * 60 * 24.
Due to daylights savings... take a good datetime library in your language and calculate the difference between the first day of the month 0:00:00 and the first day of the next month 0:00:00 and extract the number of seconds.
How accurate do you need to be?
60 seconds * 60 minutes * 24 hours * Z days in the month gives you an accurate number for a given month.
If you need an average month go for number of seconds in the year and divide by twelve.
In some domains, such as billing or legal domains a 'month' might actually be exactly 30 days.
If you are working across multiple years or doing tight integration between disperse systems, you'll need to consult resource to determine leap seconds. For historical data this could be a table, but otherwise you'd be better suited by synchronizing to a trusted time source.
http://en.wikipedia.org/wiki/Leap_second
60 (seconds) * 60 (minutes) * 24 (hours) * ## (days in the month)
Given that there are 86,400 seconds in a day, you can multiply this number by the result of the DateTime.DaysInMonth function (in C#). The following function does just that:
public double SecondsInMonth(int year, int month)
{
return DateTime.DaysInMonth(year, month) * 86400;
}
E.g., find the seconds in the current month:
double secondsInCurrentMonth = SecondsInMonth(DateTime.Now.Year, DateTime.Now.Month);
Number of days in the given month * hours/day * minutes/hour * seconds/minute
is the best way.
If you're doing this in pure math it would be 60 * 60 * 24 * <number of days in month>.
What's the use case?
No, use the date API available for a particular lannguage and determine the number of days in the current month. Then calculate the number of seconds. Also take into account leap years.
Depends on if you want an average month or a specific month....your way gets an average. For a specific month count days and multiply by 86400 (seconds per 24.0 hour day)
This isn't really a programming question. Months have different lengths, so dividing the number of seconds in a year by 12 will give you nothing useful. It's easy to determine the days in a month - a simple lookup table plus a calcualation of leap years will do it. Then just multiply by the number of seconds in a day.
If you are being really precise you might need to include calculations of leap seconds, but since they are unpredictably assigned based on astronimical calculations, and not predictable in advance, I would probably ignore them.
Number of days vary in each month.Proper algorithm for this is to get number of days in moth and multiply it with 86400 (number of seconds in a day).You might also need average count or leap years calculation ...
The trivial answer is to find the number of days in the month and then multiply by 86400. That will work perfectly if you are dealing with dates and times in UTC. However, if you are using a local time zone then this approach yields a slightly incorrect result if that time zone observes daylight saving time. The error is somewhat small over a one month period, but will magnify if you need to make similiar calculation over short periods like a day. I definitely recommend doing all processing and storage in UTC, but depending on the application you will have to convert your UTC times to the local time zone that the end user is expecting. And it might even be plausible that you have to calculate durations using the local time zone. Again, use UTC as much as possible so that you avoid most of the problems.
I came up with this solution in C#. It is compatible with UTC and local time zones alike. You just have to tell the GetNumberOfSecondsInMonth which time zone you want the calculation to be based on. In my example I chose November of 2010 because here in Missouri we observe DST and there was one extra hour this month. Daylight saving time rules change so I used an API that pulls the DST information from the operating system so that the calculation will be correct for years prior to 2007 (that is when the United States expanded DST for most regions).
I should point out that my solution does not handle leap seconds in UTC. For me that is never an issue. But it would be easy to account for that by using a lookup table if you really needed ultra high precision timing.
public class Program
{
static void Main(string[] args)
{
int seconds = GetNumberOfSecondsInMonth(2010, 11, DateTimeKind.Local);
}
public static int GetNumberOfSecondsInMonth(int year, int month, DateTimeKind kind)
{
DateTime start = new DateTime(year, month, 1);
DateTime end = start.AddMonths(1);
int seconds = (int)(end - start).TotalSeconds;
if (kind == DateTimeKind.Local)
{
DaylightTime dt = TimeZone.CurrentTimeZone.GetDaylightChanges(year);
seconds = (dt.Start > start) ? seconds - 3600 : seconds;
seconds = (dt.End < end) ? seconds + 3600 : seconds;
}
return seconds;
}
}
It's a problem with years ang months as there is not a fixed number of days in them. But after a lot of thought I have figured out how to do it. It was not a good idea to calculate months with either 30 or 31 days in them, because it looks bad, for example converting from 1 year to months would give an answer of 11 months and 25 days if I had 30 days in each month, or 12 months and 5 days if I have 31 days in each month.
Instead I loop through a series of days per month: 30,30,31,30,31,30,31,30,31,30,31,30 which makes a total of 365 days in a year. So if I want the number of days in 4 months I add 30+30+31+30. And if I start with 23 months it would go through the loop almost twice (23 times 30 or 31). It's done in a while/until loop. For every 4 years I add 1 day, making it 366 days (the first 30 is changed to 31 in the list). It's rather complex but it works and the result looks better.