District5 Date Library
A fluent, intuitive PHP wrapper around DateTime — zero dependencies, PHP 8.1+.
Installation
Install via Composer:
composer require district5/date
All functionality is accessed through the District5\Date\Date facade class using static methods.
use District5\Date\Date;
Quick Start
use District5\Date\Date;
// Get current time in UTC
$now = Date::nowUtc();
// Add 3 days
$future = Date::modify($now)->plus()->days(3);
// Format the result
echo Date::output($future)->toYMD(); // e.g. 2026-04-02
// How many days until then?
echo Date::diff($now)->days($future); // 3
Getting the Current Time
Use Date::now() to obtain a NowTimezone helper, or the convenience shortcuts for the most common cases.
Convenience shortcuts
use District5\Date\Date;
// Current time in the server's default timezone as a DateTime
$default = Date::nowDefault();
// Current time in UTC
$utc = Date::nowUtc();
// Current Unix timestamp (int)
$ts = Date::time();
// Current microtime as float or string
$float = Date::microtime(true); // float
$string = Date::microtime(false); // string
NowTimezone — named timezone shortcuts
$now = Date::now();
$utc = $now->utc(); // UTC
$london = $now->london(); // Europe/London
$eastern = $now->eastern(); // America/New_York
$central = $now->central(); // America/Chicago
$pacific = $now->pacific(); // America/Los_Angeles
$default = $now->default(); // Server default timezone
// Any IANA timezone string
$tokyo = $now->inTimezone('Asia/Tokyo');
// From a UTC offset string (e.g. +0100, -0500)
$offset = $now->fromOffset('+0200');
Creating DateTimes
From year / month / day components
use District5\Date\Date;
// Date only (time defaults to 00:00:00)
$date = Date::createYMDHISM(2026, 1, 15);
// Date + time
$datetime = Date::createYMDHISM(2026, 1, 15, 14, 30, 0);
// Date + time + microseconds + timezone
$dt = Date::createYMDHISM(2026, 1, 15, 14, 30, 0, 500000, 'America/New_York');
Unix epoch
// Returns a DateTime set to 1970-01-01 00:00:00 UTC
$epoch = Date::epoch();
From a string (auto-detect common formats)
$dt = Date::fromString('2026-03-30 14:30:00'); // DateTime or false
Calculate someone's age
$dob = Date::createYMDHISM(1990, 6, 15);
$age = Date::age($dob); // int — full years since the given date
Parsing Strings & Timestamps
Use Date::input($value) to wrap a string, integer, or float and then call the relevant parser. All methods return DateTime|false.
Date-only strings
use District5\Date\Date;
$dt = Date::input('2026-03-30')->fromYMD(); // default separator '-'
$dt = Date::input('2026/03/30')->fromYMD('/');
$dt = Date::input('30-03-2026')->fromDMY(); // DD-MM-YYYY
$dt = Date::input('03-30-2026')->fromMDY(); // MM-DD-YYYY
Date + time strings
$dt = Date::input('2026-03-30 14:30:00')->fromYMDHIS();
// Custom separators
$dt = Date::input('2026/03/30 14:30:00')->fromYMDHIS('/', ':');
ISO 8601
$dt = Date::input('2026-03-30T14:30:00+0000')->fromISO8601();
Unix timestamps
$dt = Date::input(1743340200)->fromUnixTimestamp();
$dt = Date::input(1743340200)->fromTimestamp(); // alias
Millisecond & microsecond timestamps
$dt = Date::input(1743340200123)->fromMillisecondTimestamp();
$dt = Date::input(1743340200123456)->fromMicrosecondTimestamp();
Custom format
$dt = Date::input('30/03/2026')->fromFormat('d/m/Y');
$dt = Date::input('March 30, 2026')->fromFormat('F j, Y');
Formatting Output
Use Date::output($dateTime) to wrap a DateTime and extract components or formatted strings.
Extract date/time components
use District5\Date\Date;
$dt = Date::createYMDHISM(2026, 3, 30, 14, 30, 45);
$out = Date::output($dt);
$out->getYear(); // 2026
$out->getMonth(); // 3
$out->getDay(); // 30
$out->getWeek(); // ISO week number, e.g. 14
$out->getDayOfWeek(); // 1 (Mon) – 7 (Sun)
$out->getDayName(); // "Monday"
$out->getMonthName(); // "March"
$out->getDaySuffix(); // "th" (st / nd / rd / th)
$out->getHour(); // 14
$out->getMinutes(); // 30
$out->getSeconds(); // 45
$out->getMicroseconds(); // 0
$out->getMilliseconds(); // 0
Date format strings
$out->toYMD(); // "2026-03-30"
$out->toYMD(true, '/'); // "2026/03/30"
$out->toYMD(false); // "20260330"
$out->toDMY(); // "30-03-2026"
$out->toMDY(); // "03-30-2026"
$out->toYMDHIS(); // "2026-03-30 14:30:45"
Time format strings
$out->toTimeHM(); // "14:30"
$out->toTimeHMS(); // "14:30:45"
$out->getHourMinutes(); // "14:30" (alias)
$out->getHourMinutesSeconds(); // "14:30:45" (alias)
ISO 8601 & custom formats
$out->toISO8601(); // "2026-03-30T14:30:45+0000"
$out->toFormat('l, F j Y'); // "Monday, March 30 2026" (any PHP date format)
Timestamps
$out->toUnixTimestamp(); // int
$out->toUnixTimestamp(true); // string
$out->toTimestamp(); // int (alias)
$out->toMillisecondTimestamp(); // float e.g. 1743340245.000
$out->toMicrosecondTimestamp(); // float e.g. 1743340245.000000
Modify
Date::modify($dt) returns a Modify object. By default it clones the DateTime so the original is untouched. Pass false as the second argument to mutate in place.
Set date or time components
use District5\Date\Date;
$dt = Date::createYMDHISM(2026, 3, 30, 14, 30, 0);
// Change only specific date parts (pass null to leave unchanged)
$new = Date::modify($dt)->setDate(1, null, 2027); // day=1, same month, year=2027
// Change time
$new = Date::modify($dt)->setTime(9, 0); // 09:00:00
$new = Date::modify($dt)->setTime(9, 0, 30, 0); // 09:00:30.000000
// Set individual time components
$new = Date::modify($dt)->setHours(23);
$new = Date::modify($dt)->setMinutes(59);
$new = Date::modify($dt)->setSeconds(0);
$new = Date::modify($dt)->setMicroseconds(500000);
Free-form string modification
// Same syntax as PHP's DateTime::modify()
$new = Date::modify($dt)->withString('+5 days');
$new = Date::modify($dt)->withString('next Friday');
$new = Date::modify($dt)->withString('last day of this month');
Mutate in place
// $dt itself is modified, no clone
Date::modify($dt, false)->setHours(0);
Adding Time
Access addition via Date::modify($dt)->plus() (returns DateTime|false) or the chainable fluid API via Date::modify($dt)->plusFluid().
Single additions
use District5\Date\Date;
$dt = Date::nowUtc();
Date::modify($dt)->plus()->microseconds(500);
Date::modify($dt)->plus()->milliseconds(500);
Date::modify($dt)->plus()->seconds(30);
Date::modify($dt)->plus()->minutes(15);
Date::modify($dt)->plus()->hours(2);
Date::modify($dt)->plus()->hoursAndMinutes(1, 30);
Date::modify($dt)->plus()->hoursAndMinutesAndSeconds(1, 30, 15);
Date::modify($dt)->plus()->days(7);
Date::modify($dt)->plus()->weeks(2);
Date::modify($dt)->plus()->months(3);
Date::modify($dt)->plus()->years(1);
Date::modify($dt)->plus()->decades(1);
Date::modify($dt)->plus()->centuries(1);
Date::modify($dt)->plus()->millennia(1);
// Aliases — add() and addFluid() work identically
Date::modify($dt)->add()->days(3);
Chainable (fluid) additions
$result = Date::modify($dt)
->plusFluid()
->years(1)
->months(2)
->days(10)
->hours(3)
->minutes(30)
->seconds(0)
->getDateTime(); // returns the final DateTime
Subtracting Time
Mirror of the addition API. Use ->minus() / ->subtract() / ->sub() for single steps, or ->minusFluid() / ->subtractFluid() / ->subFluid() for chaining.
Single subtractions
use District5\Date\Date;
$dt = Date::nowUtc();
Date::modify($dt)->minus()->microseconds(500);
Date::modify($dt)->minus()->milliseconds(500);
Date::modify($dt)->minus()->seconds(30);
Date::modify($dt)->minus()->minutes(15);
Date::modify($dt)->minus()->hours(2);
Date::modify($dt)->minus()->hoursAndMinutes(1, 30);
Date::modify($dt)->minus()->hoursAndMinutesAndSeconds(1, 30, 15);
Date::modify($dt)->minus()->days(7);
Date::modify($dt)->minus()->weeks(2);
Date::modify($dt)->minus()->months(3);
Date::modify($dt)->minus()->years(1);
Date::modify($dt)->minus()->decades(1);
Chainable (fluid) subtractions
$result = Date::modify($dt)
->minusFluid()
->years(1)
->months(6)
->days(15)
->getDateTime();
Differences Between Dates
Date::diff($dateTime) returns a Diff object. Pass a second DateTime to each method to compute the absolute difference as complete units.
use District5\Date\Date;
$start = Date::createYMDHISM(2020, 1, 1);
$end = Date::createYMDHISM(2026, 3, 30);
$diff = Date::diff($start);
$diff->milliseconds($end); // int — total ms difference
$diff->seconds($end);
$diff->minutes($end);
$diff->hours($end);
$diff->days($end);
$diff->weeks($end);
$diff->months($end);
$diff->years($end); // 6
$diff->decades($end);
$diff->centuries($end);
$diff->millennia($end);
Calendar Calculations
Date::calculate($dateTime) returns a Calculate object for the given date.
Days in a month
use District5\Date\Date;
$dt = Date::createYMDHISM(2026, 2, 10);
$calc = Date::calculate($dt);
$calc->numberDaysInMonth(); // 28 (Feb 2026 — not a leap year)
$calc->numberDaysLeftInMonth(); // 18 (days remaining in Feb after the 10th)
// Static helpers — no DateTime required
use District5\Date\Calculators\Calculate;
Calculate::numberDaysInMonthByGivenValues(2, 2024); // 29 (leap year)
Calculate::numberDaysLeftInMonthByGivenValues(10, 2, 2026); // 18
Comparison helpers
$earlier = Date::createYMDHISM(2024, 1, 1);
$later = Date::createYMDHISM(2026, 1, 1);
$calc = Date::calculate($earlier);
$calc->isOlderThan($later); // true
$calc->isNewerThan($later); // false
$calc->isOlderThanOrEqualTo($later); // true
$calc->isNewerThanOrEqualTo($later); // false
// Hours / minutes / seconds between two dates (absolute)
$calc->hours($later); // int
$calc->minutes($later); // int
$calc->seconds($later); // int
Validating DateTime Objects
Date::validateObject($dateTime) returns a DateTimeValidator with boolean query methods.
Time of day
use District5\Date\Date;
$dt = Date::createYMDHISM(2026, 3, 30, 9, 0, 0);
$v = Date::validateObject($dt);
$v->isAM(); // true
$v->isPM(); // false
Day of week
$v->isMonday(); $v->isTuesday(); $v->isWednesday();
$v->isThursday(); $v->isFriday(); $v->isSaturday(); $v->isSunday();
// Generic (1 = Monday … 7 = Sunday)
$v->isDayOfWeekX(5); // true if Friday
Month
$v->isJanuary(); $v->isFebruary(); $v->isMarch();
$v->isApril(); $v->isMay(); $v->isJune();
$v->isJuly(); $v->isAugust(); $v->isSeptember();
$v->isOctober(); $v->isNovember(); $v->isDecember();
// Generic (1 = January … 12 = December)
$v->isMonthNumberX(3); // true if March
Relative to today
$v->isYesterday(); // true if date is yesterday
$v->isToday(); // true if date is today
$v->isTomorrow(); // true if date is tomorrow
Leap year & comparisons
$v->isLeapYear(); // true/false
$other = Date::createYMDHISM(2020, 1, 1);
$v->isOlderThan($other);
$v->isNewerThan($other);
$v->isOlderThanOrEqualTo($other);
$v->isNewerThanOrEqualTo($other);
$v->isHourLessThan(12); // true if hour < 12
$v->isHourGreaterThan(8); // true if hour > 8
Validating Strings
Date::validateString($input) returns a StringFormatValidator that checks whether the string can be parsed as various date formats.
use District5\Date\Date;
$v = Date::validateString('2026-03-30');
$v->isValidYMD(); // true (YYYY-MM-DD)
$v->isValidDMY(); // false (DD-MM-YYYY)
$v->isValidMDY(); // false (MM-DD-YYYY)
$v->isValidYMDHIS(); // false (YYYY-MM-DD HH:MM:SS)
$v->isValidISO8601(); // false
$v->isValidUnixTimestamp(); // false
$v->isValidMillisecondTimestamp(); // false
$v->isValidMicrosecondTimestamp(); // false
Validating Arrays of DateTimes
Date::validateArray($dateTimes) returns a DateTimesValidator that works over a collection.
use District5\Date\Date;
$dates = [
Date::createYMDHISM(2026, 1, 1),
Date::createYMDHISM(2026, 6, 15),
Date::createYMDHISM(2025, 12, 25),
];
$v = Date::validateArray($dates);
$v->allAreValid(); // true — all elements are DateTime instances
$v->hasAny(); // true — array is non-empty
$v->count(); // 3
Timezones
Convert DateTime objects between timezones using Date::timezone($dt).
Convert to a timezone
use District5\Date\Date;
use District5\Date\Tz\TzConstants;
$utc = Date::nowUtc();
$tz = Date::timezone($utc);
// Using an IANA string
$ny = $tz->toTimezone('America/New_York');
// Using TzConstants
$london = $tz->toTimezone(TzConstants::EUROPE_LONDON);
Convert from one timezone to another
// Convert a DateTime that is in Europe/London to America/New_York
$converted = Date::timezone($dt)->toTimezoneFromTimezone(
TzConstants::AMERICA_NEW_YORK, // to
TzConstants::EUROPE_LONDON // from (optional, uses $dt's tz if omitted)
);
Selected TzConstants
| Constant | Value |
|---|---|
TzConstants::UTC | UTC |
TzConstants::EUROPE_LONDON | Europe/London |
TzConstants::EUROPE_PARIS | Europe/Paris |
TzConstants::AMERICA_NEW_YORK | America/New_York |
TzConstants::AMERICA_CHICAGO | America/Chicago |
TzConstants::AMERICA_LOS_ANGELES | America/Los_Angeles |
TzConstants::ASIA_TOKYO | Asia/Tokyo |
TzConstants::AUSTRALIA_SYDNEY | Australia/Sydney |
TzConstants covers all standard IANA timezones. Use your IDE's autocomplete to browse the full list.Sorting
Use Date::sorter() to sort arrays of DateTime objects or find extremes.
use District5\Date\Date;
$a = Date::createYMDHISM(2025, 6, 1);
$b = Date::createYMDHISM(2024, 1, 15);
$c = Date::createYMDHISM(2026, 12, 31);
$sorter = Date::sorter();
// Sort — variadic arguments
$asc = $sorter->sortOldestToNewest($a, $b, $c); // [$b, $a, $c]
$desc = $sorter->sortNewestToOldest($a, $b, $c); // [$c, $a, $b]
// Find the oldest / newest from an array
$oldest = $sorter->oldest([$a, $b, $c]); // $b (Jan 2024)
$newest = $sorter->newest([$a, $b, $c]); // $c (Dec 2026)
Month Helpers
Use Date::month() to query information about months.
First and last day of a month
use District5\Date\Date;
$month = Date::month();
// By month number (and optional year — defaults to current year)
$first = $month->firstDateInMonth(3, 2026); // 2026-03-01 00:00:00
$last = $month->lastDateInMonth(3, 2026); // 2026-03-31 00:00:00
// From a DateTime
$dt = Date::createYMDHISM(2026, 2, 15);
$first = $month->firstDateInMonthFromDateTime($dt); // 2026-02-01
$last = $month->lastDateInMonthFromDateTime($dt); // 2026-02-28
// For the current month
$first = $month->firstDateInCurrentMonth();
$last = $month->lastDateInCurrentMonth();
Number of days in a month
$month->numberDaysInMonth(2, 2024); // 29 (leap year)
$month->numberDaysInMonth(2, 2026); // 28
$dt = Date::createYMDHISM(2026, 2, 1);
$month->numberDaysInMonthFromDateTime($dt); // 28
Start & End of Periods
Use Date::startAndEnd() to obtain boundary DateTimes for days, months, and years.
Day boundaries
use District5\Date\Date;
$se = Date::startAndEnd();
// 2026-03-30 00:00:00
$start = $se->startOfDayFromYearMonthDay(2026, 3, 30);
// 2026-03-30 23:59:59
$end = $se->endOfDayFromYearMonthDay(2026, 3, 30);
// From a DateTime
$dt = Date::createYMDHISM(2026, 3, 30, 14, 0, 0);
$start = $se->startOfDayFromDateTime($dt);
$end = $se->endOfDayFromDateTime($dt);
// Today / yesterday / tomorrow shortcuts
$se->startOfToday(); $se->endOfToday();
$se->startOfYesterday(); $se->endOfYesterday();
$se->startOfTomorrow(); $se->endOfTomorrow();
Month boundaries
// 2026-03-01 00:00:00
$start = $se->startOfMonthFromYearMonth(2026, 3);
// 2026-03-31 23:59:59
$end = $se->endOfMonthFromYearMonth(2026, 3);
// From a DateTime
$start = $se->startOfMonthFromDateTime($dt);
$end = $se->endOfMonthFromDateTime($dt);
Year boundaries
// 2026-01-01 00:00:00
$start = $se->startOfYearFromYear(2026);
// 2026-12-31 23:59:59
$end = $se->endOfYearFromYear(2026);
// From a DateTime
$start = $se->startOfYearFromDateTime($dt);
$end = $se->endOfYearFromDateTime($dt);
Recurring Dates
Use Date::recurring() to work with fixed annual dates. Each helper returns a RecurringDateManipulator.
Available dates
| Method | Date |
|---|---|
newYearsDay() | January 1st |
newYearsEve() | December 31st |
valentinesDay() | February 14th |
stDwynwensDay() | January 25th |
christmasEve() | December 24th |
christmasDay() | December 25th |
boxingDay() | December 26th |
starWarsDay() | May 4th |
RecurringDateManipulator methods
use District5\Date\Date;
$christmas = Date::recurring()->christmasDay();
$christmas->thisYear(); // 2026-12-25 00:00:00
$christmas->nextYear(); // 2027-12-25 00:00:00
$christmas->getNext(); // next upcoming occurrence (this or next year)
$christmas->getPrevious(); // most recent past occurrence
Example — how many days until Christmas?
$nextXmas = Date::recurring()->christmasDay()->getNext();
$today = Date::nowUtc();
$days = Date::diff($today)->days($nextXmas);
echo "Christmas is in {$days} days.";
MongoDB Integration
Requires the mongodb/mongodb PHP extension. Use Date::mongo() to convert between PHP DateTime and MongoDB BSON types.
UTCDateTime
use District5\Date\Date;
$dt = Date::nowUtc();
$mongo = Date::mongo();
// DateTime → MongoDB\BSON\UTCDateTime
$bson = $mongo->convertTo($dt);
// MongoDB\BSON\UTCDateTime → DateTime
$dt = $mongo->convertFrom($bson);
ObjectId
// DateTime → MongoDB\BSON\ObjectId (timestamp-seeded)
$objectId = $mongo->toObjectId($dt);
// MongoDB\BSON\ObjectId → DateTime (extracts creation timestamp)
$dt = $mongo->fromObjectId($objectId);
Parsing from InputFormatter
// If you have a raw UTCDateTime or ObjectId as a variable $raw:
$dt = Date::input($raw)->fromMongoUtcDateTime($raw);
$dt = Date::input($raw)->fromMongoObjectId($raw);
NTP Server
Retrieve the current time from a Network Time Protocol server using Date::ntpServer(). Requires the ext-sockets PHP extension.
use District5\Date\Date;
$ntp = Date::ntpServer();
// Fetch Unix timestamp from pool.ntp.org (default)
$timestamp = $ntp->getUnixTimestamp(); // int|false
// Fetch from a custom NTP server
$timestamp = $ntp->getUnixTimestamp('time.google.com');
// Convert directly to a DateTime
$dt = $ntp->getDateTime(); // DateTime|false
$dt = $ntp->getDateTime('time.cloudflare.com');