Coder Social home page Coder Social logo

business-time's Introduction

business-time

Carbon mixin to handle business days and opening hours

Latest Stable Version Build Status Code Climate Test Coverage Issue Count StyleCI

Professionally supported nesbot/carbon is now available

Install

composer require cmixin/business-time

Usage

First load the mixin in some global bootstrap place of your app:

<?php

use Carbon\Carbon;
use Cmixin\BusinessTime;

BusinessTime::enable(Carbon::class);
// Or if you use Laravel:
// BusinessDay::enable('Illuminate\Support\Carbon');

// And you can enable multiple classes at once:
BusinessTime::enable([
    Carbon::class,
    CarbonImmutable::class,
]);

// As a second argument you can set default opening hours:
BusinessTime::enable(Carbon::class, [
  'monday' => ['09:00-12:00', '13:00-18:00'],
  'tuesday' => ['09:00-12:00', '13:00-18:00'],
  'wednesday' => ['09:00-12:00'],
  'thursday' => ['09:00-12:00', '13:00-18:00'],
  'friday' => ['09:00-12:00', '13:00-20:00'],
  'saturday' => ['09:00-12:00', '13:00-16:00'],
  'sunday' => [],
  'exceptions' => [
    '2016-11-11' => ['09:00-12:00'],
    '2016-12-25' => [],
    '01-01' => [], // Recurring on each 1st of january
    '12-25' => ['09:00-12:00'], // Recurring on each 25th of december
  ],
  'holidays' => [
    'region' => 'us-ny', // Load the official list of holidays from USA - New York
    'with' => [
      'labor-day' => null, // Remove the Labor Day (so the business is open)
      'company-special-holiday' => '04-07', // Add some custom holiday of your company 
    ],
  ],
]);

Try in the live editor

Business days methods are now available on any Carbon instance used anywhere later.

Features

By enabling BusinessTime you automatically benefit on every holidays features of BusinessDay, see cmixin/business-day

As soon as you set opening hours (using the second parameter of BusinessTime::enable(), Carbon::setOpeningHours([...]) or $carbonDate->setOpeningHours([...])), you'll be able to retrieve opening hours on any Carbon instance or statically ($carbonDate->getOpeningHours() or Carbon::getOpeningHours()) as an instance of OpeningHours (spatie/opening-hours), see spatie/opening-hours for complete list of features of this class.

Then with opening hours, you'll get the following methods directly available on Carbon instances:

Holidays

By default, holidays has no particular opening hours, it will use the opening hours of the current day of week, but you can use a custom exception to link automatically holidays to custom opening hours:

BusinessTime::enable(Carbon::class, [
  'monday' => ['09:00-12:00', '13:00-18:00'],
  'tuesday' => ['09:00-12:00', '13:00-18:00'],
  'wednesday' => ['09:00-12:00'],
  'thursday' => ['09:00-12:00', '13:00-18:00'],
  'friday' => ['09:00-12:00', '13:00-20:00'],
  'saturday' => ['09:00-12:00', '13:00-16:00'],
  'sunday' => [],
  'exceptions' => [
    function (Carbon $date) {
      if ($date->isHoliday()) {
        // Or use ->isObservedHoliday() and set observed holidays:
        // https://github.com/kylekatarnls/business-day#setobservedholidayszone
        switch ($date->getHolidayId()) {
          // If the ID "christmas" exists in the selected holidays region and matches the current date:
          case 'christmas':
            return ['10:00-12:00'];
          default:
            return []; // All other holidays are closed all day long
            // Here you can also pass context data:
            return [
              'hours' => [],
              'data'  => [
                'reason' => 'Today is ' . $date->getHolidayName(),
              ],
            ];
        }
      }
      // Else, typical day => use days of week settings
    },
  ],
]);

Carbon::setHolidaysRegion('us-national');
Carbon::parse('2018-12-25 11:00')->isOpen(); // true  matches custom opening hours of Christmas
Carbon::parse('2018-12-25 13:00')->isOpen(); // false
Carbon::parse('2019-01-01 11:00')->isOpen(); // false closed all day long
Carbon::parse('2019-01-02 11:00')->isOpen(); // true  not an holiday in us-national region, so it's open as any common wednesday

Try in the live editor

isOpenOn

Allows to know if the business is usually on open on a given day.

Carbon::isOpenOn('monday') // Returns true if default opening hours include monday
                           // Carbon::MONDAY would also works

$date->isOpenOn('monday') // Returns true $date opening hours include monday, if $date has no opening hours set,
                          // if will fallback to default opening hours you set globally

isClosedOn

Opposite of isOpenOn

Carbon::isClosedOn('monday')
$date->isClosedOn('monday')

isOpen

Allows to know if the business is usually on open at a given moment.

