10

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

3 Answers 3

21

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
}
Sign up to request clarification or add additional context in comments.

2 Comments

of course, the solution is so simple. I can't believe I didn't think to go this route. Thank you for your response.
@jdcarg if it worked for you, would you please accept the answer? :)
1

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

1 Comment

get BadMethodCallException with message 'Method floatDiffInDays does not exist.' when I use it
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;
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.