Carbon difference between two dates to get a decimal for hourly rate calculations
Asked Answered
G

3

9

I am using Carbon to calculate the time between two dates. I'd like to be able to take difference between two dates and determine the time in decimal format to be able to calculate hourly rate. From my testing, the ->diffInHours() call gives me the hours between two dates in whole numbers.

For example

$actual_start_at = Carbon::parse('2017-05-01 13:00:00');
$actual_end_at = Carbon::parse('2017-05-01 15:15:00');
return $actual_end_at->diffInHours($actual_start_at, true);

Returns

2

I would like something that returns to get the 2 hours 15 minutes

2.25
Giza answered 22/5, 2017 at 4:55 Comment(0)
H
19

Unfortunately, diffInHours only take two parameters. Maybe, you can try diffInMinutes though and then get the value you require from there?

For e.g.

$actual_start_at = Carbon::parse('2017-05-01 13:00:00');
$actual_end_at   = Carbon::parse('2017-05-01 15:15:00');
$mins            = $actual_end_at->diffInMinutes($actual_start_at, true);

dd($mins/60);

would output

2.25

Also, if you use the diff() method, it would return a DateInterval object instead.

$mins = $actual_end_at->diff($actual_start_at, true);

and then dd($mins) would output:

DateInterval {#913 ▼
  +"y": 0
  +"m": 0
  +"d": 0
  +"h": 2
  +"i": 15
  +"s": 0
  +"f": 0.0
  +"weekday": 0
  +"weekday_behavior": 0
  +"first_last_day_of": 0
  +"invert": 0
  +"days": 0
  +"special_type": 0
  +"special_amount": 0
  +"have_weekday_relative": 0
  +"have_special_relative": 0
}
Hospitalet answered 22/5, 2017 at 8:44 Comment(2)
of course, the solution is so simple. I can't believe I didn't think to go this route. Thank you for your response.Giza
@Giza if it worked for you, would you please accept the answer? :)Hospitalet
B
1

Here's a more complete solution using CarbonPeriod.

Carbon Calculate hours in an interval from a period

<?php

use Carbon\Carbon;
use Carbon\CarbonPeriod;
use Carbon\CarbonInterval;

class PeriodInterval {
    public function hoursIn() {
        /**
        * Time Periods
        */
        $periods = [
            'day' => [
                '08:00:00',
                '18:00:00'
            ],
            'night' => [
                '18:00:00',
                '08:00:00'
            ],
            'lunch' => [
                '11:00:00',
                '14:00:00'
            ]
        ];

        /**
        * Time Intervals
        */
        $intervals = [
            'parking' => [
                'John Doe' => [
                    Carbon::createFromFormat('Y-m-d H:i:s', '2018-12-10 07:00:00'),
                    Carbon::createFromFormat('Y-m-d H:i:s', '2018-12-10 09:00:00')
                ],
                'Jane Doe' => [
                    Carbon::createFromFormat('Y-m-d H:i:s', '2018-12-10 08:00:00'),
                    Carbon::createFromFormat('Y-m-d H:i:s', '2018-12-10 09:00:00')
                ],
                'John Hope' => [
                    Carbon::createFromFormat('Y-m-d H:i:s', '2018-12-10 11:00:00'),
                    Carbon::createFromFormat('Y-m-d H:i:s', '2018-12-10 13:00:00')
                ],
                'Jane Hope' => [
                    Carbon::createFromFormat('Y-m-d H:i:s', '2018-12-10 18:00:00'),
                    Carbon::createFromFormat('Y-m-d H:i:s', '2018-12-10 19:00:00')
                ]
            ]
        ];

        /**
        * Hours for Interval in Period
        */
        function hoursForIntervalInPeriod(array $period, array $interval) {
            $Period = new CarbonPeriod(array_shift($interval)->toDateTimeString(), '1 hour', array_pop($interval)->toDateTimeString());

            return $Period->filter(function($date) use ($period) {
                $period_starts = Carbon::createFromFormat('Y-m-d H:i:s', $date->format('Y-m-d') . ' ' . array_shift($period));
                $period_ends = Carbon::createFromFormat('Y-m-d H:i:s', $date->format('Y-m-d') . ' ' . array_pop($period));

                // Normal Period
                if ($period_starts < $period_ends) {
                    return ($date >= $period_starts && $date < $period_ends);
                }

                // Inverted Period (Overnight)
                if ($period_starts > $period_ends) {
                    return ($date >= $period_starts || $date < $period_ends);
                }

                return false;
            })->count();
        }

        /**
        * Map Everything
        */
        $hours = array_map(function($interval, $interval_key) use ($periods) {
            return array_map(function ($period, $period_key) use ($interval, $interval_key) {
                return [ $interval_key . ucfirst($period_key) => array_map(function($interval_item, $interval_item_key) use ($period) {
                    /**
                    * Calculate Total Hours
                    */
                    $total_hours = hoursForIntervalInPeriod($period, $interval_item);

                    return [ $interval_item_key => $total_hours ];
                }, $interval, array_keys($interval)) ];
            }, $periods, array_keys($periods));
        }, $intervals, array_keys($intervals));

        return $hours;
    }
}
Beeler answered 16/11, 2018 at 23:5 Comment(0)
P
1

There is Carbon::floatDiffInDays() which should suit your needs

Paiz answered 4/3, 2019 at 16:28 Comment(1)
get BadMethodCallException with message 'Method floatDiffInDays does not exist.' when I use itWaadt

© 2022 - 2024 — McMap. All rights reserved.