Carbon::isOpen()       // returns true if the business is now open
$carbonDate->isOpen()  // returns true if the business is open at the current date and time

if (Carbon::isOpen()) {
  $closingTime = Carbon::nextClose()->isoFormat('LT');
  echo "It's now open and until $closingTime.";
}

isClosed

Opposite of isOpen

Carbon::isClosed()       // returns true if the business is now closed
$carbonDate->isClosed()  // returns true if the business is closed at the current date and time

if (Carbon::isClosed()) {
  $openingTime = Carbon::nextClose()->calendar();
  echo "It's now closed and will re-open $openingTime.";
}

nextOpen

Go to next open-business time.

Carbon::nextOpen()       // go to next open time from now
$carbonDate->nextOpen()  // go to next open time from $carbonDate

nextClose

Go to next closed-business time.

Carbon::nextClose()       // go to next close time from now
$carbonDate->nextClose()  // go to next close time from $carbonDate

previousOpen

Go to previous open-business time.

Carbon::previousOpen()       // go to previous open time from now
$carbonDate->previousOpen()  // go to previous open time from $carbonDate

previousClose

Go to previous closed-business time.

Carbon::previousClose()       // go to previous close time from now
$carbonDate->previousClose()  // go to previous close time from $carbonDate

getCurrentDayOpeningHours

Returns the opening hours current day settings (first matching exception or else current weekday settings).

BusinessTime::enable(Carbon::class, [
  'monday' => [
    'data' => [
      'remarks' => 'Extra evening on Monday',
    ],
    'hours' => [
        '09:00-12:00',
        '13:00-18:00',
        '19:00-20:00',
    ]
  ],
  // ...
]);

$todayRanges = Carbon::getCurrentDayOpeningHours(); // Equivalent to Carbon::now()->getCurrentDayOpeningHours()
// You can also get opening hours of any other day: Carbon::parse('2018-01-16')->getCurrentDayOpeningHours()

echo '<h1>Today office open hours</h1>';
$data = $todayRanges->getData();
if (is_array($data) && isset($data['remarks'])) {
  echo '<p><em>' . $data['remarks'] . '</em></p>';
}
// $todayRanges is iterable on every time range of the day.
foreach ($todayRanges as $range) {
  // TimeRange object have start, end and data properties but can also be implicitly converted as strings:
  echo '<p><time>' . $range . '</time></p>';
}
// $todayRanges can also be directly dumped as string
echo '<p>' . $todayRanges . '</p>';

Try in the live editor

isBusinessOpen / isOpenExcludingHolidays

Allows to know if the business is usually on open at a given moment and not an holidays. But you also can handle holidays with a dedicated exception for a finest setting. See Holidays section

Carbon::setHolidaysRegion('us-national');
Carbon::isBusinessOpen()       // returns true if the business is now open and not an holiday
$carbonDate->isBusinessOpen()  // returns true if the business is open and not an holiday at the current date and time

isBusinessClosed / isClosedIncludingHolidays

Opposite of isOpenExcludingHolidays

Carbon::setHolidaysRegion('us-national');
Carbon::isBusinessClosed()       // returns true if the business is now closed or an holiday
$carbonDate->isBusinessClosed()  // returns true if the business is closed or an holiday at the current date and time

nextBusinessOpen / nextOpenExcludingHolidays

Go to next open time (considering all holidays as closed time). But prefer to handle holidays with a dedicated exception for a finest setting. See Holidays section

Carbon::setHolidaysRegion('us-national');
echo Carbon::nextBusinessOpen();
echo $carbonDate->nextBusinessOpen();

nextBusinessClose / nextCloseIncludingHolidays

Go to next closed time (considering all holidays as closed time). But prefer to handle holidays with a dedicated exception for a finest setting. See Holidays section

Carbon::setHolidaysRegion('us-national');
echo Carbon::nextBusinessClose();
echo $carbonDate->nextBusinessClose();

previousBusinessOpen / previousOpenExcludingHolidays

Go to previous open time (considering all holidays as closed time). But prefer to handle holidays with a dedicated exception for a finest setting. See Holidays section

Carbon::setHolidaysRegion('us-national');
echo Carbon::previousBusinessOpen();
echo $carbonDate->previousBusinessOpen();

previousBusinessClose / previousCloseIncludingHolidays

Go to previous closed time (considering all holidays as closed time). But prefer to handle holidays with a dedicated exception for a finest setting. See Holidays section

Carbon::setHolidaysRegion('us-national');
echo Carbon::previousBusinessClose();
echo $carbonDate->previousBusinessClose();

getCurrentOpenTimeRanges

Get list of ranges that contain the current date-time.

