Skip to content

Instantly share code, notes, and snippets.

@haykuro
Created January 9, 2026 21:53
Show Gist options
  • Select an option

  • Save haykuro/9a2aa90a24278009b684e6b7f8df4b9e to your computer and use it in GitHub Desktop.

Select an option

Save haykuro/9a2aa90a24278009b684e6b7f8df4b9e to your computer and use it in GitHub Desktop.
BusinessDateTime, a class that allows you to do simple math for business days.
<?php
class BusinessDateTime extends DateTime
{
private $holidays = []; // Array to store holidays
// Constructor
public function __construct($time = "now", DateTimeZone $timezone = null)
{
parent::__construct($time, $timezone);
$this->setDefaultHolidays(); // Preload default US holidays
}
/**
* Modify the DateTime according to business day rules.
*
* @param string $modifier The modifier string (e.g., "+2 business days").
* @return DateTime|false
*/
public function modify(string $modifier): DateTime|false
{
if (preg_match('/^([\+\-]?\d+)\s*business days?$/i', $modifier, $matches)) {
return $this->addBusinessDays((int)$matches[1]);
}
return parent::modify($modifier);
}
/**
* Add business days to the current date.
*
* @param int $businessDays The number of business days to add (can be negative).
* @return $this
*/
private function addBusinessDays(int $businessDays): self
{
$direction = $businessDays > 0 ? 1 : -1;
$absDays = abs($businessDays);
while ($absDays > 0) {
$this->modify(($direction === 1 ? '+1 day' : '-1 day'));
if ($this->isBusinessDay()) {
$absDays--;
}
}
return $this;
}
/**
* Check if the current date is a business day.
*
* @return bool
*/
private function isBusinessDay(): bool
{
// Check if the current day is a weekend
if (in_array($this->format('N'), [6, 7])) {
return false;
}
// Check if the current date is a holiday
if ($this->isHoliday()) {
return false;
}
return true;
}
/**
* Check if the current date is a holiday.
*
* @return bool
*/
private function isHoliday(): bool
{
$year = (int)$this->format('Y');
$month = (int)$this->format('n');
$day = (int)$this->format('j');
// Define holidays using rules instead of fixed dates
return $this->checkFixedHolidays($year, $month, $day) ||
$this->checkVariableHolidays($year, $month, $day);
}
/**
* Define fixed holidays.
*/
private function checkFixedHolidays($year, $month, $day): bool
{
$fixedHolidays = [
'01-01', // New Year's Day
'07-04', // Independence Day
'11-11', // Veterans Day
'12-25', // Christmas Day
];
return in_array(sprintf('%02d-%02d', $month, $day), $fixedHolidays);
}
/**
* Define variable holidays.
*/
private function checkVariableHolidays($year, $month, $day): bool
{
// Variable holidays logic
// Note: This is simplified and may require adjustments for holiday observances
// Martin Luther King Jr. Day (Third Monday of January)
if ($month === 1 && $day >= 15 && $this->format('N') == 1) {
return true;
}
// Presidents' Day (Third Monday of February)
if ($month === 2 && $day >= 15 && $this->format('N') == 1) {
return true;
}
// Memorial Day (Last Monday of May)
if ($month === 5 && $day > 24 && $this->format('N') == 1) {
$lastMonday = (int)$this->format('j') - ((int)$this->format('j') % 7);
return $lastMonday === 31;
}
// Labor Day (First Monday of September)
if ($month === 9 && $day <= 7 && $this->format('N') == 1) {
return true;
}
// Columbus Day (Second Monday of October)
if ($month === 10 && $day >= 8 && $this->format('N') == 1) {
return true;
}
// Thanksgiving Day (Fourth Thursday of November)
if ($month === 11 && $day >= 22 && $this->format('N') == 4) {
return true;
}
return false;
}
/**
* Set the holidays for the current object.
*
* @param array $holidays Array of holiday dates in 'Y-m-d' format.
*/
public function setHolidays(array $holidays): void
{
$this->holidays = $holidays; // This method isn't strictly necessary anymore
}
/**
* Retrieve current holidays.
*
* @return array
*/
public function getHolidays(): array
{
return $this->holidays; // This method isn't strictly necessary anymore
}
/**
* Set default holidays for the US.
*/
private function setDefaultHolidays(): void
{
// The default holidays will be handled in the isHoliday check
}
}
<?php
require_once __DIR__ . '/businessdatetime.php';
$businessDateTime = new BusinessDateTime();
echo $businessDateTime->format('Y-m-d'); // Current date
$businessDateTime->modify('+12 business days');
echo $businessDateTime->format('Y-m-d'); // 12 business days later
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment