Calendar
Available versions:
Installation
composer require aeon-php/calendar
Getting Started
To get current time initialize GregorianCalendar through __construct or by one of available static constructors.
<?php
use Aeon\Calendar\Gregorian\GregorianCalendar;
echo GregorianCalendar::UTC()->now()->toISO8601();
GregorianCalendar implements Calendar interface which should be used for type hinting.
Initializing DateTime
Initialization time from string
is just as easy as using \DateTime
or \DateTimeInterface
.
Just take the string
and pass it to fromString
static constructor.
<?php
use Aeon\Calendar\Gregorian\DateTime;
echo DateTime::fromString('2020-01-01 00:00:00 UTC')->toISO8601();
Defining period of time
There are few ways to define period of time, it can be done by initializing two DateTime instances and creating time period since one date until another.
<?php
use Aeon\Calendar\Gregorian\DateTime;
$newYear = DateTime::fromString('2020-01-01 00:00:00 UTC');
$timePeriod = $newYear->until(
DateTime::fromString('2020-01-10 00:00:00 UTC')
);
Iterating over time
TimePeriod is the very first step to iterate over time. In following example we are going to iterate between two points in time by 24 hours periods. Iterate method generates instance of TimePeriods which is collection of TimePeriod instances representing chunks of time between two points.
<?php
use Aeon\Calendar\Gregorian\DateTime;
$newYear = DateTime::fromString('2020-01-01 00:00:00 UTC');
$newYear->until(
DateTime::fromString('2020-01-10 00:00:00 UTC')
)->iterate(TimeUnit::day())
->each(function(TimePeriod $timePeriod) : void {
var_dump(
$timePeriod->start()->toISO8601(),
$timePeriod->end()->toISO8601(),
$timePeriod->distance()->inHours()
);
});
Measure elapsed time
It might look tempting to use measuring difference between two points in time to measure elapsed time but if you are looking for precise results use Stopwatch class instead which is built on top of \hrtime high resolution time php function.
<?php
use Aeon\Calendar\Stopwatch;
use Aeon\Calendar\TimeUnit;
$stopwatch = new Stopwatch();
$stopwatch->start();
\usleep(TimeUnit::milliseconds(500)->microsecond());
$stopwatch->lap();
\usleep(TimeUnit::milliseconds(700)->microsecond());
$stopwatch->stop();
var_dump($stopwatch->elapsedTime(1)->inSecondsPrecise());
var_dump($stopwatch->firstLapElapsedTime()->inSecondsPrecise());
var_dump($stopwatch->lastLapElapsedTime()->inSecondsPrecise());
var_dump($stopwatch->elapsedTime(2)->inSecondsPrecise());
var_dump($stopwatch->totalElapsedTime()->inSecondsPrecise());
Relative format interface
PHP DateTime Relative Formats are powerful and flexible, Aeon brings similar experience through object oriented API.
<?php
use Aeon\Calendar\Gregorian\GregorianCalendar;
use Aeon\Calendar\TimeUnit;
$calendar = GregorianCalendar::UTC();
$calendar->currentYear()
->january()
->lastDay()
->noon($calendar->timeZone())
->sub(TimeUnit::days(3));
Day Value Set - Collection
One of the most common use cases is to assign values into given days and then filter/map/sum/split this collection.
Let say one would like to calculate average sales from last 10 days knowing there is a gap
in sales. Following example explains how to do define DayValueSet
and work on it.
<?php
use Aeon\Calendar\Gregorian\Day;
use Aeon\Collection\DayValue;
use Aeon\Collection\DayValueSet;
$initialSet = DayValueSet::createWith(
Day::fromString('-10 days'),
Day::fromString('yesterday'),
$initialValue = 0
);
// Fetch those values from database or any other source
$sales = [
new DayValue(Day::fromString('-1 day'), 100),
new DayValue(Day::fromString('-2 day'), 150),
new DayValue(Day::fromString('-3 day'), 125),
// Day 4 business was closed, no sales
new DayValue(Day::fromString('-5 day'), 180),
new DayValue(Day::fromString('-6 day'), 100),
new DayValue(Day::fromString('-7 day'), 108),
new DayValue(Day::fromString('-8 day'), 100),
new DayValue(Day::fromString('-9 day'), 150),
new DayValue(Day::fromString('-10 day'), 130),
];
$salesSet = $initialSet->put(...$sales)->sortDescending();
$totalSales = $salesSet->reduce(
fn(int $total, DayValue $dayValue) : int => $dayValue->value() + $total, 0
);
$T10AvgSales = floor($totalSales / $salesSet->count());
/**
2020-10-08 - 100
2020-10-07 - 150
2020-10-06 - 125
2020-10-05 - 0
2020-10-04 - 180
2020-10-03 - 100
2020-10-02 - 108
2020-10-01 - 100
2020-09-30 - 150
2020-09-29 - 130
---
AVG Sales: 114
*/