foreach (Carbon::getCurrentOpenTimeRanges() as $timeRange) {
  echo 'From: '.$timeRange->start().' to '.$timeRange->end()."\n";
}
foreach ($carbonDate->getCurrentOpenTimeRanges() as $timeRange) {
  echo 'From: '.$timeRange->start().' to '.$timeRange->end()."\n";
}

getCurrentOpenTimeRange

Get the first range that contain the current date-time.

$timeRange = Carbon::getCurrentOpenTimeRange();

if ($timeRange) {
  echo 'From: '.$timeRange->start().' to '.$timeRange->end()."\n";
}

$timeRange = $carbonDate->getCurrentOpenTimeRange();

if ($timeRange) {
  echo 'From: '.$timeRange->start().' to '.$timeRange->end()."\n";
}

getCurrentOpenTimeRangeStart

Get the start of the current open time range (if open, holidays ignored).

$start = Carbon::getCurrentOpenTimeRangeStart();

if ($start) {
  echo 'Open since '.$start->format('l H:i')."\n";
} else {
  echo "Closed\n";
}

$start = $carbonDate->getCurrentOpenTimeRangeStart();

if ($start) {
  echo 'Open since '.$start->format('l H:i')."\n";
} else {
   echo "Closed\n";
 }

getCurrentOpenTimeRangeEnd

Get the end of the current open time range (if open, holidays ignored).

$end = Carbon::getCurrentOpenTimeRangeEnd();

if ($end) {
  echo 'Will close at '.$start->format('l H:i')."\n";
} else {
  echo "Closed\n";
}

$end = $carbonDate->getCurrentOpenTimeRangeEnd();

if ($end) {
  echo 'Will close at '.$start->format('l H:i')."\n";
} else {
   echo "Closed\n";
 }

getCurrentBusinessTimeRangeStart

Get the start of the current open time range (if open and not holiday).

$start = Carbon::getCurrentBusinessTimeRangeStart();

if ($start) {
  echo 'Open since '.$start->format('l H:i')."\n";
} else {
  echo "Closed\n";
}

$start = $carbonDate->getCurrentBusinessTimeRangeStart();

if ($start) {
  echo 'Open since '.$start->format('l H:i')."\n";
} else {
   echo "Closed\n";
 }

getCurrentBusinessTimeRangeEnd

Get the end of the current open time range (if open and not holiday).

$end = Carbon::getCurrentBusinessTimeRangeEnd();

if ($end) {
  echo 'Will close at '.$start->format('l H:i')."\n";
} else {
  echo "Closed\n";
}

$end = $carbonDate->getCurrentBusinessTimeRangeEnd();

if ($end) {
  echo 'Will close at '.$start->format('l H:i')."\n";
} else {
   echo "Closed\n";
 }

Laravel

To enable business-time globally in Laravel, set default openning hours and holidays settings in the config file config/carbon.php (create this file if it does not exist yet):

<?php return [
  'opening-hours' => [
    'monday' => ['08:00-12:00', '14:00-19:00'],
    'wednesday' => ['09:00-19:00'],
  ],
  'holidays' => [
    'region' => 'us',
    'with' => [
      'boss-birthday' => '09-26',
      'last-monday'   => '= last Monday of October',
    ],
  ],
];

Note about timezones

When you set an holidays region, it does not change the timezone, so if January 1st is an holiday, ->isHoliday() returns true from Carbon::parse('2010-01-01 00:00:00.000000) to Carbon::parse('2010-01-01 23:59:59.999999) no matter the timezone you set for those Carbon instance.

If you want to know if it's holiday or business day in somewhere else in the world, you have to convert it:

Carbon::parse('2010-01-01 02:30', 'Europe/Paris')->setTimezone('America/Toronto')->isHoliday() // false
Carbon::parse('2010-01-01 12:30', 'Europe/Paris')->setTimezone('America/Toronto')->isHoliday() // true

The same goes for opening hours, let's say you want to know if you call center based in Toronto is available from Tokyo at a given hour (Tokyo timezone), you would get something like:

// Opening hours in Toronto
BusinessTime::enable(Carbon::class, [
  'monday' => ['08:00-20:00'],
  'tuesday' => ['08:00-20:00'],
  'wednesday' => ['08:00-20:00'],
  'thursday' => ['08:00-20:00'],
]);
// Can I call the hotline if it's Tuesday 19:30 in Tokyo? > No
Carbon::parse('2019-03-05 20:30', 'Asia/Tokyo')->setTimezone('America/Toronto')->isOpen() // false
// Can I call the hotline if it's Tuesday 22:30 in Tokyo? > Yes
Carbon::parse('2019-03-05 22:30', 'Asia/Tokyo')->setTimezone('America/Toronto')->isOpen() // true

Try in the live editor

business-time's People

Contributors

kylekatarnls avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.