PHP code example of vesselind / working-days-calculator
1. Go to this page and download the library: Download vesselind/working-days-calculator library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
vesselind / working-days-calculator example snippets
$result = (new \Vesselind\WorkingDaysCalculator\Calculator\WorkingDaysCalculator())->workingDaysInMonth(2026, 5);
echo $result->workingDays; // 18
use Vesselind\WorkingDaysCalculator\Calculator\WorkingDaysCalculator;
$calculator = new WorkingDaysCalculator();
$result = $calculator->workingDaysInMonth(2026, 5); // May 2026
echo $result->workingDays; // 18
$result->totalCalendarDays; // 31 (May has 31 days)
$result->weekendDays; // int — Saturdays + Sundays
$result->publicHolidayDays; // int — all non-weekend holidays in May
$result->holidays; // Holiday[] — each holiday with date, name, type
use Vesselind\WorkingDaysCalculator\Model\WorkPeriod;
use Carbon\CarbonImmutable;
$period = new WorkPeriod(
startDate: new CarbonImmutable('2025-12-15'),
endDate: new CarbonImmutable('2026-01-15'),
);
$result = $calculator->workingDaysInPeriod($period);
echo $result->workingDays;
// Hours in a month
$hours = $calculator->workingHoursInMonth(2025, 1); // January 2025
echo $hours->totalWorkingHours; // workingDays × 8
// Hours in a year
$hours = $calculator->workingHoursInYear(2025);
echo $hours->totalWorkingHours;
// Hours in a custom period
$hours = $calculator->workingHoursInPeriod($period);
echo $hours->workingDays;
echo $hours->hoursPerDay; // 8 (default)
use Vesselind\WorkingDaysCalculator\Model\HolidayType;
$holidays = $calculator->holidaysInPeriod($period); // Holiday[]
foreach ($holidays as $holiday) {
echo $holiday->date->toDateString(); // e.g., 2025-01-01
echo $holiday->name; // Нова година
echo $holiday->type->value; // 'fixed' | 'compensation' | 'orthodox_easter' | 'government_announced'
}
// Filter: only Easter holidays
$easterHolidays = array_filter(
$holidays,
fn($h) => $h->type === HolidayType::OrthodoxEaster
);
use Carbon\CarbonImmutable;
$calculator = new WorkingDaysCalculator(
governmentDaysOff: [
new CarbonImmutable('2026-01-02'), // Bridge day announced by decree
]
);
$result = $calculator->workingDaysInMonth(2026, 1);
// January 2026 working days decreased by 1 for the injected day
// Safe to inject a date that is already a public holiday:
// it is deduplicated automatically — no double-counting.
use Vesselind\WorkingDaysCalculator\Calculator\EasterCalculator;
use Carbon\CarbonImmutable;
$easter = new EasterCalculator();
$easterSunday = $easter->forYear(2025); // CarbonImmutable: 2025-04-20
$goodFriday = $easterSunday->subDays(2); // 2025-04-18
$holySaturday = $easterSunday->subDays(1); // 2025-04-19
$easterMonday = $easterSunday->addDays(1); // 2025-04-21
use Vesselind\WorkingDaysCalculator\Calculator\DeadlineCalculator;
use Vesselind\WorkingDaysCalculator\Model\TermUnit;
use Carbon\CarbonImmutable;
$deadlineCalc = new DeadlineCalculator(new WorkingDaysCalculator());
$startDate = new CarbonImmutable('2025-01-01');
// 1-month term
$deadline = $deadlineCalc->calculate($startDate, TermUnit::Month, 1);
echo $deadline->rawExpiry->toDateString(); // 2025-02-01
echo $deadline->resolvedExpiry->toDateString(); // next working day if 2025-02-01 is non-working
// 30-day term (counts from day after start date)
$deadline = $deadlineCalc->calculate($startDate, TermUnit::Day, 30);
echo $deadline->resolvedExpiry->toDateString();
// 1-year term from leap day
$deadline = $deadlineCalc->calculate(
new CarbonImmutable('2024-02-29'), // leap year
TermUnit::Year,
1
);
echo $deadline->rawExpiry->toDateString(); // 2025-02-28 (Feb has no 29th in 2025)
use Vesselind\WorkingDaysCalculator\Exception\InvalidDateRangeException;
use Vesselind\WorkingDaysCalculator\Model\WorkPeriod;
use Carbon\CarbonImmutable;
try {
$period = new WorkPeriod(
startDate: new CarbonImmutable('2025-05-31'),
endDate: new CarbonImmutable('2025-05-01'), // end < start
);
} catch (InvalidDateRangeException $e) {
echo $e->getMessage();
// "End date 2025-05-01 must be on or after start date 2025-05-31"
}
use Vesselind\WorkingDaysCalculator\Calculator\ZzdDeadlineCalculator;
use Vesselind\WorkingDaysCalculator\Calculator\WorkingDaysCalculator;
use Vesselind\WorkingDaysCalculator\Model\MonthAnchor;
use Vesselind\WorkingDaysCalculator\Model\TermUnit;
use Carbon\CarbonImmutable;
$calc = new ZzdDeadlineCalculator(new WorkingDaysCalculator());
// Forward term — 1 month (start day is NOT counted per art. 72 §2)
$deadline = $calc->calculate(new CarbonImmutable('2025-01-31'), TermUnit::Month, 1);
echo $deadline->rawExpiry->toDateString(); // 2025-02-28 (Feb has no 31st)
echo $deadline->resolvedExpiry->toDateString(); // first following working day if non-working
// Forward term — 30 days
$deadline = $calc->calculate(new CarbonImmutable('2025-01-01'), TermUnit::Day, 30);
echo $deadline->rawExpiry->toDateString(); // 2025-01-31
// Forward term — 2 weeks (expires on same weekday)
$deadline = $calc->calculate(new CarbonImmutable('2025-01-01'), TermUnit::Week, 2);
echo $deadline->rawExpiry->toDateString(); // 2025-01-15 (same weekday, 2 weeks later)
// Backward term — art. 72 §3: 3 days BEFORE a known date
// Neither the target day nor the expiry day is counted
$deadline = $calc->calculateBackward(new CarbonImmutable('2026-01-10'), 3);
echo $deadline->rawExpiry->toDateString(); // 2026-01-06 (Jan 7, 8, 9 = 3 days strictly between)
echo $deadline->resolvedExpiry->toDateString(); // advanced if non-working
// Month anchors — art. 72 §5
$date = new CarbonImmutable('2025-02-10');
echo $calc->resolveMonthAnchor($date, MonthAnchor::Beginning)->toDateString(); // 2025-02-01
echo $calc->resolveMonthAnchor($date, MonthAnchor::Middle)->toDateString(); // 2025-02-15
echo $calc->resolveMonthAnchor($date, MonthAnchor::End)->toDateString(); // 2025-02-28
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.