Closed baptistebisson closed 6 years ago
The correct result should be 24 days 7 hours
Sorry but no, diffForHumans does not care about week days and should not no matter you previously calculate something with diffInWeekdays, that's 2 calls that does not interfere.
So, it's a business specific need and solution depends on your specifications. What is your granularity (smallest unit to display), and biggest unit since month/year would not have too much sense with 5-days weeks counting. So I guess, it should rather use week count as maximal unit then, day/hour remaining.
Can you precise your expectations for that?
My mistake sorry. 24 days 7 hours
is what I would like to get at the end.
For my needs, the smallest unit should be hours, and the biggest: month. Here is some example of time difference that would be perfect:
Or if this is too complex, the result of diffForHumans
is already great ! I only need to get the result with only working days.
Do you consider a month is 5 weeks, 20 work days? I don't understand your way to cascade it?
And if you use workday, I presume days may not be 24 hours long. What would be expected diff from 2018-09-13 16:30:00 to 2018-09-14 09:30:00?
See what I mean, you need rules to cascade from one unit to the other. That's what allow to split into multiple parts the difference.
If you're not sure, tell me what you are trying to do. You have work task start and end and try to figure out the time spent?
A month is about 20 work days yeah.
Well if you want details here are they:
I'm building an app where you can take your holidays in it. A week is 5 days from 08h30 to 18h00. So yes, a day is not 24 hours longs.
Someone can take holidays the same day. From 2017-07-12 11:00 to 2017-07-12 18:00 so the duration will look like this:
If it's 2 days like from 2017-07-12 to 2017-07-13
If the duration is 10 days
And is you take your holidays from 2017-07-13 11:00 to 2017-07-17
diffForHumans
do that really well already. I only want to add a filter to it so I can check if this is a work day or not.
-> For this example it will be 7h + 2 days + 2 weeks = 2 weeks 2 days 7h
I don't think it is possible to use custom factors (hour/day/week ratios) in diffForHumans
of plain Carbon.
You could instead count the number of work hours with diffInHoursFiltered
. Check if each passed date is on weekday within the hour range you mentioned. Then create a new interval from counted hours and cascade it using custom factors defined by setCascadeFactors
:
CarbonInterval::setCascadeFactors(array(
'dayz' => array(10, 'hours'),
'weeks' => array(5, 'dayz'),
'months' => array(20, 'dayz'),
));
$resolution = CarbonInterval::hour();
$start = Carbon::parse('2017-07-13 11:00');
$end = Carbon::parse('2017-07-17 18:00');
$hours = $start->diffFiltered($resolution, function ($date) {
return $date->isWeekday() && $date->hour >= 8 && $date->hour < 18;
}, $end);
$interval = CarbonInterval::hours($hours)->cascade();
echo $interval->forHumans(); // 2 days 7 hours
Unfortunately it looks like CarbonInterval::forHumans
doesn't produce as nice output as Carbon::diffForHumans
. It would be nice if we could use the same method internally, to keep output of both in line, for example by calling CarbonInterval::forHumans
from Carbon::diffForHumans
.
Additionally I noticed that if we define months factor using weeks 'months' => array(4, 'weeks'),
it will zero-out the days part completely when cascading.
diffForHumans do that really well already. I only want to add a filter to it so I can check if this is a work day or not.
I would not say that, because if you leave at 16pm and come back next day 11am, diffForHumans will not allow you to handle the off-business time. And I don't even talk about a possible lunch break.
We are far away from diffForHumans abilities and purpose I think.
Else I think @imbrish is right, if hour is your smallest unit, then count total work hours then cascade it to each next unit using setCascadeFactors and cascade with your own factors.
@imbrish Thank you so much, it's perfect ! I will update my post to share what I've done. Didn't know about the cascade factors.
Last question. Any idea how I could sum up all these results ? For example, here is a list of holidays for 1 month:
And I want to get the total of holidays for the month.
I don't think that Carbon have any method for that. I was looking at Addition and Subtraction But it can only take a date as input and not duration.
Maybe I have to manually sum those results ?
Like this: 2 days 7 hours + 4 days = 6 days 7 hours So --> 1 week 1 day 7 hours
Then 1 week 1 day 7 hours + 9 hours = 1 week 2 days 7 hours
I will try that first, but if you have any idea it will be perfect !
You can sum intervals:
CarbonInterval::setCascadeFactors(array(
'days' => array(9, 'hours'),
'weeks' => array(5, 'days'),
));
$di = CarbonInterval::fromString('2 days 7 hours')->add(CarbonInterval::fromString('4 days'));
echo $di->cascade()->forHumans();
Output:
1 week 1 day 7 hours
Well... I did it in pure PHP but if there is a solution in Carbon :+1:
The only things I need to change is 'days' => array(9, 'hours')
with 'days' => array(24, 'hours')
since it's already formatted.
Thanks a lot for your quick response !
'days' => array(24, 'hours')
mean that if you add 8 hours + 8 hours, you will get 16 hours.
Hi.
I'm trying to get difference between two dates in human format but only with working days. Here is my actual code:
diffForHumans
is perfect for my needs but I can't find any way of filtering likediffInDaysFiltered
What I would like to achieve is to get this result
24 days 7 hours
I tried a
preg_replace
first to replace 3 days by$weekDay
result but if we have a month before it's incorrect and I have:1 month 24 days 7 hours
Is there any solution for my problem ?