Carbon date difference in minutes, hours, days, etc - php

I am using the Carbon Date library.
I want the difference between two dates which outputs directly as below:
If the difference is in minutes, then it should show something like 26 Minutes
If the difference in hours, then it should show something like 4 hours 3 Minutes
If the difference is in days, hours, minutes then it should show something like 2 Days 9 Hours 7 Minutes
If the difference is in days & minutes, then it should show something like 3 Days 10 Minutes and NOT 3 Days 0 Hours 10 Minutes
I am having a solution where I check, d, h, i and set the data manually, also I don't want the solution as 0 Days 0 Hours 15 Minutes.
The logic should be smart enough to omit the 0 ones.
So I searched under Carbon Documentation, but I didn't find one, I am not looking for the difference for Humans.
Hence I am looking if there is a Carbon Method which I have not discovered.
Thanks.

Related

Extract Working/Non-Working Hours With Weekend/Weekday Breakdown For A Working Schedule

I do need a calculation script for my project which would be calculating 4 things in minutes for me.
Total assigned minutes in working hours for weekdays (Between 08.30 - 17.30)
Total assigned minutes in out of working hours for weekdays (Except 08.30 - 17.30)
Total assigned minutes in working hours for weekends (Between 08.30 - 17.30)
Total assigned minutes in out of working hours for weekends (Except 08.30 - 17.30)
Basically, I am creating and using a schedule Google Calendar actually but doesnt matter, I just have start-end datetime objects in my hand for the employees on a calendar and assigning datetime ranges to employees to make them responsible for answering the customer calls in a certain time range which also could last a week, a few hours, a few minutes or a few days. The thing here is those date ranges are pretty flexible.
I've tried looping over the unix timestamp, creating a DateTime object per loop and check those 4 things but that would have been too much memory&cpu usage as I locked my computer a few times. I would be able to loop over hours in day if the events could only last a day at maximum but they are very flexible so I need a strong algorithm here.
For example a schedule would look like below:
Start(DateTime Object) => 2022-01-27 00:00:00
End(DateTime Object) => 2022-01-29 13:30:00
The function should take those two objects as an argument and should create an output like in the picture I ve shared below. Should be similiar to this:
function createReport(DateTime $employeeWorkStart, DateTime $employeeWorkEnd) : array {
...
return [
'weekday_in-working-hours' => XXX,
'weekday_out-working-hours' => XXX,
'weekend_in-working-hours' => XXX,
'weekday_out-working-hours' => XXX,
]
}
So I need to create a monthly-basis report which shows how many minutes I've assigned for each employee in the schedule.
My working hours are between 08.30 - 17.30, saturday & sunday is considered as weekend.
Example Report Output
So, not able to provide an actual code-answer right now. But how I would approach it is the following:
Get the amount of days between the two dates, subtract weekends. Also subtract one day if the $employeeWorkEnd is the current day (today) and if you want to have extra precision. I found this gist that gives you the working days (weekends and holidays excluded): https://gist.github.com/quawn/8503445
Multiply this by 9 (working hours) and then by 60 to get the total minutes. This is the total time worked.
If you wanted the extra precision in step 1, now just take the difference in minutes between 09:30 and the current time (date_diff can provide this). Add this difference to the total you had so far.
Execute this procedure for every employee you have. The above procedure will not do any loops, I believe it should be possible to do it just by subtraction and multiplication (if you want to exclude holidays using the code in the gist, this will introduce a small loop assuming low amount of holidays).
Your example output shows hours but your description shows minutes. The above story will give you minutes but it's just as easy to get the hours (or milliseconds for that matter).

Convert a string describing a working shift into a integer that equals the hours

Problem
In my php webapp a user can create a new event with the following properties:
StartDate (DATE)
EndDate (DATE)
OpeningHours (STRING)
I want to use these properties to calculate the number of hours the event is going as an DOUBLE. (because these hours define how long the working shift is). Basically start and end date is given in a normalized way, but the opening hours can be given in any kind of way.
Example
So if a user enters the following data
StartDate: "2015-07-02"
EndDate: "2015-07-05"
OpeningHours: first day from 9 am to 6:30pm, other days till 6pm
I want to calculate that the total number of events hours is 36,5 hours (first day 9 hours + other three days 9,5 hours each).
Constraints
There are almost endless ways to describe opening hours, here are just a few:
"from 9 am to 6 pm, except last day till 6:30 pm"
"from 9 am to 6 pm, except saturday from 9 am am to 6:30 pm"
"first day from 9 am to 6 pm, second day from 9 am to 6 pm, third day from 9 am to 6:30 pm"
"July 2nd from 9 am to 6:30pm, other days till 6 pm"
I don't expect to be able catch all phrases, but at least the mayority.
My Approachso far
My basic approach so far is the following:
Calculate the number of days the event is going (e.g. 4 days)
Parse the OpeningHours String and get all substrings that describe one or more shifts (e.g. "from 9 am to 6 pm, except last day till 6:30 pm" becomes "9 am to 6pm" and "except last day till 6:30pm")
For each substring calculate how long the shift is, that it describes (e.g. "9 am to 6pm" is 9 hours and "except last day till 6:30pm" is 9.5 hours)
For each substring describing a shift duration try to guess, to how many days it should be applied to (e.g. 9.5 hour shift only to one day, the 9 hour shift to all other)
Add up all numbers to calculate (36.5 hours total)
Step 3 is hard because sometimes on substring describing a shift has not the complete information, but instead references a another substring (e.g. "except last day till 6:30pm" implies that it also starts at 9 am).
Step 4 is hard because there are many different indicators that can define onto how many days a described shift should be applied to (e.g. "except last day..." implies that this shift is only applied to one day).
Has anybody run into similiar problem and might be able to guide me through a solution, that would at least catch the majority of phrases and calculate the hours properly?
Or maybe there does even already exist a library or best practise approach that solves this problem in an elegant way

Output format while building mysql php countdown function [duplicate]

This question already has answers here:
Converting timestamp to time ago in PHP e.g 1 day ago, 2 days ago...
(32 answers)
Closed 8 years ago.
I've been struggling with this for quite sometime, after few long hours spend on forums I came up with this code:
SELECT *, TIMESTAMPDIFF(SECOND,NOW(),`pay_date`) AS `expire` FROM `users`
pay_date is datetime field which in the moment of tries had setup (current time + 7 days)
so NOW() is showing 03-09-2013 23:30:20; pay_date is showing 10-09-2013 23:30:20. I'am using this code to extract my countdown:
echo $date['expire'];
It is working, its properly giving me amount of seconds left, what i dont know is how to make it to say something like:
2 years, 10 months, 20 days, 5 hours, 30 minutes, 46 seconds left.
ive tried in few ways for instance date('d-m-Y H:i:s', $date['expire']) but its giving me as output something like 1790-01-01, strtotime isnt also working, i dont know how to make it to work in the way i described above.
You can use DateTime class for time calculation:
Code:
$start = new DateTime;
$end = clone $start;
$end->modify("+{$date['expire']} seconds");
$diff = $start->diff($end);
print_r($diff);
Output:
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 0
[i] => 4
[s] => 29
[invert] => 0
[days] => 0
)
As you can see in output, you have all the info you need. To access it, just use $diff->i for minutes, $diff->s for seconds etc. or use DateInterval::format for formating interval.
I strongly suggest using PHP's DateTime object instead of strtotime.
http://www.php.net/manual/en/book.datetime.php
You can get the date difference using Datetime::diff method.
Also, you can style output however you want:
$datetime->diff()->format('%y Years, %m Months, %d Days')
sorry guys but none of these works, this stuff time_elapsed_string($ptime) no matter what i do, i can even put there date manually and it still returns 44 years ...
new so cold feature DateTime class isnt accurate, its so far from true while calculating, there is more professional and working solution for this, i will wait until someone present solution that actually works.
Again, i believe that nobody wants amateur function that sometimes works sometimes not and is badly written (months always 30 days ? no thanks). While reading php manual you will qucikly notice that there is a lot of proof's that datetime class isnt working, even on stackoverflow ive seen that kind of posts.
This stuff is good:
select *,Concat(hour(diffTime),' hours ',minute(diffTime),' Minutes ',second(diffTime),' seconds remaining') as timetaken
from (select *,sec_to_time(UNIX_TIMESTAMP(now())- UNIX_TIMESTAMP( ttable.pay_date))
as diffTime from users ttable )
as temptable1
i've found it on different topic also related to date calculating, adapted it to my database and it works, but unfortunetely it shows only Hours Minutes and Seconds, when its like few days it shows 800 hours for example, i dont understand how it works exactly, but i believe it could be modified to show also years months and days perhaps someone will know how to do it

Strange PHP 5.3 issue with date diff calculating difference in days

I am experiencing a rather strange problem using PHP 5.3's date diff function to calculate the difference in days between two dates. Below is my code:
$currentDate = new DateTime(); // (today's date is 2012-1-27)
$startDate = new DateTime('2012-04-01');
$diff = $startDate->diff($currentDate);
$daysBefore = $diff->d;
echo $daysBefore;
The above code displays 4 as the value of the $daysBefore variable.
Why is PHP displaying a difference of 4 days between the dates 27th Jan 2012 and 1st April 2012, when clearly there are many more days between these dates.
Am I doing something wrong?
DateInterval::$d is the days part of the interval, not the total number of days of the difference. For that, you want DateInterval::$days, so:
$daysBefore = $diff->days;
When creating a DateInterval through the DateTime::diff method, it populates not just days, but hours, minutes, seconds, months and even years in the single character properties. You're checking single-character d for days, which will be the days left over once years and months are calculated.
Try looking at the days property, which only actually gets populated when you use diff.
Behavior here is wildly inconsistent. Check out the DateInterval::format manual page for some interesting information about what happens when you create a DateInterval through various means.
The d property is the number of days as in "3 months, 4 days". If you want the total number of days, use the days property.
4 days, and a couple months...
Use $diff->days for total number of days.
http://www.php.net/manual/en/class.dateinterval.php

How do I calculate the number of seconds in a month in PHP?

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.

Categories