Showing preview only (497K chars total). Download the full file or copy to clipboard to get everything.
Repository: aeon-php/calendar
Branch: 1.x
Commit: fe51e9e0e676
Files: 90
Total size: 465.9 KB
Directory structure:
gitextract_0agqa1a6/
├── .gitattributes
├── .github/
│ └── workflows/
│ └── readonly.yaml
├── .gitignore
├── README.md
├── benchmark/
│ └── Aeon/
│ └── Calendar/
│ └── Benchmark/
│ └── Gregorian/
│ ├── DateTimeFormatBench.php
│ ├── DateTimeInitBench.php
│ ├── DateTimeUnixTimestampBench.php
│ ├── DayIterationBench.php
│ ├── TimeUnitInitBench.php
│ └── TimeZoneInitBench.php
├── composer.json
├── phpbench.json
├── src/
│ └── Aeon/
│ ├── Calculator/
│ │ ├── BCMathCalculator.php
│ │ ├── Calculator.php
│ │ ├── Exception/
│ │ │ ├── Exception.php
│ │ │ └── InvalidTypeException.php
│ │ ├── PHPCalculator.php
│ │ └── PreciseCalculator.php
│ └── Calendar/
│ ├── Exception/
│ │ ├── Exception.php
│ │ └── InvalidArgumentException.php
│ ├── Gregorian/
│ │ ├── Calendar.php
│ │ ├── DateTime.php
│ │ ├── DateTimeIntervalIterator.php
│ │ ├── DateTimeIterator.php
│ │ ├── Day/
│ │ │ └── WeekDay.php
│ │ ├── Day.php
│ │ ├── Days.php
│ │ ├── DaysIterator.php
│ │ ├── GregorianCalendar.php
│ │ ├── GregorianCalendarStub.php
│ │ ├── Interval.php
│ │ ├── LeapSecond.php
│ │ ├── LeapSeconds.php
│ │ ├── Month.php
│ │ ├── MonthDays.php
│ │ ├── Months.php
│ │ ├── MonthsIterator.php
│ │ ├── Psr20CalendarAdapter.php
│ │ ├── Quarter.php
│ │ ├── Time.php
│ │ ├── TimeEpoch.php
│ │ ├── TimePeriod.php
│ │ ├── TimePeriods.php
│ │ ├── TimePeriodsIterator.php
│ │ ├── TimePeriodsSort.php
│ │ ├── TimeZone/
│ │ │ └── TimeOffset.php
│ │ ├── TimeZone.php
│ │ ├── Year.php
│ │ ├── YearMonths.php
│ │ └── Years.php
│ ├── RelativeTimeUnit.php
│ ├── Stopwatch.php
│ ├── TimeUnit/
│ │ └── HRTime.php
│ ├── TimeUnit.php
│ └── Unit.php
└── tests/
└── Aeon/
├── Calculator/
│ └── Tests/
│ └── Unit/
│ ├── BCMathCalculatorTest.php
│ ├── PHPCalculatorTest.php
│ └── PreciseCalculatorTest.php
└── Calendar/
└── Tests/
├── Functional/
│ └── Gregorian/
│ └── GregorianCalendarTest.php
└── Unit/
├── Gregorian/
│ ├── DateTimeIntervalIteratorTest.php
│ ├── DateTimeIteratorTest.php
│ ├── DateTimeTest.php
│ ├── Day/
│ │ └── WeekDayTest.php
│ ├── DayTest.php
│ ├── DaysIteratorTest.php
│ ├── DaysTest.php
│ ├── LeapSecondTest.php
│ ├── LeapSecondsTest.php
│ ├── MonthDaysTest.php
│ ├── MonthTest.php
│ ├── MonthsIteratorTest.php
│ ├── MonthsTest.php
│ ├── Psr20ClockAdapterTest.php
│ ├── QuarterTest.php
│ ├── TimeEpochTest.php
│ ├── TimePeriodTest.php
│ ├── TimePeriodsIteratorTest.php
│ ├── TimePeriodsSortTest.php
│ ├── TimePeriodsTest.php
│ ├── TimeTest.php
│ ├── TimeZone/
│ │ └── TimeOffsetTest.php
│ ├── TimeZoneTest.php
│ ├── YearMonthsTest.php
│ ├── YearTest.php
│ └── YearsTest.php
├── IntervalTest.php
├── RelativeTimeUnitTest.php
├── StopwatchTest.php
├── TimeUnit/
│ └── HRTimeTest.php
└── TimeUnitTest.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
*.php text eol=lf
*.phpt text eol=lf
/composer.lock export-ignore
/tools/ export-ignore
/.github/ export-ignore
/docs export-ignore
/tests export-ignore
/.phive export-ignore
/benchmark export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.php_cs export-ignore
/phpstan.neon export-ignore
/phpunit.xml export-ignore
/psalm.xml export-ignore
/infection.json export-ignore
/phpbench.json export-ignore
================================================
FILE: .github/workflows/readonly.yaml
================================================
name: Readonly
on:
pull_request_target:
types: [opened]
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi, thank you for your contribution.
Unfortunately, this repository is read-only. It's a split from our main monorepo repository.
In order to proceed with this PR please open it against https://github.com/aeon-php/aeon repository.
Thank you.
================================================
FILE: .gitignore
================================================
vendor
*.cache
var
================================================
FILE: README.md
================================================
# Aeon
[](https://php.net/)
[](https://packagist.org/packages/aeon-php/calendar)
[](https://packagist.org/packages/aeon-php/calendar)
[](https://packagist.org/packages/aeon-php/calendar)

[](https://dashboard.stryker-mutator.io/reports/github.com/aeon-php/calendar/1.x)
Time Management Framework for PHP
> The word aeon /ˈiːɒn/, also spelled eon (in American English), originally meant "life", "vital force" or "being",
> "generation" or "a period of time", though it tended to be translated as "age" in the sense of "ages", "forever",
> "timeless" or "for eternity".
[Source: Wikipedia](https://en.wikipedia.org/wiki/Aeon)
Aeon is a set of libraries that makes easier to work with PHP Date & Time in elegant Object Oriented way.
* [Documentation & Examples](https://aeon-php.org/docs/calendar/)
* [Contributing & Development](https://github.com/aeon-php/.github/blob/master/CONTRIBUTING.md)
* [Community](https://github.com/orgs/aeon-php/discussions)
================================================
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeFormatBench.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Benchmark\Gregorian;
use Aeon\Calendar\Gregorian\DateTime;
/**
* @revs(50)
*
* @iterations(10)
*
* @outputTimeUnit("milliseconds")
*
* @BeforeMethods({"init"})
*/
final class DateTimeFormatBench
{
private DateTime $aeonDateTime;
private \DateTimeImmutable $dateTime;
public function init() : void
{
$this->aeonDateTime = DateTime::fromString('2020-01-01 00:00:00');
$this->dateTime = new \DateTimeImmutable('2020-01-01 00:00:00');
}
public function bench_aeon_format() : void
{
$this->aeonDateTime->format('Y-m-d H:i:s.u P');
}
public function bench_php_format() : void
{
$this->dateTime->format('Y-m-d H:i:s.u P');
}
}
================================================
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeInitBench.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Benchmark\Gregorian;
use Aeon\Calendar\Gregorian\DateTime;
use Aeon\Calendar\Gregorian\Day;
use Aeon\Calendar\Gregorian\Month;
use Aeon\Calendar\Gregorian\Time;
use Aeon\Calendar\Gregorian\TimeZone;
use Aeon\Calendar\Gregorian\Year;
/**
* @revs(50)
*
* @iterations(10)
*
* @outputTimeUnit("milliseconds")
*/
final class DateTimeInitBench
{
public function bench_datetime_immutable_constructor() : void
{
new \DateTimeImmutable('2020-01-01 00:00:00.00000 UTC');
}
public function bench_datetime_constructor() : void
{
new \DateTime('2020-01-01 00:00:00.00000 UTC');
}
public function bench_aeon_datetime_from_datetime_immutable() : void
{
DateTime::fromDateTime(new \DateTimeImmutable('2020-01-01 00:00:00.00000 UTC'));
}
public function bench_aeon_datetime_create() : void
{
DateTime::create(2020, 01, 01, 00, 00, 00, 0, 'UTC');
}
public function bench_aeon_datetime_constructor() : void
{
new DateTime(
new Day(new Month(new Year(2020), 01), 01),
new Time(00, 00, 00, 0),
TimeZone::fromString('UTC')
);
}
public function bench_aeon_datetime_from_string() : void
{
DateTime::fromString('2020-01-01 00:00:00.00000 UTC');
}
}
================================================
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeUnixTimestampBench.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Benchmark\Gregorian;
use Aeon\Calendar\Gregorian\DateTime;
/**
* @revs(50)
*
* @iterations(10)
*
* @outputTimeUnit("milliseconds")
*/
final class DateTimeUnixTimestampBench
{
private DateTime $aeonDateTime;
private \DateTimeImmutable $dateTime;
public function __construct()
{
$this->aeonDateTime = DateTime::fromString('2020-01-01 00:00:00');
$this->dateTime = new \DateTimeImmutable('2020-01-01 00:00:00');
}
public function bench_aeon_unix_timestamp() : void
{
$this->aeonDateTime->timestampUNIX();
}
public function bench_php_unix_timestamp() : void
{
$this->dateTime->getTimestamp();
}
}
================================================
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/DayIterationBench.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Benchmark\Gregorian;
use Aeon\Calendar\Gregorian\GregorianCalendar;
use Aeon\Calendar\Gregorian\Interval;
/**
* @revs(50)
*
* @iterations(10)*
*
* @outputTimeUnit("milliseconds")
*/
final class DayIterationBench
{
public function bench_aeon_iteration_over_last_half_of_the_year() : void
{
$end = GregorianCalendar::UTC()->currentDay();
$start = $end->subMonths(6);
$days = [];
foreach ($start->until($end, Interval::rightOpen())->all() as $nextDay) {
$days[] = $nextDay->format('Y-m-d');
}
}
public function bench_php_iteration_over_last_half_of_the_year() : void
{
\date_default_timezone_set('UTC');
$end = new \DateTime('today');
$start = new \DateTime('-6 months');
$interval = \DateInterval::createFromDateString('1 day');
$period = new \DatePeriod($start, $interval, $end);
$days = [];
foreach ($period as $nextDay) {
$days[] = $nextDay->format('Y-m-d');
}
}
}
================================================
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/TimeUnitInitBench.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Benchmark\Gregorian;
use Aeon\Calendar\TimeUnit;
/**
* @revs(50)
*
* @iterations(10)
*
* @outputTimeUnit("milliseconds")
*/
final class TimeUnitInitBench
{
public function bench_time_unit_positive() : void
{
TimeUnit::positive(100, 50000);
}
public function bench_time_unit_negative() : void
{
TimeUnit::positive(100, 50000);
}
}
================================================
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/TimeZoneInitBench.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Benchmark\Gregorian;
use Aeon\Calendar\Gregorian\TimeZone;
/**
* @revs(50)
*
* @iterations(10)
*
* @outputTimeUnit("milliseconds")
*/
final class TimeZoneInitBench
{
public function bench_time_zone_init_by_static_name() : void
{
TimeZone::europeWarsaw();
}
public function bench_time_zone_init_by_abbreviation() : void
{
TimeZone::abbreviation('CEST');
}
public function bench_time_zone_init_by_id() : void
{
TimeZone::id('Europe/Warsaw');
}
public function bench_time_zone_init_by_offset() : void
{
TimeZone::offset('+01:00');
}
public function bench_time_zone_init_by_string() : void
{
TimeZone::fromString('Europe/Warsaw');
}
public function bench_php_datetime_zone_constructor() : void
{
new \DateTimeZone('Europe/Warsaw');
}
}
================================================
FILE: composer.json
================================================
{
"name": "aeon-php/calendar",
"type": "library",
"description": "PHP type safe, immutable calendar library",
"keywords": [
"calendar",
"immutable",
"date",
"time",
"datetime"
],
"require": {
"php": "~8.3.0 || ~8.4.0 || ~8.5.0"
},
"require-dev": {
"ext-bcmath": "*",
"ext-pcov": "*"
},
"suggest": {
"ext-bcmath": "Compare time units with high precision"
},
"config": {
"optimize-autoloader": true,
"sort-packages": true
},
"license": "MIT",
"autoload": {
"psr-4": {
"Aeon\\": [
"src/Aeon"
]
}
},
"autoload-dev": {
"psr-4": {
"Aeon\\Calendar\\Tests\\": "tests/Aeon/Calendar/Tests/",
"Aeon\\Calculator\\Tests\\": "tests/Aeon/Calculator/Tests/",
"Aeon\\Calendar\\Benchmark\\": "benchmark/Aeon/Calendar/Benchmark/"
}
},
"prefer-stable": true
}
================================================
FILE: phpbench.json
================================================
{
"runner.bootstrap": "./vendor/autoload.php",
"runner.path": "benchmark",
"runner.retry_threshold": 5,
"runner.progress": "dots",
"report.generators": {
"aeon": {
"extends": "default",
"break": ["benchmark"]
}
}
}
================================================
FILE: src/Aeon/Calculator/BCMathCalculator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calculator;
use Aeon\Calculator\Exception\InvalidTypeException;
/**
* @psalm-immutable
*/
final class BCMathCalculator implements Calculator
{
private int $precision;
public function __construct(int $precision)
{
$this->precision = $precision;
}
/**
* @psalm-pure
*/
public static function supported() : bool
{
return \extension_loaded('bcmath');
}
public function precision() : int
{
return $this->precision;
}
/**
* @psalm-suppress InvalidNullableReturnType
* @psalm-suppress NullableReturnStatement
*/
public function divide(string $value, string $divisor) : string
{
if (!\is_numeric($value) || !\is_numeric($divisor)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
if (\floatval($divisor) === \floatval('0')) {
throw new \LogicException("Divisor can't be 0");
}
return \bcdiv($value, $divisor, $this->precision);
}
/**
* @psalm-suppress InvalidNullableReturnType
* @psalm-suppress NullableReturnStatement
*/
public function modulo(string $value, string $divisor) : string
{
if (!\is_numeric($value) || !\is_numeric($divisor)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
if (\floatval($divisor) === \floatval('0')) {
throw new \LogicException("Divisor can't be 0");
}
return \bcmod($value, $divisor, $this->precision);
}
public function multiply(string $value, string $multiplier) : string
{
if (!\is_numeric($value) || !\is_numeric($multiplier)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
return \bcmul($value, $multiplier, $this->precision);
}
public function add(string $value, string $nextValue) : string
{
if (!\is_numeric($value) || !\is_numeric($nextValue)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
return \bcadd($value, $nextValue, $this->precision);
}
public function sub(string $value, string $nextValue) : string
{
if (!\is_numeric($value) || !\is_numeric($nextValue)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
return \bcsub($value, $nextValue, $this->precision);
}
public function isGreaterThan(string $value, string $nextValue) : bool
{
if (!\is_numeric($value) || !\is_numeric($nextValue)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
return \bccomp($value, $nextValue, $this->precision) === 1;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isGreaterThanOrEqualTo` instead. Will be removed with 2.0
*/
public function isGreaterThanEq(string $value, string $nextValue) : bool
{
return $this->isGreaterThanOrEqualTo($value, $nextValue);
}
public function isGreaterThanOrEqualTo(string $value, string $nextValue) : bool
{
if (!\is_numeric($value) || !\is_numeric($nextValue)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
return \in_array(\bccomp($value, $nextValue, $this->precision), [0, 1], true);
}
public function isLessThan(string $value, string $nextValue) : bool
{
if (!\is_numeric($value) || !\is_numeric($nextValue)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
return \bccomp($value, $nextValue, $this->precision) === -1;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isLessThanOrEqualTo` instead. Will be removed with 2.0
*/
public function isLessThanEq(string $value, string $nextValue) : bool
{
return $this->isLessThanOrEqualTo($value, $nextValue);
}
public function isLessThanOrEqualTo(string $value, string $nextValue) : bool
{
if (!\is_numeric($value) || !\is_numeric($nextValue)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
return \in_array(\bccomp($value, $nextValue, $this->precision), [-1, 0], true);
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(string $value, string $nextValue) : bool
{
return $this->isEqualTo($value, $nextValue);
}
public function isEqualTo(string $value, string $nextValue) : bool
{
if (!\is_numeric($value) || !\is_numeric($nextValue)) {
throw new InvalidTypeException('Expected values to be numeric string');
}
return \bccomp($value, $nextValue, $this->precision) === 0;
}
}
================================================
FILE: src/Aeon/Calculator/Calculator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calculator;
/**
* @psalm-immutable
*/
interface Calculator
{
public function precision() : int;
public function modulo(string $value, string $divisor) : string;
public function divide(string $value, string $divisor) : string;
public function multiply(string $value, string $multiplier) : string;
public function add(string $value, string $nextValue) : string;
public function sub(string $value, string $nextValue) : string;
public function isGreaterThan(string $value, string $nextValue) : bool;
/**
* @infection-ignore-all
*
* @deprecated Use `isGreaterThanOrEqualTo` instead. Will be removed with 2.0
*/
public function isGreaterThanEq(string $value, string $nextValue) : bool;
public function isGreaterThanOrEqualTo(string $value, string $nextValue) : bool;
public function isLessThan(string $value, string $nextValue) : bool;
/**
* @infection-ignore-all
*
* @deprecated Use `isLessThanOrEqualTo` instead. Will be removed with 2.0
*/
public function isLessThanEq(string $value, string $nextValue) : bool;
public function isLessThanOrEqualTo(string $value, string $nextValue) : bool;
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(string $value, string $nextValue) : bool;
public function isEqualTo(string $value, string $nextValue) : bool;
}
================================================
FILE: src/Aeon/Calculator/Exception/Exception.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calculator\Exception;
class Exception extends \Exception
{
}
================================================
FILE: src/Aeon/Calculator/Exception/InvalidTypeException.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calculator\Exception;
final class InvalidTypeException extends Exception
{
}
================================================
FILE: src/Aeon/Calculator/PHPCalculator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calculator;
/**
* @psalm-immutable
*/
final class PHPCalculator implements Calculator
{
private int $precision;
public function __construct(int $precision)
{
$this->precision = $precision;
}
public function precision() : int
{
return $this->precision;
}
public function divide(string $value, string $divisor) : string
{
return \number_format(\floatval($value) / \floatval($divisor), $this->precision, '.', '');
}
public function modulo(string $value, string $divisor) : string
{
return \number_format(\fmod(\floatval($value), \floatval($divisor)), $this->precision, '.', '');
}
public function multiply(string $value, string $multiplier) : string
{
return \number_format(\floatval($value) * \floatval($multiplier), $this->precision, '.', '');
}
public function add(string $value, string $nextValue) : string
{
return \number_format(\floatval($value) + \floatval($nextValue), $this->precision, '.', '');
}
public function sub(string $value, string $nextValue) : string
{
return \number_format(\floatval($value) - \floatval($nextValue), $this->precision, '.', '');
}
public function isGreaterThan(string $value, string $nextValue) : bool
{
return \floatval(\number_format(\floatval($value), $this->precision, '.', '')) >
\floatval(\number_format(\floatval($nextValue), $this->precision, '.', ''));
}
/**
* @infection-ignore-all
*
* @deprecated Use `isGreaterThanOrEqualTo` instead. Will be removed with 2.0
*/
public function isGreaterThanEq(string $value, string $nextValue) : bool
{
return $this->isGreaterThanOrEqualTo($value, $nextValue);
}
public function isGreaterThanOrEqualTo(string $value, string $nextValue) : bool
{
return \floatval(\number_format(\floatval($value), $this->precision, '.', '')) >=
\floatval(\number_format(\floatval($nextValue), $this->precision, '.', ''));
}
public function isLessThan(string $value, string $nextValue) : bool
{
return \floatval(\number_format(\floatval($value), $this->precision, '.', '')) <
\floatval(\number_format(\floatval($nextValue), $this->precision, '.', ''));
}
/**
* @infection-ignore-all
*
* @deprecated Use `isLessThanOrEqualTo` instead. Will be removed with 2.0
*/
public function isLessThanEq(string $value, string $nextValue) : bool
{
return $this->isLessThanOrEqualTo($value, $nextValue);
}
public function isLessThanOrEqualTo(string $value, string $nextValue) : bool
{
return \floatval(\number_format(\floatval($value), $this->precision, '.', '')) <=
\floatval(\number_format(\floatval($nextValue), $this->precision, '.', ''));
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(string $value, string $nextValue) : bool
{
return $this->isEqualTo($value, $nextValue);
}
public function isEqualTo(string $value, string $nextValue) : bool
{
return \floatval(\number_format(\floatval($value), $this->precision, '.', '')) ==
\floatval(\number_format(\floatval($nextValue), $this->precision, '.', ''));
}
}
================================================
FILE: src/Aeon/Calculator/PreciseCalculator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calculator;
final class PreciseCalculator
{
private static ?Calculator $instance = null;
/**
* @psalm-pure
*
* @psalm-suppress ImpureStaticProperty
*/
public static function initialize(int $precision) : Calculator
{
if (self::$instance instanceof Calculator && self::$instance->precision() === $precision) {
return self::$instance;
}
if (BCMathCalculator::supported()) {
self::$instance = new BCMathCalculator($precision);
return self::$instance;
}
// @codeCoverageIgnoreStart
self::$instance = new PHPCalculator($precision);
return self::$instance;
// @codeCoverageIgnoreEnd
}
}
================================================
FILE: src/Aeon/Calendar/Exception/Exception.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Exception;
class Exception extends \Exception
{
}
================================================
FILE: src/Aeon/Calendar/Exception/InvalidArgumentException.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Exception;
final class InvalidArgumentException extends Exception
{
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Calendar.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*/
interface Calendar
{
public function timeZone() : TimeZone;
public function currentYear() : Year;
public function currentMonth() : Month;
public function currentDay() : Day;
public function yesterday() : DateTime;
public function tomorrow() : DateTime;
public function now() : DateTime;
}
================================================
FILE: src/Aeon/Calendar/Gregorian/DateTime.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\Exception;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\RelativeTimeUnit;
use Aeon\Calendar\TimeUnit;
use Aeon\Calendar\Unit;
/**
* @psalm-immutable
*/
final class DateTime
{
private Day $day;
private Time $time;
private TimeZone $timeZone;
public function __construct(Day $day, Time $time, TimeZone $timeZone)
{
$this->day = $day;
$this->time = $time;
$this->timeZone = $timeZone;
}
/**
* @psalm-pure
*/
public static function create(int $year, int $month, int $day, int $hour, int $minute, int $second, int $microsecond = 0, string $timezone = 'UTC') : self
{
return new self(
new Day(
new Month(
new Year($year),
$month
),
$day
),
new Time($hour, $minute, $second, $microsecond),
TimeZone::fromString($timezone)
);
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
* @psalm-suppress ImpureStaticProperty
* @psalm-suppress PropertyTypeCoercion
* @psalm-suppress ImpurePropertyAssignment
* @psalm-suppress InaccessibleProperty
*/
public static function fromDateTime(\DateTimeInterface $dateTime) : self
{
$day = Day::fromDateTime($dateTime);
$time = Time::fromDateTime($dateTime);
$timeZone = TimeZone::fromDateTimeZone($dateTime->getTimezone());
return new self(
$day,
$time,
$timeZone,
);
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureFunctionCall
* @psalm-suppress ImpureMethodCall
*/
public static function fromString(string $date) : self
{
$currentPHPTimeZone = \date_default_timezone_get();
\date_default_timezone_set('UTC');
try {
$dateTime = self::fromDateTime(new \DateTimeImmutable($date));
} catch (\Exception $e) {
throw new InvalidArgumentException("Value \"{$date}\" is not valid date time format.");
}
if ($currentPHPTimeZone !== 'UTC') {
\date_default_timezone_set($currentPHPTimeZone);
}
return $dateTime;
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureFunctionCall
* @psalm-suppress ImpureMethodCall
*/
public static function fromTimestampUnix(int $timestamp) : self
{
$currentPHPTimeZone = \date_default_timezone_get();
\date_default_timezone_set('UTC');
$dateTime = self::fromDateTime((new \DateTimeImmutable)->setTimestamp($timestamp));
if ($currentPHPTimeZone !== 'UTC') {
\date_default_timezone_set($currentPHPTimeZone);
}
return $dateTime;
}
public function __toString() : string
{
return $this->toISO8601();
}
/**
* @return array{datetime: string, day: Day, time: Time, timeZone: TimeZone}
*/
public function __debugInfo() : array
{
return [
'datetime' => $this->toISO8601(),
'day' => $this->day,
'time' => $this->time,
'timeZone' => $this->timeZone,
];
}
/**
* @return array{day: Day, time: Time, timeZone: TimeZone}
*/
public function __serialize() : array
{
return [
'day' => $this->day,
'time' => $this->time,
'timeZone' => $this->timeZone,
];
}
/**
* @param array{day: Day, time: Time, timeZone: TimeZone} $data
*/
public function __unserialize(array $data) : void
{
$this->day = $data['day'];
$this->time = $data['time'];
$this->timeZone = $data['timeZone'];
}
public function year() : Year
{
return $this->month()->year();
}
public function month() : Month
{
return $this->day->month();
}
public function day() : Day
{
return $this->day;
}
public function time() : Time
{
return $this->time;
}
public function setTime(Time $time) : self
{
return new self(
$this->day,
$time,
$this->timeZone
);
}
public function setTimeIn(Time $time, TimeZone $timeZone) : self
{
return (new self(
$this->day,
$time,
$this->timeZone
))->toTimeZone($timeZone)
->setTime($time);
}
public function setDay(Day $day) : self
{
return new self(
$day,
$this->time,
$this->timeZone
);
}
public function toDateTimeImmutable() : \DateTimeImmutable
{
return new \DateTimeImmutable(
\sprintf(
'%d-%02d-%02d %02d:%02d:%02d.%06d',
$this->day->year()->number(),
$this->day->month()->number(),
$this->day->number(),
$this->time->hour(),
$this->time->minute(),
$this->time->second(),
$this->time->microsecond(),
),
$this->timeZone->toDateTimeZone()
);
}
public function toAtomicTime() : self
{
return $this->add(LeapSeconds::load()->until($this)->offsetTAI());
}
public function toGPSTime() : self
{
return $this->add(LeapSeconds::load()
->since(TimeEpoch::GPS()->date())
->until($this)->count());
}
public function format(string $format) : string
{
return $this->toDateTimeImmutable()->format($format);
}
public function timeZone() : TimeZone
{
return $this->timeZone;
}
public function timeZoneAbbreviation() : TimeZone
{
if ($this->timeZone->isOffset()) {
throw new Exception("TimeZone offset {$this->timeZone->name()} can't be converted into abbreviation.");
}
return TimeZone::fromString($this->toDateTimeImmutable()->format('T'));
}
public function toTimeZone(TimeZone $dateTimeZone) : self
{
return self::fromDateTime($this->toDateTimeImmutable()->setTimezone($dateTimeZone->toDateTimeZone()));
}
public function toISO8601(bool $extended = true) : string
{
return $extended
? $this->toDateTimeImmutable()->format('Y-m-d\TH:i:sP')
: $this->toDateTimeImmutable()->format('Ymd\THisO');
}
public function isDaylightSaving() : bool
{
return (bool) $this->toDateTimeImmutable()->format('I');
}
public function isDaylight() : bool
{
return !$this->isDaylightSaving();
}
public function timestamp(TimeEpoch $timeEpoch) : TimeUnit
{
if ($this->isBefore($timeEpoch->date())) {
throw new Exception('Given epoch started at ' . $timeEpoch->date()->toISO8601() . ' which was after ' . $this->toISO8601());
}
switch ($timeEpoch->type()) {
case TimeEpoch::UTC:
return $this->timestampUNIX()
->sub(TimeEpoch::UNIX()->distanceTo($timeEpoch))
->add(LeapSeconds::load()->offsetTAI());
case TimeEpoch::GPS:
return $this->timestampUNIX()
->sub(TimeEpoch::UNIX()->distanceTo($timeEpoch))
->add(
LeapSeconds::load()->offsetTAI()
->sub(LeapSeconds::load()->until($timeEpoch->date())->offsetTAI())
);
case TimeEpoch::TAI:
return $timeEpoch->date()->until($this)->distance()
->add($timeEpoch->date()->until($this)->leapSeconds()->offsetTAI());
default:
return $this->timestampUNIX();
}
}
/**
* Number of seconds elapsed since Unix epoch started at 1970-01-01 (1970-01-01T00:00:00Z)
* Not including leap seconds.
*/
public function timestampUNIX() : TimeUnit
{
$timestamp = $this->toDateTimeImmutable()->getTimestamp();
if ($timestamp >= 0) {
return TimeUnit::positive($timestamp, $this->time->microsecond());
}
return TimeUnit::negative(\abs($timestamp), $this->time->microsecond());
}
public function modify(string $modifier) : self
{
$dateTimeParts = \date_parse($modifier);
if (!\is_array($dateTimeParts)) {
throw new InvalidArgumentException('Value "{modify}" is not valid relative time format.');
}
if ($dateTimeParts['error_count'] > 0) {
throw new InvalidArgumentException("Value \"{$modifier}\" is not valid relative time format.");
}
if (!isset($dateTimeParts['relative']) || !\is_array($dateTimeParts['relative'])) {
throw new InvalidArgumentException("Value \"{$modifier}\" is not valid relative time format.");
}
$dateTime = $this;
if (
!\is_int($dateTimeParts['relative']['year']) ||
!\is_int($dateTimeParts['relative']['month']) ||
!\is_int($dateTimeParts['relative']['day']) ||
!\is_int($dateTimeParts['relative']['hour']) ||
!\is_int($dateTimeParts['relative']['minute']) ||
!\is_int($dateTimeParts['relative']['second'])
) {
throw new InvalidArgumentException("Value \"{$modifier}\" is not valid relative time format.");
}
if ($dateTimeParts['relative']['year'] !== 0) {
$dateTime = $dateTime->add(RelativeTimeUnit::years($dateTimeParts['relative']['year']));
}
if ($dateTimeParts['relative']['month'] !== 0) {
$dateTime = $dateTime->add(RelativeTimeUnit::months($dateTimeParts['relative']['month']));
}
if (\array_key_exists('weekday', $dateTimeParts['relative'])) {
if ($dateTimeParts['relative']['weekday'] !== 0) {
$dateTimeWeekDay = $dateTime->day()->weekDay();
if ($dateTime->day()->weekDay()->number() < (int) $dateTimeParts['relative']['weekday']) {
$dateTime = $dateTime->add(TimeUnit::days((int) $dateTimeParts['relative']['weekday'] - $dateTimeWeekDay->number()));
}
}
}
return $dateTime->add(
TimeUnit::days($dateTimeParts['relative']['day'])
->add(TimeUnit::hours($dateTimeParts['relative']['hour']))
->add(TimeUnit::minutes($dateTimeParts['relative']['minute']))
->add(TimeUnit::seconds($dateTimeParts['relative']['second']))
);
}
public function addHour() : self
{
return $this->add(TimeUnit::hour());
}
public function subHour() : self
{
return $this->sub(TimeUnit::hour());
}
public function addHours(int $hours) : self
{
return $this->add(TimeUnit::hours($hours));
}
public function subHours(int $hours) : self
{
return $this->sub(TimeUnit::hours($hours));
}
public function addMinute() : self
{
return $this->add(TimeUnit::minute());
}
public function subMinute() : self
{
return $this->sub(TimeUnit::minute());
}
public function addMinutes(int $minutes) : self
{
return $this->add(TimeUnit::minutes($minutes));
}
public function subMinutes(int $minutes) : self
{
return $this->sub(TimeUnit::minutes($minutes));
}
public function addSecond() : self
{
return $this->add(TimeUnit::second());
}
public function subSecond() : self
{
return $this->sub(TimeUnit::second());
}
public function addSeconds(int $seconds) : self
{
return $this->add(TimeUnit::seconds($seconds));
}
public function subSeconds(int $seconds) : self
{
return $this->sub(TimeUnit::seconds($seconds));
}
public function addDay() : self
{
return $this->add(TimeUnit::day());
}
public function subDay() : self
{
return $this->sub(TimeUnit::day());
}
public function addDays(int $days) : self
{
return $this->add(TimeUnit::days($days));
}
public function subDays(int $days) : self
{
return $this->sub(TimeUnit::days($days));
}
public function addMonth() : self
{
return $this->add(RelativeTimeUnit::month());
}
public function subMonth() : self
{
return $this->sub(RelativeTimeUnit::month());
}
public function addMonths(int $months) : self
{
return $this->add(RelativeTimeUnit::months($months));
}
public function subMonths(int $months) : self
{
return $this->sub(RelativeTimeUnit::months($months));
}
public function addYear() : self
{
return $this->add(RelativeTimeUnit::year());
}
public function subYear() : self
{
return $this->sub(RelativeTimeUnit::year());
}
public function addYears(int $years) : self
{
return $this->add(RelativeTimeUnit::years($years));
}
public function subYears(int $years) : self
{
return $this->sub(RelativeTimeUnit::years($years));
}
public function midnight() : self
{
return new self(
$this->day,
new Time(0, 0, 0, 0),
$this->timeZone
);
}
public function noon() : self
{
return new self(
$this->day,
new Time(12, 0, 0, 0),
$this->timeZone
);
}
public function endOfDay() : self
{
return new self(
$this->day,
new Time(23, 59, 59, 999999),
$this->timeZone
);
}
public function yesterday() : self
{
return $this->sub(TimeUnit::day())->midnight();
}
public function tomorrow() : self
{
return $this->add(TimeUnit::day())->midnight();
}
/**
* When adding RelativeTimeUnit::month() this method will try to change month and adjust
* day of the month.
* Examples:
* - 2021-02-28 + RelativeTimeUnit::month() = 2021-03-28.
*/
public function add(Unit $timeUnit) : self
{
if ($timeUnit instanceof RelativeTimeUnit && $timeUnit->inMonths()) {
$years = $timeUnit->toPositive()->inYears();
$months = $timeUnit->inCalendarMonths();
$newMonth = $timeUnit->isNegative()
? $this->month()->sub($years, $months)
: $this->month()->add($years, $months);
if ($newMonth->lastDay()->number() < $this->day->number()) {
return new self(new Day($newMonth, $newMonth->lastDay()->number()), $this->time, $this->timeZone);
}
return new self(new Day($newMonth, $this->day->number()), $this->time, $this->timeZone);
}
return self::fromDateTime($this->toDateTimeImmutable()->add($timeUnit->toDateInterval()));
}
/**
* When subtracting RelativeTimeUnit::month() this method will try to change month and adjust
* day of the month.
* Examples:
* - 2021-03-31 - RelativeTimeUnit::month() = 2021-02-28.
*/
public function sub(Unit $timeUnit) : self
{
return $this->add($timeUnit->invert());
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $dateTime) : bool
{
return $this->isEqualTo($dateTime);
}
public function isEqualTo(self $dateTime) : bool
{
return $this->toDateTimeImmutable() == $dateTime->toDateTimeImmutable();
}
public function isAfter(self $dateTime) : bool
{
return $this->toDateTimeImmutable() > $dateTime->toDateTimeImmutable();
}
/**
* @infection-ignore-all
*
* @deprecated Use `isAfterOrEqualTo` instead. Will be removed with 2.0
*/
public function isAfterOrEqual(self $dateTime) : bool
{
return $this->isAfterOrEqualTo($dateTime);
}
public function isAfterOrEqualTo(self $dateTime) : bool
{
return $this->toDateTimeImmutable() >= $dateTime->toDateTimeImmutable();
}
/**
* @infection-ignore-all
*
* @deprecated Use `isBeforeOrEqualTo` instead. Will be removed with 2.0
*/
public function isBeforeOrEqual(self $dateTime) : bool
{
return $this->isBeforeOrEqualTo($dateTime);
}
public function isBeforeOrEqualTo(self $dateTime) : bool
{
return $this->toDateTimeImmutable() <= $dateTime->toDateTimeImmutable();
}
public function isBefore(self $dateTime) : bool
{
return $this->toDateTimeImmutable() < $dateTime->toDateTimeImmutable();
}
public function until(self $dateTime) : TimePeriod
{
return new TimePeriod($this, $dateTime);
}
public function since(self $dateTime) : TimePeriod
{
return new TimePeriod($dateTime, $this);
}
public function distance(self $dateTime) : TimeUnit
{
return $this->until($dateTime)->distance();
}
public function distanceSince(self $dateTime) : TimeUnit
{
return $this->since($dateTime)->distance();
}
public function distanceUntil(self $dateTime) : TimeUnit
{
return $this->until($dateTime)->distance();
}
public function iterate(self $pointInTime, TimeUnit $by) : TimePeriods
{
return $pointInTime->isBefore($this)
? $this->since($pointInTime)->iterateBackward($by, Interval::closed())
: $this->until($pointInTime)->iterate($by, Interval::closed());
}
public function isAmbiguous() : bool
{
$tz = $this->timeZone;
if ($tz->timeOffset($this)->isUTC()) {
return false;
}
/**
* @var array<int, array{ts: int, time: string, offset: int, isdst: bool, abbr: string}> $transitions
*/
$transitions = $tz->toDateTimeZone()->getTransitions(
$this->timestampUNIX()->sub(TimeUnit::hours(1)->add(TimeUnit::minute()))->inSeconds(),
$this->timestampUNIX()->add(TimeUnit::hours(1))->inSeconds(),
);
if (\count($transitions) === 1) {
return false;
}
if ($transitions[1]['offset'] - $transitions[0]['offset'] === 3600) {
return false;
}
return true;
}
public function quarter() : Quarter
{
return $this->year()->quarter((int) \ceil($this->month()->number() / 3));
}
public function compareTo(self $dateTime) : int
{
if ($this->isEqualTo($dateTime)) {
return 0;
}
return $this->isBefore($dateTime)
? -1
: 1;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/DateTimeIntervalIterator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Unit;
final class DateTimeIntervalIterator extends \FilterIterator
{
private Interval $interval;
public function __construct(DateTime $start, DateTime $end, Unit $timeUnit, Interval $interval)
{
$this->interval = $interval;
parent::__construct(new DateTimeIterator($start, $end, $timeUnit));
}
public function start() : DateTime
{
return $this->getInnerIterator()->start();
}
public function end() : DateTime
{
return $this->getInnerIterator()->end();
}
public function unit() : Unit
{
return $this->getInnerIterator()->unit();
}
public function isForward() : bool
{
return $this->getInnerIterator()->isForward();
}
public function interval() : Interval
{
return $this->interval;
}
public function hasNext() : bool
{
$dateTimeIterator = clone $this->getInnerIterator();
$dateTimeIterator->next();
if ($dateTimeIterator->isForward()) {
if ($this->interval->isRightOpen() && !$dateTimeIterator->hasNext()) {
return false;
}
if ($dateTimeIterator->current()->isAfter($dateTimeIterator->end())) {
return false;
}
} else {
if ($this->interval->isLeftOpen() && !$dateTimeIterator->hasNext()) {
return false;
}
if ($dateTimeIterator->current()->isBefore($dateTimeIterator->end())) {
return false;
}
}
return true;
}
public function accept() : bool
{
$dateTimeIterator = $this->getInnerIterator();
if ($dateTimeIterator->isForward()) {
if (($this->interval->isRightOpen() || $this->interval->isOpen()) && !$dateTimeIterator->hasNext()) {
return false;
}
if (($this->interval->isLeftOpen() || $this->interval->isOpen()) && $dateTimeIterator->isFirst()) {
return false;
}
} else {
if (($this->interval->isRightOpen() || $this->interval->isOpen()) && $dateTimeIterator->isFirst()) {
return false;
}
if (($this->interval->isLeftOpen() || $this->interval->isOpen()) && !$dateTimeIterator->hasNext()) {
return false;
}
}
return true;
}
public function key() : int
{
$dateTimeIterator = $this->getInnerIterator();
if ($dateTimeIterator->isForward()) {
if ($this->interval->isLeftOpen() || $this->interval->isOpen()) {
return $dateTimeIterator->key() - 1;
}
} else {
if ($this->interval->isRightOpen() || $this->interval->isOpen()) {
return $dateTimeIterator->key() - 1;
}
}
return $dateTimeIterator->key();
}
/**
* @psalm-suppress MixedReturnStatement
*/
public function current() : ?DateTime
{
/**
* @phpstan-ignore-next-line
*/
return parent::current();
}
/**
* @psalm-suppress InvalidReturnStatement
* @psalm-suppress InvalidReturnType
*/
public function getInnerIterator() : DateTimeIterator
{
/** @phpstan-ignore-next-line */
return parent::getInnerIterator();
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/DateTimeIterator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\Unit;
/**
* @implements \Iterator<DateTime>
*/
final class DateTimeIterator implements \Iterator
{
private DateTime $currentDate;
private DateTime $start;
private DateTime $end;
private Unit $timeUnit;
private int $key;
private bool $forward;
private bool $empty;
/**
* @throws InvalidArgumentException
*/
public function __construct(DateTime $start, DateTime $end, Unit $timeUnit)
{
$this->start = $start;
$this->end = $end;
$this->timeUnit = $timeUnit;
$this->currentDate = $start;
$this->key = 0;
$this->forward = $start->isBeforeOrEqualTo($end);
$this->empty = $start->isEqualTo($end);
if ($this->forward && $timeUnit->isNegative()) {
throw new InvalidArgumentException("Forward DateTimeIterator {$start->format('Y-m-d H:i:sP')}...{$end->format('Y-m-d H:i:sP')} requires positive TimeUnit");
}
if (!$this->forward && !$timeUnit->isNegative()) {
throw new InvalidArgumentException("Backward DateTimeIterator {$start->format('Y-m-d H:i:sP')}...{$end->format('Y-m-d H:i:sP')} requires negative TimeUnit");
}
}
public function isForward() : bool
{
return $this->forward;
}
public function unit() : Unit
{
return $this->timeUnit;
}
public function start() : DateTime
{
return $this->start;
}
public function end() : DateTime
{
return $this->end;
}
public function current() : DateTime
{
return $this->currentDate;
}
public function next() : void
{
$this->currentDate = $this->currentDate->add($this->timeUnit);
$this->key++;
}
public function hasNext() : bool
{
if ($this->forward) {
return !$this->current()->add($this->timeUnit)->isAfter($this->end);
}
return !$this->current()->add($this->timeUnit)->isBefore($this->end);
}
public function key() : int
{
return $this->key;
}
public function isFirst() : bool
{
return $this->key() === 0;
}
public function valid() : bool
{
if ($this->empty) {
return false;
}
if ($this->forward) {
return $this->currentDate->isBeforeOrEqualTo($this->end);
}
return $this->currentDate->isAfterOrEqualTo($this->end);
}
public function rewind() : void
{
$this->currentDate = $this->start;
$this->key = 0;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Day/WeekDay.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian\Day;
use Aeon\Calendar\Exception\InvalidArgumentException;
/**
* @psalm-immutable
*/
final class WeekDay
{
private const NAMES = [
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
6 => 'Saturday',
7 => 'Sunday',
];
private const NAMES_SHORT = [
1 => 'Mon',
2 => 'Tue',
3 => 'Wed',
4 => 'Thu',
5 => 'Fri',
6 => 'Sat',
7 => 'Sun',
];
private int $number;
public function __construct(int $number)
{
if ($number <= 0 || $number > 7) {
throw new InvalidArgumentException('Day number must be greater or equal 1 and less or equal than 7');
}
$this->number = $number;
}
/**
* @psalm-pure
*/
public static function monday() : self
{
return new self(1);
}
/**
* @psalm-pure
*/
public static function tuesday() : self
{
return new self(2);
}
/**
* @psalm-pure
*/
public static function wednesday() : self
{
return new self(3);
}
/**
* @psalm-pure
*/
public static function thursday() : self
{
return new self(4);
}
/**
* @psalm-pure
*/
public static function friday() : self
{
return new self(5);
}
/**
* @psalm-pure
*/
public static function saturday() : self
{
return new self(6);
}
/**
* @psalm-pure
*/
public static function sunday() : self
{
return new self(7);
}
public function number() : int
{
return $this->number;
}
public function name() : string
{
return self::NAMES[$this->number];
}
public function shortName() : string
{
return self::NAMES_SHORT[$this->number];
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $weekDay) : bool
{
return $this->isEqualTo($weekDay);
}
public function isEqualTo(self $weekDay) : bool
{
return $this->number() === $weekDay->number();
}
public function isWeekend() : bool
{
return \in_array($this->number(), [6, 7], true);
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Day.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\Gregorian\Day\WeekDay;
use Aeon\Calendar\RelativeTimeUnit;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class Day
{
private Month $month;
private int $number;
public function __construct(Month $month, int $number)
{
if ($number <= 0 || $number > $month->numberOfDays()) {
throw new InvalidArgumentException('Day number must be greater or equal 1 and less or equal than ' . $month->numberOfDays());
}
$this->number = $number;
$this->month = $month;
}
/**
* @psalm-pure
*/
public static function create(int $year, int $month, int $day) : self
{
return new self(
new Month(
new Year($year),
$month
),
$day
);
}
/**
* @psalm-pure
*
* @psalm-suppress PossiblyNullArrayAccess
* @psalm-suppress PossiblyNullArgument
* @psalm-suppress ImpureMethodCall
* @psalm-suppress PossiblyInvalidArgument
*/
public static function fromDateTime(\DateTimeInterface $dateTime) : self
{
/**
* @phpstan-ignore-next-line
*/
[$year, $month, $day] = \sscanf($dateTime->format('Y-m-d'), '%d-%d-%d');
/** @phpstan-ignore-next-line */
return new self(new Month(new Year($year), $month), $day, );
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
*/
public static function fromString(string $date) : self
{
try {
return self::fromDateTime(new \DateTimeImmutable($date));
} catch (\Exception $e) {
throw new InvalidArgumentException("Value \"{$date}\" is not valid day format.");
}
}
/**
* @return array{year: int, month:int, day: int}
*/
public function __debugInfo() : array
{
return [
'year' => $this->month->year()->number(),
'month' => $this->month->number(),
'day' => $this->number,
];
}
/**
* @return array{month: Month, number: int}
*/
public function __serialize() : array
{
return [
'month' => $this->month,
'number' => $this->number,
];
}
/**
* @param array{month: Month, number: int} $data
*/
public function __unserialize(array $data) : void
{
$this->month = $data['month'];
$this->number = $data['number'];
}
public function toString() : string
{
return $this->format('Y-m-d');
}
public function timeBetween(self $day) : TimeUnit
{
return TimeUnit::seconds(\abs(($this->toDateTimeImmutable()->getTimestamp() - $day->toDateTimeImmutable()->getTimestamp())));
}
/** @deprecated Use `add` instead. Will be removed with 2.0 */
public function plus(int $years, int $months, int $days) : self
{
return $this->add($years, $months, $days);
}
public function add(int $years, int $months, int $days) : self
{
$dateTime = $this->midnight(TimeZone::UTC());
if ($years !== 0) {
$dateTime = $dateTime->add(RelativeTimeUnit::years($years));
}
if ($months !== 0) {
$dateTime = $dateTime->add(RelativeTimeUnit::months($months));
}
if ($days !== 0) {
$dateTime = $dateTime->add(TimeUnit::days($days));
}
return $dateTime->day();
}
/** @deprecated Use `sub` instead. Will be removed with 2.0 */
public function minus(int $years, int $months, int $days) : self
{
return $this->sub($years, $months, $days);
}
public function sub(int $years, int $months, int $days) : self
{
$dateTime = $this->midnight(TimeZone::UTC());
if ($years !== 0) {
$dateTime = $dateTime->sub(RelativeTimeUnit::years($years));
}
if ($months !== 0) {
$dateTime = $dateTime->sub(RelativeTimeUnit::months($months));
}
if ($days !== 0) {
$dateTime = $dateTime->sub(TimeUnit::days($days));
}
return $dateTime->day();
}
/**
* @infection-ignore-all
*
* @deprecated Use `addDays` instead. Will be removed with 2.0
*/
public function plusDays(int $days) : self
{
return $this->addDays($days);
}
public function addDays(int $days) : self
{
return $this->midnight(TimeZone::UTC())->add(TimeUnit::days($days))->day();
}
/**
* @infection-ignore-all
*
* @deprecated Use `subDays` instead. Will be removed with 2.0
*/
public function minusDays(int $days) : self
{
return $this->subDays($days);
}
public function subDays(int $days) : self
{
return $this->midnight(TimeZone::UTC())->sub(TimeUnit::days($days))->day();
}
/**
* @infection-ignore-all
*
* @deprecated Use `addMonths` instead. Will be removed with 2.0
*/
public function plusMonths(int $months) : self
{
return $this->addMonths($months);
}
public function addMonths(int $months) : self
{
return $this->midnight(TimeZone::UTC())->add(RelativeTimeUnit::months($months))->day();
}
/**
* @infection-ignore-all
*
* @deprecated Use `subMonths` instead. Will be removed with 2.0
*/
public function minusMonths(int $months) : self
{
return $this->subMonths($months);
}
public function subMonths(int $months) : self
{
return $this->midnight(TimeZone::UTC())->sub(RelativeTimeUnit::months($months))->day();
}
/**
* @infection-ignore-all
*
* @deprecated Use `addYears` instead. Will be removed with 2.0
*/
public function plusYears(int $years) : self
{
return $this->addYears($years);
}
public function addYears(int $years) : self
{
return $this->midnight(TimeZone::UTC())->add(RelativeTimeUnit::years($years))->day();
}
/**
* @infection-ignore-all
*
* @deprecated Use `subYears` instead. Will be removed with 2.0
*/
public function minusYears(int $years) : self
{
return $this->subYears($years);
}
public function subYears(int $years) : self
{
return $this->midnight(TimeZone::UTC())->sub(RelativeTimeUnit::years($years))->day();
}
public function previous() : self
{
return $this->midnight(TimeZone::UTC())->sub(TimeUnit::day())->day();
}
public function next() : self
{
return $this->midnight(TimeZone::UTC())->add(TimeUnit::day())->day();
}
public function midnight(TimeZone $timeZone) : DateTime
{
return new DateTime($this, new Time(0, 0, 0, 0), $timeZone);
}
public function noon(TimeZone $timeZone) : DateTime
{
return new DateTime($this, new Time(12, 0, 0, 0), $timeZone);
}
public function endOfDay(TimeZone $timeZone) : DateTime
{
return new DateTime($this, new Time(23, 59, 59, 999999), $timeZone);
}
public function setTime(Time $time, TimeZone $timeZone) : DateTime
{
return new DateTime(
$this,
$time,
$timeZone
);
}
public function month() : Month
{
return $this->month;
}
public function year() : Year
{
return $this->month->year();
}
public function number() : int
{
return $this->number;
}
public function weekDay() : WeekDay
{
return new WeekDay((int) $this->toDateTimeImmutable()->format('N'));
}
/**
* Week of year starting from 1.
*/
public function weekOfYear() : int
{
return (int) $this->toDateTimeImmutable()->format('W');
}
/**
* Week of year starting from 1.
*/
public function weekOfMonth() : int
{
return $this->weekOfYear() - $this->month->days()->first()->weekOfYear() + 1;
}
/**
* Day of year starting from 1.
*/
public function dayOfYear() : int
{
return \intval($this->toDateTimeImmutable()->format('z')) + 1;
}
public function isWeekend() : bool
{
return $this->weekDay()->isWeekend();
}
public function toDateTimeImmutable() : \DateTimeImmutable
{
return new \DateTimeImmutable(\sprintf(
'%d-%d-%d 00:00:00.000000 UTC',
$this->month->year()->number(),
$this->month->number(),
$this->number
));
}
public function format(string $format) : string
{
return $this->toDateTimeImmutable()->format($format);
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $day) : bool
{
return $this->isEqualTo($day);
}
public function isEqualTo(self $day) : bool
{
return $this->number === $day->number()
&& $this->month->isEqualTo($day->month());
}
public function isBefore(self $day) : bool
{
if ($this->month->isBefore($day->month())) {
return true;
}
if ($this->month->isAfter($day->month())) {
return false;
}
return $this->number < $day->number();
}
/**
* @infection-ignore-all
*
* @deprecated Use `isBeforeOrEqualTo` instead. Will be removed with 2.0
*/
public function isBeforeOrEqual(self $day) : bool
{
return $this->isBeforeOrEqualTo($day);
}
public function isBeforeOrEqualTo(self $day) : bool
{
if ($this->month->isBefore($day->month())) {
return true;
}
if ($this->month->isAfter($day->month())) {
return false;
}
return $this->number <= $day->number();
}
public function isAfter(self $day) : bool
{
if ($this->month->isAfter($day->month())) {
return true;
}
if ($this->month->isBefore($day->month())) {
return false;
}
return $this->number > $day->number();
}
/**
* @infection-ignore-all
*
* @deprecated Use `isAfterOrEqualTo` instead. Will be removed with 2.0
*/
public function isAfterOrEqual(self $day) : bool
{
return $this->isAfterOrEqualTo($day);
}
public function isAfterOrEqualTo(self $day) : bool
{
if ($this->month->isAfter($day->month())) {
return true;
}
if ($this->month->isBefore($day->month())) {
return false;
}
return $this->number >= $day->number();
}
public function iterate(self $destination, Interval $interval) : Days
{
return $this->isAfter($destination)
? $this->since($destination, $interval)
: $this->until($destination, $interval);
}
public function until(self $day, Interval $interval) : Days
{
if ($this->isAfter($day)) {
throw new InvalidArgumentException(
\sprintf(
'%d %s %d is after %d %s %d',
$this->number,
$this->month->name(),
$this->month->year()->number(),
$day->number(),
$day->month()->name(),
$day->month()->year()->number(),
)
);
}
return Days::fromDateTimeIterator(
new DateTimeIntervalIterator(
$this->midnight(TimeZone::UTC()),
$day->midnight(TimeZone::UTC()),
TimeUnit::day(),
$interval
)
);
}
public function since(self $day, Interval $interval) : Days
{
if ($this->isBefore($day)) {
throw new InvalidArgumentException(
\sprintf(
'%d %s %d is before %d %s %d',
$this->number,
$this->month->name(),
$this->month->year()->number(),
$day->number(),
$day->month()->name(),
$day->month()->year()->number(),
)
);
}
return Days::fromDateTimeIterator(
new DateTimeIntervalIterator(
$this->midnight(TimeZone::UTC()),
$day->midnight(TimeZone::UTC()),
TimeUnit::day()->toNegative(),
$interval
)
);
}
public function distance(self $to) : TimeUnit
{
return (new TimePeriod($this->midnight(TimeZone::UTC()), $to->midnight(TimeZone::UTC())))->distance();
}
public function quarter() : Quarter
{
return $this->year()->quarter((int) \ceil($this->month->number() / 3));
}
public function compareTo(self $day) : int
{
if ($this->isEqualTo($day)) {
return 0;
}
return $this->isBefore($day)
? -1
: 1;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Days.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*
* @implements \IteratorAggregate<Day>
*/
final class Days implements \Countable, \IteratorAggregate
{
/**
* @var \Iterator<int|string, Day>
*/
private \Iterator $days;
/**
* @param \Iterator<int|string, Day> $days
*/
private function __construct(\Iterator $days)
{
$this->days = $days;
}
/**
* @psalm-pure
*/
public static function fromArray(Day ...$days) : self
{
/** @psalm-suppress ImpureMethodCall */
return new self(new \ArrayIterator($days));
}
/**
* @psalm-pure
*/
public static function fromDateTimeIterator(DateTimeIntervalIterator $iterator) : self
{
/** @psalm-suppress ImpureMethodCall */
return new self(DaysIterator::fromDateTimeIterator($iterator));
}
/**
* @return array<Day>
*
* @psalm-suppress ImpureFunctionCall
*/
public function all() : array
{
return \iterator_to_array($this->days);
}
/**
* @psalm-template MapResultType
*
* @param callable(Day $day) : MapResultType $iterator
*
* @psalm-param pure-callable(Day $day) : MapResultType $iterator
*
* @return array<MapResultType>
*/
public function map(callable $iterator) : array
{
return \array_map($iterator, $this->all());
}
/**
* @psalm-suppress InvalidScalarArgument
*
* @param callable(Day $day) : bool $iterator
*
* @psalm-param pure-callable(Day $day) : bool $iterator
*/
public function filter(callable $iterator) : self
{
return new self(new \CallbackFilterIterator($this->days, $iterator));
}
public function count() : int
{
return \iterator_count($this->days);
}
/**
* @return \Traversable<int|string, Day>
*/
public function getIterator() : \Traversable
{
return $this->days;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/DaysIterator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
final class DaysIterator extends \IteratorIterator
{
/**
* @param \Traversable<DateTime> $iterator
*/
private function __construct(\Traversable $iterator)
{
parent::__construct($iterator);
}
/**
* @psalm-suppress MixedArgumentTypeCoercion
*/
public static function fromDateTimeIterator(DateTimeIntervalIterator $datePeriod) : self
{
return new self($datePeriod);
}
public function current() : ?Day
{
/** @var null|DateTime|Day $current */
$current = parent::current();
if ($current === null) {
return null;
}
if ($current instanceof Day) {
return $current;
}
return $current->day();
}
public function reverse() : self
{
/** @phpstan-ignore-next-line */
return new self(new \ArrayIterator(\array_reverse(\iterator_to_array($this))));
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/GregorianCalendar.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*/
final class GregorianCalendar implements Calendar
{
private TimeZone $timeZone;
public function __construct(TimeZone $timeZone)
{
$this->timeZone = $timeZone;
}
/**
* @psalm-pure
*/
public static function UTC() : self
{
return new self(TimeZone::UTC());
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureFunctionCall
*/
public static function systemDefault() : self
{
return new self(TimeZone::fromString(\date_default_timezone_get()));
}
public function timeZone() : TimeZone
{
return $this->timeZone;
}
public function currentYear() : Year
{
return $this->now()->year();
}
public function currentMonth() : Month
{
return $this->now()->month();
}
public function currentDay() : Day
{
return $this->now()->day();
}
public function now() : DateTime
{
if ($this->timeZone->name() === 'UTC') {
return DateTime::fromDateTime(new \DateTimeImmutable('now', new \DateTimeZone('UTC')));
}
return DateTime::fromDateTime(new \DateTimeImmutable('now', new \DateTimeZone('UTC')))
->toTimeZone($this->timeZone);
}
public function yesterday() : DateTime
{
return $this->now()->yesterday();
}
public function tomorrow() : DateTime
{
return $this->now()->tomorrow();
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/GregorianCalendarStub.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*
* @codeCoverageIgnore
*/
final class GregorianCalendarStub implements Calendar
{
private TimeZone $timeZone;
private ?DateTime $currentDate;
public function __construct(TimeZone $timeZone, ?DateTime $currentDate = null)
{
$this->timeZone = $timeZone;
$this->currentDate = $currentDate;
}
/**
* @psalm-pure
*/
public static function UTC(?DateTime $currentDate = null) : self
{
return new self(TimeZone::UTC(), $currentDate);
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureFunctionCall
*/
public static function systemDefault(?DateTime $currentDate = null) : self
{
return new self(TimeZone::fromString(\date_default_timezone_get()), $currentDate);
}
public function timeZone() : TimeZone
{
return $this->timeZone;
}
public function currentYear() : Year
{
return $this->now()->year();
}
public function currentMonth() : Month
{
return $this->now()->month();
}
public function currentDay() : Day
{
return $this->now()->day();
}
public function now() : DateTime
{
return $this->currentDate
? $this->currentDate
: DateTime::fromDateTime(new \DateTimeImmutable('now', $this->timeZone->toDateTimeZone()));
}
public function yesterday() : DateTime
{
return $this->now()->yesterday();
}
public function tomorrow() : DateTime
{
return $this->now()->tomorrow();
}
/**
* @psalm-suppress InaccessibleProperty
*/
public function setNow(DateTime $dateTime) : void
{
$this->currentDate = $dateTime;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Interval.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*/
final class Interval
{
public const CLOSED = 0;
public const LEFT_OPEN = 1;
public const RIGHT_OPEN = 2;
public const OPEN = 4;
private int $type;
private function __construct(int $type)
{
$this->type = $type;
}
/**
* A <= x <= B.
*
* @psalm-pure
*/
public static function closed() : self
{
return new self(self::CLOSED);
}
/**
* A <= x < B.
*
* @psalm-pure
*/
public static function rightOpen() : self
{
return new self(self::RIGHT_OPEN);
}
/**
* A < x <= B.
*
* @psalm-pure
*/
public static function leftOpen() : self
{
return new self(self::LEFT_OPEN);
}
/**
* A < x < B.
*
* @psalm-pure
*/
public static function open() : self
{
return new self(self::OPEN);
}
public function isOpen() : bool
{
return $this->type === self::OPEN;
}
public function isLeftOpen() : bool
{
return $this->type === self::LEFT_OPEN || $this->type === self::OPEN;
}
public function isRightOpen() : bool
{
return $this->type === self::RIGHT_OPEN || $this->type === self::OPEN;
}
public function isClosed() : bool
{
return $this->type === self::CLOSED;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/LeapSecond.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class LeapSecond
{
private DateTime $dateTime;
private TimeUnit $offsetTAI;
public function __construct(DateTime $dateTime, TimeUnit $offsetTAI)
{
if ($offsetTAI->inSeconds() < 10) {
throw new InvalidArgumentException('Leap second TAI offset must be greater or equal 10');
}
$this->dateTime = $dateTime;
$this->offsetTAI = $offsetTAI;
}
/**
* @return array{dateTime: DateTime, offsetTAI: TimeUnit}
*/
public function __serialize() : array
{
return [
'dateTime' => $this->dateTime,
'offsetTAI' => $this->offsetTAI,
];
}
public function dateTime() : DateTime
{
return $this->dateTime;
}
public function offsetTAI() : TimeUnit
{
return $this->offsetTAI;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $second) : bool
{
return $this->isEqualTo($second);
}
public function isEqualTo(self $second) : bool
{
return $this->dateTime->isEqualTo($second->dateTime()) && $this->offsetTAI->isEqualTo($second->offsetTAI());
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/LeapSeconds.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class LeapSeconds
{
private static ?self $instance = null;
private DateTime $listExpirationDate;
/**
* @var array<LeapSecond>
*/
private array $leapSeconds;
private function __construct(DateTime $listExpiration, LeapSecond ...$leapSeconds)
{
$this->leapSeconds = $leapSeconds;
$this->listExpirationDate = $listExpiration;
}
/**
* List taken from https://www.ietf.org/timezones/data/leap-seconds.list.
*
* Leap seconds are announced by https://www.iers.org/ (The International Earth Rotation and Reference Systems Service)
* in their Bulletin C, list of all available releases https://www.iers.org/IERS/EN/Publications/Bulletins/bulletins.html
*
* @psalm-pure
*
* @psalm-suppress ImpureStaticProperty
*/
public static function load() : self
{
if (self::$instance instanceof self) {
return self::$instance;
}
self::$instance = new self(
DateTime::fromString('2026-06-28 00:00:00 UTC'),
new LeapSecond(DateTime::fromString('1972-01-01 00:00:00 UTC'), TimeUnit::seconds(10)),
new LeapSecond(DateTime::fromString('1972-07-01 00:00:00 UTC'), TimeUnit::seconds(11)),
new LeapSecond(DateTime::fromString('1973-01-01 00:00:00 UTC'), TimeUnit::seconds(12)),
new LeapSecond(DateTime::fromString('1974-01-01 00:00:00 UTC'), TimeUnit::seconds(13)),
new LeapSecond(DateTime::fromString('1975-01-01 00:00:00 UTC'), TimeUnit::seconds(14)),
new LeapSecond(DateTime::fromString('1976-01-01 00:00:00 UTC'), TimeUnit::seconds(15)),
new LeapSecond(DateTime::fromString('1977-01-01 00:00:00 UTC'), TimeUnit::seconds(16)),
new LeapSecond(DateTime::fromString('1978-01-01 00:00:00 UTC'), TimeUnit::seconds(17)),
new LeapSecond(DateTime::fromString('1979-01-01 00:00:00 UTC'), TimeUnit::seconds(18)),
new LeapSecond(DateTime::fromString('1980-01-01 00:00:00 UTC'), TimeUnit::seconds(19)),
new LeapSecond(DateTime::fromString('1981-07-01 00:00:00 UTC'), TimeUnit::seconds(20)),
new LeapSecond(DateTime::fromString('1982-07-01 00:00:00 UTC'), TimeUnit::seconds(21)),
new LeapSecond(DateTime::fromString('1983-07-01 00:00:00 UTC'), TimeUnit::seconds(22)),
new LeapSecond(DateTime::fromString('1985-07-01 00:00:00 UTC'), TimeUnit::seconds(23)),
new LeapSecond(DateTime::fromString('1988-01-01 00:00:00 UTC'), TimeUnit::seconds(24)),
new LeapSecond(DateTime::fromString('1990-01-01 00:00:00 UTC'), TimeUnit::seconds(24)),
new LeapSecond(DateTime::fromString('1991-01-01 00:00:00 UTC'), TimeUnit::seconds(25)),
new LeapSecond(DateTime::fromString('1992-07-01 00:00:00 UTC'), TimeUnit::seconds(26)),
new LeapSecond(DateTime::fromString('1993-07-01 00:00:00 UTC'), TimeUnit::seconds(27)),
new LeapSecond(DateTime::fromString('1994-07-01 00:00:00 UTC'), TimeUnit::seconds(28)),
new LeapSecond(DateTime::fromString('1996-01-01 00:00:00 UTC'), TimeUnit::seconds(29)),
new LeapSecond(DateTime::fromString('1997-07-01 00:00:00 UTC'), TimeUnit::seconds(30)),
new LeapSecond(DateTime::fromString('1999-01-01 00:00:00 UTC'), TimeUnit::seconds(31)),
new LeapSecond(DateTime::fromString('2006-01-01 00:00:00 UTC'), TimeUnit::seconds(32)),
new LeapSecond(DateTime::fromString('2009-01-01 00:00:00 UTC'), TimeUnit::seconds(33)),
new LeapSecond(DateTime::fromString('2012-07-01 00:00:00 UTC'), TimeUnit::seconds(34)),
new LeapSecond(DateTime::fromString('2015-07-01 00:00:00 UTC'), TimeUnit::seconds(36)),
new LeapSecond(DateTime::fromString('2017-01-01 00:00:00 UTC'), TimeUnit::seconds(37)),
);
return self::$instance;
}
public function expirationDate() : DateTime
{
return $this->listExpirationDate;
}
public function since(DateTime $dateTime) : self
{
/* @phpstan-ignore-next-line */
return $this->filter(function (LeapSecond $leapSecond) use ($dateTime) : bool {
return $dateTime
->toTimeZone(TimeZone::UTC())
->isBefore($leapSecond->dateTime());
});
}
public function until(DateTime $dateTime) : self
{
/* @phpstan-ignore-next-line */
return $this->filter(function (LeapSecond $leapSecond) use ($dateTime) : bool {
return $dateTime
->toTimeZone(TimeZone::UTC())
->isAfterOrEqualTo($leapSecond->dateTime());
});
}
public function findAllBetween(TimePeriod $timePeriod) : self
{
/* @phpstan-ignore-next-line */
return $this->filter(function (LeapSecond $leapSecond) use ($timePeriod) : bool {
return $timePeriod->start()
->toTimeZone(TimeZone::UTC())
->isBeforeOrEqualTo($leapSecond->dateTime())
&& $timePeriod->end()
->toTimeZone(TimeZone::UTC())
->isAfter($leapSecond->dateTime());
});
}
public function offsetTAI() : TimeUnit
{
return $this->leapSeconds[\count($this->leapSeconds) - 1]->offsetTAI();
}
/**
* @param callable(LeapSecond $leapSecond) : bool $filter
*
* @psalm-param pure-callable(LeapSecond $leapSecond) : bool $filter
*/
public function filter(callable $filter) : self
{
return new self(
$this->expirationDate(),
...\array_filter($this->all(), $filter)
);
}
public function count() : TimeUnit
{
return TimeUnit::seconds(\count($this->all()));
}
/**
* @return array<LeapSecond>
*/
public function all() : array
{
return $this->leapSeconds;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Month.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\RelativeTimeUnit;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class Month
{
private const TOTAL_MONTHS = 12;
private Year $year;
private MonthDays $days;
private int $number;
public function __construct(Year $year, int $number)
{
if ($number <= 0 || $number > self::TOTAL_MONTHS) {
throw new InvalidArgumentException('Month number must be greater or equal 1 and less or equal than 12');
}
$this->year = $year;
$this->number = $number;
$this->days = new MonthDays($this);
}
/**
* @psalm-pure
*/
public static function create(int $year, int $month) : self
{
return new self(
new Year($year),
$month
);
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
*/
public static function fromDateTime(\DateTimeInterface $dateTime) : self
{
return new self(
new Year((int) $dateTime->format('Y')),
(int) $dateTime->format('m')
);
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
*/
public static function fromString(string $date) : self
{
try {
return self::fromDateTime(new \DateTimeImmutable($date));
} catch (\Exception $e) {
throw new InvalidArgumentException("Value \"{$date}\" is not valid month format.");
}
}
/**
* @return array{year: int, month: int}
*/
public function __debugInfo() : array
{
return [
'year' => $this->year()->number(),
'month' => $this->number(),
];
}
/**
* @return array{year: Year, number: int}
*/
public function __serialize() : array
{
return [
'year' => $this->year(),
'number' => $this->number(),
];
}
/**
* @param array{year: Year, number: int} $data
*/
public function __unserialize(array $data) : void
{
$this->year = $data['year'];
$this->number = $data['number'];
$this->days = new MonthDays($this);
}
public function __toString() : string
{
return $this->toString();
}
public function toString() : string
{
return $this->toDateTimeImmutable()->format('Y-m');
}
public function previous() : self
{
return $this->subMonths(1);
}
public function next() : self
{
return $this->addMonths(1);
}
/**
* @infection-ignore-all
*
* @deprecated Use `add` instead. Will be removed with 2.0
*/
public function plus(int $years, int $months) : self
{
return $this->add($years, $months);
}
public function add(int $years, int $months) : self
{
$month = $this;
if ($months !== 0) {
$month = $month->addMonths($months);
}
if ($years !== 0) {
$month = $month->addYears($years);
}
return $month;
}
/**
* @infection-ignore-all
*
* @deprecated Use `sub` instead. Will be removed with 2.0
*/
public function minus(int $years, int $months) : self
{
return $this->sub($years, $months);
}
public function sub(int $years, int $months) : self
{
$month = $this;
if ($months !== 0) {
$month = $month->subMonths($months);
}
if ($years !== 0) {
$month = $month->subYears($years);
}
return $month;
}
/**
* @infection-ignore-all
*
* @deprecated Use `addMonths` instead. Will be removed with 2.0
*/
public function plusMonths(int $months) : self
{
return $this->addMonths($months);
}
public function addMonths(int $months) : self
{
$years = (int) ($months / self::TOTAL_MONTHS);
$monthsRemainder = $months % self::TOTAL_MONTHS;
$year = $this->year->number() + $years;
$month = $this->number() + $monthsRemainder;
if ($month > self::TOTAL_MONTHS) {
$year += ((int) ($month / self::TOTAL_MONTHS));
$month %= self::TOTAL_MONTHS;
}
if ($month === 0) {
$month = 12;
}
return new self(new Year($year), $month);
}
/**
* @infection-ignore-all
*
* @deprecated Use `subMonths` instead. Will be removed with 2.0
*/
public function minusMonths(int $months) : self
{
return $this->subMonths($months);
}
public function subMonths(int $months) : self
{
$years = (int) ($months / self::TOTAL_MONTHS);
$monthsRemainder = $months % self::TOTAL_MONTHS;
$year = $this->year->number() - $years;
$month = $this->number() - $monthsRemainder;
if ($month === 0) {
$month = self::TOTAL_MONTHS;
$year--;
}
if ($month < 0) {
$month = self::TOTAL_MONTHS - \abs($month);
$year--;
}
return new self(new Year($year), $month);
}
/**
* @infection-ignore-all
*
* @deprecated Use `addYears` instead. Will be removed with 2.0
*/
public function plusYears(int $years) : self
{
return $this->addYears($years);
}
public function addYears(int $years) : self
{
return new self($this->year->add($years), $this->number);
}
/**
* @infection-ignore-all
*
* @deprecated Use `subYears` instead. Will be removed with 2.0
*/
public function minusYears(int $years) : self
{
return $this->subYears($years);
}
public function subYears(int $years) : self
{
return new self($this->year->sub($years), $this->number);
}
public function firstDay() : Day
{
return $this->days()->first();
}
public function lastDay() : Day
{
return $this->days()->last();
}
public function number() : int
{
return $this->number;
}
public function year() : Year
{
return $this->year;
}
public function days() : MonthDays
{
return $this->days;
}
public function numberOfDays() : int
{
return 31 - (($this->number == 2) ?
(3 - (int) $this->year->isLeap()) : (($this->number - 1) % 7 % 2));
}
public function shortName() : string
{
return $this->toDateTimeImmutable()->format('M');
}
public function name() : string
{
return $this->toDateTimeImmutable()->format('F');
}
public function toDateTimeImmutable() : \DateTimeImmutable
{
return new \DateTimeImmutable(\sprintf(
'%d-%d-01 00:00:00.000000 UTC',
$this->year()->number(),
$this->number()
));
}
public function iterate(self $destination, Interval $interval) : Months
{
return $this->isAfter($destination)
? $this->since($destination, $interval)
: $this->until($destination, $interval);
}
public function until(self $month, Interval $interval) : Months
{
if ($this->isAfter($month)) {
throw new InvalidArgumentException(
\sprintf(
'%s %d is after %s %d',
$this->name(),
$this->year->number(),
$month->name(),
$month->year->number(),
)
);
}
return Months::fromDateTimeIterator(
new DateTimeIntervalIterator(
$this->firstDay()->midnight(TimeZone::UTC()),
$month->firstDay()->midnight(TimeZone::UTC()),
RelativeTimeUnit::month(),
$interval
)
);
}
public function since(self $month, Interval $interval) : Months
{
if ($this->isBefore($month)) {
throw new InvalidArgumentException(
\sprintf(
'%s %d is before %s %d',
$this->name(),
$this->year->number(),
$month->name(),
$month->year->number(),
)
);
}
return Months::fromDateTimeIterator(
new DateTimeIntervalIterator(
$month->firstDay()->midnight(TimeZone::UTC()),
$this->firstDay()->midnight(TimeZone::UTC()),
RelativeTimeUnit::month(),
$interval
)
);
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $month) : bool
{
return $this->isEqualTo($month);
}
public function isEqualTo(self $month) : bool
{
return $this->number() == $month->number()
&& $this->year()->isEqualTo($month->year());
}
public function isBefore(self $month) : bool
{
if ($this->year()->isBefore($month->year())) {
return true;
}
if ($this->year()->isAfter($month->year())) {
return false;
}
return $this->number() < $month->number();
}
/**
* @infection-ignore-all
*
* @deprecated Use `isBeforeOrEqualTo` instead. Will be removed with 2.0
*/
public function isBeforeOrEqual(self $month) : bool
{
return $this->isBeforeOrEqualTo($month);
}
public function isBeforeOrEqualTo(self $month) : bool
{
if ($this->year()->isBefore($month->year())) {
return true;
}
if ($this->year()->isAfter($month->year())) {
return false;
}
return $this->number() <= $month->number();
}
public function isAfter(self $month) : bool
{
if ($this->year()->isAfter($month->year())) {
return true;
}
if ($this->year()->isBefore($month->year())) {
return false;
}
return $this->number() > $month->number();
}
/**
* @infection-ignore-all
*
* @deprecated Use `isAfterOrEqualTo` instead. Will be removed with 2.0
*/
public function isAfterOrEqual(self $month) : bool
{
return $this->isAfterOrEqualTo($month);
}
public function isAfterOrEqualTo(self $month) : bool
{
if ($this->year()->isAfter($month->year())) {
return true;
}
if ($this->year()->isBefore($month->year())) {
return false;
}
return $this->number() >= $month->number();
}
public function distance(self $to) : TimeUnit
{
return (new TimePeriod($this->firstDay()->midnight(TimeZone::UTC()), $to->firstDay()->midnight(TimeZone::UTC())))->distance();
}
public function quarter() : Quarter
{
return $this->year->quarter((int) \ceil($this->number / 3));
}
public function compareTo(self $month) : int
{
if ($this->isEqualTo($month)) {
return 0;
}
return $this->isBefore($month)
? -1
: 1;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/MonthDays.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*/
final class MonthDays implements \Countable
{
private Month $month;
public function __construct(Month $month)
{
$this->month = $month;
}
public function count() : int
{
return $this->month->numberOfDays();
}
public function first() : Day
{
return new Day($this->month, 1);
}
public function last() : Day
{
return new Day($this->month, $this->month->numberOfDays());
}
/**
* @return array<int, Day>
*/
public function all() : array
{
/** @psalm-suppress ImpureFunctionCall */
return \array_map(
fn (int $dayNumber) : Day => new Day($this->month, $dayNumber),
\range(1, $this->month->numberOfDays())
);
}
/**
* @param callable(Day $day) : void $iterator
*
* @psalm-param pure-callable(Day $day) : void $iterator
*
* @return array<mixed>
*/
public function map(callable $iterator) : array
{
return \array_map(
$iterator,
$this->all()
);
}
/**
* @param callable(Day $day) : bool $iterator
*
* @psalm-param pure-callable(Day $day) : bool $iterator
*
* @return Days
*/
public function filter(callable $iterator) : Days
{
return Days::fromArray(
...\array_filter(
$this->all(),
$iterator
)
);
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Months.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*
* @implements \IteratorAggregate<Month>
*/
final class Months implements \Countable, \IteratorAggregate
{
/**
* @var \Iterator<int|string, Month>
*/
private \Iterator $months;
/**
* @param \Iterator<int|string, Month> $months
*/
private function __construct(\Iterator $months)
{
$this->months = $months;
}
/**
* @psalm-pure
*/
public static function fromArray(Month ...$days) : self
{
/** @psalm-suppress ImpureMethodCall */
return new self(new \ArrayIterator($days));
}
/**
* @psalm-pure
*/
public static function fromDateTimeIterator(DateTimeIntervalIterator $iterator) : self
{
/** @psalm-suppress ImpureMethodCall */
return new self(MonthsIterator::fromDateTimeIterator($iterator));
}
/**
* @return array<Month>
*
* @psalm-suppress ImpureFunctionCall
*/
public function all() : array
{
return \iterator_to_array($this->months);
}
/**
* @param callable(Month $month) : mixed $iterator
*
* @psalm-param pure-callable(Month $month) : mixed $iterator
*
* @return array<mixed>
*/
public function map(callable $iterator) : array
{
return \array_map($iterator, $this->all());
}
/**
* @psalm-suppress InvalidScalarArgument
*
* @param callable(Month $month) : bool $iterator
*
* @psalm-param pure-callable(Month $month) : bool $iterator
*/
public function filter(callable $iterator) : self
{
return new self(new \CallbackFilterIterator($this->months, $iterator));
}
public function count() : int
{
return \iterator_count($this->months);
}
/**
* @return \Traversable<int|string, Month>
*/
public function getIterator() : \Traversable
{
return $this->months;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/MonthsIterator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
final class MonthsIterator extends \IteratorIterator
{
/**
* @param \Traversable<DateTime> $iterator
*/
private function __construct(\Traversable $iterator)
{
parent::__construct($iterator);
}
/**
* @psalm-suppress MixedArgumentTypeCoercion
*/
public static function fromDateTimeIterator(DateTimeIntervalIterator $iterator) : self
{
return new self($iterator);
}
public function current() : ?Month
{
/** @var null|DateTime|Month $current */
$current = parent::current();
if ($current === null) {
return null;
}
if ($current instanceof Month) {
return $current;
}
return $current->month();
}
public function reverse() : self
{
/** @phpstan-ignore-next-line */
return new self(new \ArrayIterator(\array_reverse(\iterator_to_array($this))));
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Psr20CalendarAdapter.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Psr\Clock\ClockInterface;
final class Psr20CalendarAdapter implements ClockInterface
{
public function __construct(private readonly Calendar $calendar)
{
}
public function now() : \DateTimeImmutable
{
return $this->calendar->now()->toDateTimeImmutable();
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Quarter.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
/**
* @psalm-immutable
*/
final class Quarter
{
private int $number;
private Months $months;
public function __construct(int $number, Months $months)
{
if ($number < 1 || $number > 4) {
throw new InvalidArgumentException('Quarter number must be greater or equal 1 and less or equal than 4');
}
if (\count($months) !== 3) {
throw new InvalidArgumentException('Quarter must have exactly 3 months');
}
switch ($number) {
case 1:
/* @phpstan-ignore-next-line */
if ($months->map(fn (Month $month) => $month->number()) !== [1, 2, 3]) {
throw new InvalidArgumentException('Quarter 1 must must have Jan, Feb and Mar');
}
break;
case 2:
/* @phpstan-ignore-next-line */
if ($months->map(fn (Month $month) => $month->number()) !== [4, 5, 6]) {
throw new InvalidArgumentException('Quarter 2 must must have Apr, May and Jun');
}
break;
case 3:
/* @phpstan-ignore-next-line */
if ($months->map(fn (Month $month) => $month->number()) !== [7, 8, 9]) {
throw new InvalidArgumentException('Quarter 3 must must have Jul, Aug and Sep');
}
break;
case 4:
/* @phpstan-ignore-next-line */
if ($months->map(fn (Month $month) => $month->number()) !== [10, 11, 12]) {
throw new InvalidArgumentException('Quarter 4 must must have Oct, Nov and Dec');
}
break;
}
$this->number = $number;
$this->months = $months;
}
public function number() : int
{
return $this->number;
}
public function months() : Months
{
return $this->months;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Time.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class Time
{
private const PRECISION_MICROSECOND = 6;
private int $hour;
private int $minute;
private int $second;
private int $microsecond;
public function __construct(int $hour, int $minute, int $second, int $microsecond = 0)
{
if ($hour < 0 || $hour > 23) {
throw new InvalidArgumentException('Hour must be greater or equal 0 and less or equal than 23');
}
if ($minute < 0 || $minute >= 60) {
throw new InvalidArgumentException('Minut must be greater or equal 0 and less than 60');
}
if ($second < 0 || $second >= 60) {
throw new InvalidArgumentException('Second must be greater or equal 0 and less than 60');
}
if ($microsecond < 0 || $microsecond >= 1000000) {
throw new InvalidArgumentException('Microsecond must be greater or equal 0 and less than 1000000');
}
$this->hour = $hour;
$this->minute = $minute;
$this->second = $second;
$this->microsecond = $microsecond;
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
* @psalm-suppress PossiblyNullArrayAccess
* @psalm-suppress PossiblyInvalidArgument
*/
public static function fromDateTime(\DateTimeInterface $dateTime) : self
{
/**
* @phpstan-ignore-next-line
*/
[$hour, $minute, $second, $microsecond] = \sscanf($dateTime->format('H-i-s.u'), '%d-%d-%d.%d');
/** @phpstan-ignore-next-line */
return new self($hour, $minute, $second, $microsecond);
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
*/
public static function fromString(string $time) : self
{
try {
return self::fromDateTime(new \DateTimeImmutable($time));
} catch (\Exception $e) {
throw new InvalidArgumentException("Value \"{$time}\" is not valid time format.");
}
}
/**
* @return array{hour: int, minute: int, second: int, microsecond: int}
*/
public function __debugInfo() : array
{
return [
'hour' => $this->hour,
'minute' => $this->minute,
'second' => $this->second,
'microsecond' => $this->microsecond,
];
}
/**
* @return array{hour: int, minute: int, second: int, microsecond: int}
*/
public function __serialize() : array
{
return [
'hour' => $this->hour,
'minute' => $this->minute,
'second' => $this->second,
'microsecond' => $this->microsecond,
];
}
/**
* @param array{hour: int, minute: int, second: int, microsecond: int} $data
*/
public function __unserialize(array $data) : void
{
$this->hour = $data['hour'];
$this->minute = $data['minute'];
$this->second = $data['second'];
$this->microsecond = $data['microsecond'];
}
public function format(string $format) : string
{
return $this->toDateTimeImmutable()->format($format);
}
public function toTimeUnit() : TimeUnit
{
return TimeUnit::positive($this->second, $this->microsecond)
->add(TimeUnit::minutes($this->minute))
->add(TimeUnit::hours($this->hour));
}
public function toString() : string
{
return \str_pad((string) $this->hour, 2, '0', STR_PAD_LEFT) . ':'
. \str_pad((string) $this->minute, 2, '0', STR_PAD_LEFT) . ':'
. \str_pad((string) $this->second, 2, '0', STR_PAD_LEFT) . '.'
. \str_pad((string) $this->microsecond, self::PRECISION_MICROSECOND, '0', STR_PAD_LEFT);
}
public function hour() : int
{
return $this->hour;
}
public function minute() : int
{
return $this->minute;
}
public function second() : int
{
return $this->second;
}
public function microsecond() : int
{
return $this->microsecond;
}
public function millisecond() : int
{
return \intval($this->microsecond / 1000);
}
public function isAM() : bool
{
return $this->toDateTimeImmutable()->format('a') === 'am';
}
public function isPM() : bool
{
return $this->toDateTimeImmutable()->format('a') === 'pm';
}
/**
* @infection-ignore-all
*
* @deprecated Use `isAfter` instead. Will be removed with 2.0
*/
public function isGreaterThan(self $time) : bool
{
return $this->isAfter($time);
}
public function isAfter(self $time) : bool
{
$dateTimeImmutable = $this->toDateTimeImmutable();
$nextDateTimeImmutable = $dateTimeImmutable->setTime($time->hour, $time->minute, $time->second, $time->microsecond);
return $dateTimeImmutable > $nextDateTimeImmutable;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isAfterOrEqualTo` instead. Will be removed with 2.0
*/
public function isGreaterThanEq(self $time) : bool
{
return $this->isAfterOrEqualTo($time);
}
public function isAfterOrEqualTo(self $time) : bool
{
$dateTimeImmutable = $this->toDateTimeImmutable();
$nextDateTimeImmutable = $dateTimeImmutable->setTime($time->hour, $time->minute, $time->second, $time->microsecond);
return $dateTimeImmutable >= $nextDateTimeImmutable;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $time) : bool
{
return $this->isEqualTo($time);
}
public function isEqualTo(self $time) : bool
{
$dateTimeImmutable = $this->toDateTimeImmutable();
$nextDateTimeImmutable = $dateTimeImmutable->setTime($time->hour, $time->minute, $time->second, $time->microsecond);
return $dateTimeImmutable == $nextDateTimeImmutable;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isBefore` instead. Will be removed with 2.0
*/
public function isLessThan(self $time) : bool
{
return $this->isBefore($time);
}
public function isBefore(self $time) : bool
{
$dateTimeImmutable = $this->toDateTimeImmutable();
$nextDateTimeImmutable = $dateTimeImmutable->setTime($time->hour, $time->minute, $time->second, $time->microsecond);
return $dateTimeImmutable < $nextDateTimeImmutable;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isBeforeOrEqualTo` instead. Will be removed with 2.0
*/
public function isLessThanEq(self $time) : bool
{
return $this->isBeforeOrEqualTo($time);
}
public function isBeforeOrEqualTo(self $time) : bool
{
$dateTimeImmutable = $this->toDateTimeImmutable();
$nextDateTimeImmutable = $dateTimeImmutable->setTime($time->hour, $time->minute, $time->second, $time->microsecond);
return $dateTimeImmutable <= $nextDateTimeImmutable;
}
public function isMidnight() : bool
{
return $this->hour() === 0
&& $this->minute() === 0
&& $this->second() === 0
&& $this->microsecond() === 0;
}
public function isNotMidnight() : bool
{
return !$this->isMidnight();
}
public function add(TimeUnit $timeUnit) : self
{
return self::fromDateTime($this->toDateTimeImmutable()->add($timeUnit->toDateInterval()));
}
public function sub(TimeUnit $timeUnit) : self
{
/** @psalm-suppress PossiblyFalseArgument */
return self::fromDateTime($this->toDateTimeImmutable()->sub($timeUnit->toDateInterval()));
}
public function compareTo(self $time) : int
{
if ($this->isEqualTo($time)) {
return 0;
}
return $this->isBefore($time)
? -1
: 1;
}
private function toDateTimeImmutable() : \DateTimeImmutable
{
return (new \DateTimeImmutable('now', new \DateTimeZone('UTC')))
->setTime(
$this->hour,
$this->minute,
$this->second,
$this->microsecond
);
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/TimeEpoch.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class TimeEpoch
{
public const UNIX = 0;
public const UTC = 1;
public const TAI = 2;
public const GPS = 3;
private int $type;
private DateTime $dateTime;
private function __construct(int $type, DateTime $dateTime)
{
$this->type = $type;
$this->dateTime = $dateTime;
}
/**
* Unix Epoch, started at 1970-01-01 00:00:00 UTC, not including leap seconds.
*
* @psalm-pure
*/
public static function UNIX() : self
{
return new self(self::UNIX, DateTime::fromString('1970-01-01 00:00:00 UTC'));
}
/**
* Other name for UNIX epoch.
*
* @psalm-pure
*/
public static function POSIX() : self
{
return self::UNIX();
}
/**
* UTC Epoch, started at 1972-01-01 00:00:00 UTC, including leap seconds.
*
* @psalm-pure
*/
public static function UTC() : self
{
return new self(self::UTC, DateTime::fromString('1972-01-01 00:00:00 UTC'));
}
/**
* GPS Epoch, started at 1980-01-06 00:00:00 UTC, including leap seconds
* except first 9 there were added before epoch.
*
* @psalm-pure
*/
public static function GPS() : self
{
return new self(self::GPS, DateTime::fromString('1980-01-06 00:00:00 UTC'));
}
/**
* TAI Epoch, started at 1958-01-01 00:00:00 UTC, including leap seconds.
*
* @psalm-pure
*/
public static function TAI() : self
{
return new self(self::TAI, DateTime::fromString('1958-01-01 00:00:00 UTC'));
}
public function type() : int
{
return $this->type;
}
public function date() : DateTime
{
return $this->dateTime;
}
/**
* Returns difference in seconds between epoches without leap seconds.
*/
public function distanceTo(self $timeEpoch) : TimeUnit
{
switch ($this->type) {
case self::UTC:
switch ($timeEpoch->type()) {
case self::GPS:
return TimeUnit::seconds(252892800); // 1972-01-01 00:00:00 UTC - 1980-01-06 00:00:00 UTC
case self::UNIX:
return TimeUnit::seconds(63072000)->invert(); // 1972-01-01 00:00:00 UTC - 1970-01-01 00:00:00 UTC
case self::TAI:
return TimeUnit::seconds(441763200)->invert(); // 1972-01-01 00:00:00 UTC - 1958-01-01 00:00:00 UTC
default:
return TimeUnit::seconds(0);
}
// no break
case self::GPS:
switch ($timeEpoch->type()) {
case self::UTC:
return TimeUnit::seconds(252892800)->invert(); // 1980-01-06 00:00:00 UTC - 1972-01-01 00:00:00 UTC
case self::UNIX:
return TimeUnit::seconds(315964800)->invert(); // 1980-01-06 00:00:00 UTC - 1970-01-01 00:00:00 UTC
case self::TAI:
return TimeUnit::seconds(694656000)->invert(); // 1980-01-06 00:00:00 UTC - 1958-01-01 00:00:00 UTC
default:
return TimeUnit::seconds(0);
}
// no break
case self::TAI:
switch ($timeEpoch->type()) {
case self::UTC:
return TimeUnit::seconds(441763200); // 1958-01-01 00:00:00 UTC - 1972-01-01 00:00:00 UTC
case self::UNIX:
return TimeUnit::seconds(378691200); // 1958-01-01 00:00:00 UTC - 1970-01-00 00:00:00 UTC
case self::GPS:
return TimeUnit::seconds(694656000); // 1958-01-01 00:00:00 UTC - 1980-01-06 00:00:00 UTC
default:
return TimeUnit::seconds(0);
}
// no break
default: // UNIX
switch ($timeEpoch->type()) {
case self::UTC:
return TimeUnit::seconds(63072000); // 1970-01-01 00:00:00 UTC - 1972-01-01 00:00:00 UTC
case self::GPS:
return TimeUnit::seconds(315964800); // 1970-01-01 00:00:00 UTC - 1980-01-06 00:00:00 UTC
case self::TAI:
return TimeUnit::seconds(378691200)->invert(); // 1970-01-01 00:00:00 UTC - 1958-01-01 00:00:00 UTC
default:
return TimeUnit::seconds(0);
}
}
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/TimePeriod.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\TimeUnit;
use Aeon\Calendar\Unit;
/**
* @psalm-immutable
*/
final class TimePeriod
{
private DateTime $start;
private DateTime $end;
public function __construct(DateTime $start, DateTime $end)
{
$this->start = $start;
$this->end = $end;
}
/**
* @return array{start: DateTime, end: DateTime}
*/
public function __serialize() : array
{
return [
'start' => $this->start,
'end' => $this->end,
];
}
public function start() : DateTime
{
return $this->start;
}
public function end() : DateTime
{
return $this->end;
}
public function isForward() : bool
{
return $this->distance()->isPositive();
}
public function isBackward() : bool
{
return $this->distance()->isNegative();
}
/**
* Calculate distance between 2 points in time without leap seconds.
*/
public function distance() : TimeUnit
{
$startUnixTimestamp = $this->start->timestampUNIX();
$endUnixTimestamp = $this->end->timestampUNIX();
$result = $endUnixTimestamp
->sub($startUnixTimestamp)
->toPositive();
return $this->start->isAfter($this->end) ? $result->invert() : $result;
}
public function leapSeconds() : LeapSeconds
{
return LeapSeconds::load()->findAllBetween($this);
}
/**
* @psalm-suppress ImpureMethodCall
*/
public function iterate(Unit $timeUnit, Interval $interval) : TimePeriods
{
return TimePeriods::fromIterator(new TimePeriodsIterator($this->start, $this->end, $timeUnit, $interval));
}
/**
* @psalm-suppress ImpureMethodCall
*/
public function iterateBackward(Unit $timeUnit, Interval $interval) : TimePeriods
{
return TimePeriods::fromIterator(new TimePeriodsIterator($this->end, $this->start, $timeUnit->toNegative(), $interval));
}
public function overlaps(self $timePeriod) : bool
{
if ($this->isBackward()) {
$thisPeriodForward = $this->revert();
} else {
$thisPeriodForward = $this;
}
if ($timePeriod->isBackward()) {
$otherPeriodForward = $timePeriod->revert();
} else {
$otherPeriodForward = $timePeriod;
}
$thisPeriodStart = $thisPeriodForward->start();
$thisPeriodEnd = $thisPeriodForward->end();
$otherPeriodStart = $otherPeriodForward->start();
$otherPeriodEnd = $otherPeriodForward->end();
if ($thisPeriodForward->abuts($otherPeriodForward)) {
return false;
}
if ($thisPeriodStart->isBefore($otherPeriodStart) &&
$thisPeriodEnd->isBefore($otherPeriodStart) &&
$thisPeriodEnd->isBefore($otherPeriodEnd)
) {
return false;
}
if ($thisPeriodEnd->isBefore($otherPeriodEnd)) {
return true;
}
if ($thisPeriodStart->isAfter($otherPeriodStart) &&
$thisPeriodStart->isBefore($otherPeriodEnd) &&
$thisPeriodEnd->isAfter($otherPeriodStart)
) {
return true;
}
if ($thisPeriodStart->isAfter($otherPeriodStart) &&
$thisPeriodEnd->isAfter($otherPeriodStart) &&
$thisPeriodEnd->isAfter($otherPeriodEnd)
) {
return false;
}
return true;
}
public function contains(self $timePeriod) : bool
{
return $this->start->isBeforeOrEqualTo($timePeriod->start()) && $this->end->isAfterOrEqualTo($timePeriod->end());
}
public function revert() : self
{
return new self($this->end(), $this->start());
}
public function merge(self $timePeriod) : self
{
if (!$this->overlaps($timePeriod) && !$this->abuts($timePeriod)) {
throw new InvalidArgumentException("Can't merge not overlapping time periods.");
}
return new self(
$this->start->isBeforeOrEqualTo($timePeriod->start)
? $this->start()
: $timePeriod->start,
$this->end->isAfterOrEqualTo($timePeriod->end)
? $this->end()
: $timePeriod->end()
);
}
public function abuts(self $timePeriod) : bool
{
$thisPeriodForward = $this->isBackward()
? $this->revert()
: $this;
$otherPeriodForward = $timePeriod->isBackward()
? $timePeriod->revert()
: $timePeriod;
if ($thisPeriodForward->end()->isEqualTo($otherPeriodForward->start())) {
return true;
}
if ($thisPeriodForward->start()->isEqualTo($otherPeriodForward->end())) {
return true;
}
return false;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $period) : bool
{
return $this->isEqualTo($period);
}
public function isEqualTo(self $period) : bool
{
return $this->start->isEqualTo($period->start()) && $this->end->isEqualTo($period->end());
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/TimePeriods.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @implements \IteratorAggregate<TimePeriod>
*/
final class TimePeriods implements \Countable, \IteratorAggregate
{
/**
* @var \Iterator<int|string, TimePeriod>
*/
private \Iterator $periods;
/**
* @param \Iterator<int|string, TimePeriod> $periods
*/
private function __construct(\Iterator $periods)
{
$this->periods = $periods;
}
public static function fromArray(TimePeriod ...$periods) : self
{
return new self(new \ArrayIterator($periods));
}
public static function fromIterator(TimePeriodsIterator $timePeriodsIterator) : self
{
return new self($timePeriodsIterator);
}
/**
* @return array<TimePeriod>
*/
public function all() : array
{
return \iterator_to_array($this->periods);
}
/**
* @param callable(TimePeriod $timePeriod) : void $iterator
*
* @psalm-param pure-callable(TimePeriod $timePeriod) : void $iterator
*/
public function each(callable $iterator) : void
{
foreach ($this->periods as $period) {
$iterator($period);
}
}
/**
* @param callable(TimePeriod $timePeriod) : mixed $iterator
*
* @psalm-param pure-callable(TimePeriod $timePeriod) : mixed $iterator
*
* @return array<mixed>
*/
public function map(callable $iterator) : array
{
return \array_map($iterator, $this->all());
}
/**
* @psalm-suppress InvalidScalarArgument
*
* @param callable(TimePeriod $timePeriod) : bool $iterator
*
* @psalm-param pure-callable(TimePeriod $timePeriod) : bool $iterator
*
* @return self
*/
public function filter(callable $iterator) : self
{
return new self(new \CallbackFilterIterator($this->periods, $iterator));
}
public function count() : int
{
return \iterator_count($this->periods);
}
/**
* @return \Traversable<int|string, TimePeriod>
*/
public function getIterator() : \Traversable
{
return $this->periods;
}
/**
* Find all gaps between time periods.
*/
public function gaps() : self
{
$periods = \array_map(
function (TimePeriod $timePeriod) : TimePeriod {
return $timePeriod->isBackward() ? $timePeriod->revert() : $timePeriod;
},
$this->sort()->all()
);
if (!\count($periods)) {
return self::fromArray(...[]);
}
$gaps = [];
$totalPeriod = \current($periods);
while ($period = \next($periods)) {
if ($totalPeriod->overlaps($period) || $totalPeriod->abuts($period)) {
$totalPeriod = $totalPeriod->merge($period);
} else {
$gaps[] = new TimePeriod($totalPeriod->end(), $period->start());
$totalPeriod = $period;
}
}
return self::fromArray(...$gaps);
}
public function sort() : self
{
return $this->sortBy(TimePeriodsSort::asc());
}
public function sortBy(TimePeriodsSort $sort) : self
{
$periods = $this->all();
\uasort(
$periods,
function (TimePeriod $timePeriodA, TimePeriod $timePeriodB) use ($sort) : int {
if ($sort->byStartDate()) {
return $sort->isAscending()
? $timePeriodA->start()->toDateTimeImmutable() <=> $timePeriodB->start()->toDateTimeImmutable()
: $timePeriodB->start()->toDateTimeImmutable() <=> $timePeriodA->start()->toDateTimeImmutable();
}
return $sort->isAscending()
? $timePeriodA->end()->toDateTimeImmutable() <=> $timePeriodB->end()->toDateTimeImmutable()
: $timePeriodB->end()->toDateTimeImmutable() <=> $timePeriodA->end()->toDateTimeImmutable();
}
);
return self::fromArray(...$periods);
}
public function first() : ?TimePeriod
{
$this->periods->rewind();
return $this->periods->current();
}
public function last() : ?TimePeriod
{
$periods = $this->all();
if (!\count($periods)) {
return null;
}
return \end($periods);
}
public function add(TimePeriod ...$timePeriods) : self
{
return self::fromArray(...\array_merge($this->all(), $timePeriods));
}
public function merge(self $timePeriods) : self
{
return self::fromArray(...\array_merge($this->all(), $timePeriods->all()));
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $periods) : bool
{
return $this->isEqualTo($periods);
}
public function isEqualTo(self $periods) : bool
{
if ($periods->count() !== $this->count()) {
return false;
}
$selfArray = \array_values($this->sort()->all());
$periodsArray = \array_values($periods->sort()->all());
foreach ($selfArray as $i => $timePeriod) {
if (!$periodsArray[$i]->isEqualTo($timePeriod)) {
return false;
}
}
return true;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/TimePeriodsIterator.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Unit;
final class TimePeriodsIterator extends \FilterIterator
{
private Interval $interval;
public function __construct(DateTime $start, DateTime $end, Unit $timeUnit, Interval $interval)
{
$this->interval = $interval;
parent::__construct(new DateTimeIterator($start, $end, $timeUnit));
}
public function current() : ?TimePeriod
{
$dateTimeIterator = $this->getInnerIterator();
$end = $dateTimeIterator->end();
$currentStart = $dateTimeIterator->current();
$currentEnd = $dateTimeIterator->current()->add($dateTimeIterator->unit());
if ($dateTimeIterator->isForward()) {
if ($currentEnd->isAfterOrEqualTo($end)) {
$currentEnd = $end;
}
} else {
if ($currentEnd->isBeforeOrEqualTo($end)) {
$currentEnd = $end;
}
}
return new TimePeriod($currentStart, $currentEnd);
}
public function accept() : bool
{
$dateTimeIterator = $this->getInnerIterator();
$current = $dateTimeIterator->current();
$end = $dateTimeIterator->end();
if ($dateTimeIterator->isForward()) {
if ($current->isAfterOrEqualTo($end)) {
return false;
}
if ($this->interval->isRightOpen() && $current->add($dateTimeIterator->unit())->isAfterOrEqualTo($end)) {
return false;
}
if ($this->interval->isLeftOpen() && $dateTimeIterator->isFirst()) {
return false;
}
} else {
if ($current->isBeforeOrEqualTo($end)) {
return false;
}
if (($this->interval->isRightOpen()) && $dateTimeIterator->isFirst()) {
return false;
}
if (($this->interval->isLeftOpen()) && $current->add($dateTimeIterator->unit())->isBeforeOrEqualTo($end)) {
return false;
}
}
return true;
}
public function key() : int
{
$dateTimeIterator = $this->getInnerIterator();
if ($dateTimeIterator->isForward()) {
if ($this->interval->isLeftOpen()) {
return $dateTimeIterator->key() - 1;
}
} else {
if ($this->interval->isRightOpen()) {
return $dateTimeIterator->key() - 1;
}
}
return $dateTimeIterator->key();
}
/**
* @psalm-suppress InvalidReturnType
* @psalm-suppress InvalidReturnStatement
*/
public function getInnerIterator() : DateTimeIterator
{
/** @phpstan-ignore-next-line */
return parent::getInnerIterator();
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/TimePeriodsSort.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*/
final class TimePeriodsSort
{
private const START_DATE_ASC = 1;
private const START_DATE_DESC = 2;
private const END_DATE_ASC = 3;
private const END_DATE_DESC = 4;
private int $type;
private function __construct(int $type)
{
$this->type = $type;
}
/**
* @psalm-pure
*/
public static function asc() : self
{
return self::startDate();
}
/**
* @psalm-pure
*/
public static function desc() : self
{
return self::startDate(false);
}
/**
* @psalm-pure
*/
public static function startDate(bool $ascending = true) : self
{
return new self($ascending ? self::START_DATE_ASC : self::START_DATE_DESC);
}
/**
* @psalm-pure
*/
public static function endDate(bool $ascending = true) : self
{
return new self($ascending ? self::END_DATE_ASC : self::END_DATE_DESC);
}
public function byStartDate() : bool
{
return $this->type === self::START_DATE_ASC || $this->type === self::START_DATE_DESC;
}
public function isAscending() : bool
{
return $this->type === self::START_DATE_ASC || $this->type === self::END_DATE_ASC;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/TimeZone/TimeOffset.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian\TimeZone;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class TimeOffset
{
private const OFFSET_REGEXP = '/^(GMT)?([+-]?)(2[0-3]|[01][0-9]):?([0-5][0-9])$/';
private bool $negative;
private int $hours;
private int $minutes;
private function __construct(bool $negative, int $hours, int $minutes)
{
$this->negative = $negative;
$this->hours = $hours;
$this->minutes = $minutes;
}
/** @psalm-pure */
public static function UTC() : self
{
return new self(false, 0, 0);
}
/** @psalm-pure */
public static function fromString(string $offset) : self
{
if (!\preg_match(self::OFFSET_REGEXP, $offset, $matches)) {
throw new InvalidArgumentException("\"{$offset}\" is not a valid UTC Offset.");
}
return new self($matches[2] === '-', (int) $matches[3], (int) $matches[4]);
}
/** @psalm-pure */
public static function isValid(string $offset) : bool
{
return (bool) \preg_match(self::OFFSET_REGEXP, $offset, $matches);
}
/** @psalm-pure */
public static function fromTimeUnit(TimeUnit $timeUnit) : self
{
return self::fromString(
($timeUnit->isNegative() ? '-' : '+')
. \str_pad((string) $timeUnit->inHoursAbs(), 2, '0', STR_PAD_LEFT)
. \str_pad((string) $timeUnit->inTimeMinutes(), 2, '0', STR_PAD_LEFT)
);
}
/**
* @return array{hours: int, minutes: int, negative: bool}
*/
public function __serialize() : array
{
return [
'hours' => $this->hours,
'minutes' => $this->minutes,
'negative' => $this->negative,
];
}
public function toString() : string
{
return ($this->negative ? '-' : '+')
. \str_pad((string) $this->hours, 2, '0', STR_PAD_LEFT) . ':' . \str_pad((string) $this->minutes, 2, '0', STR_PAD_LEFT);
}
public function toTimeUnit() : TimeUnit
{
return $this->negative
? TimeUnit::minutes($this->minutes)->add(TimeUnit::hours($this->hours))->invert()
: TimeUnit::minutes($this->minutes)->add(TimeUnit::hours($this->hours));
}
public function toDateTimeZone() : \DateTimeZone
{
return new \DateTimeZone($this->toString());
}
public function isUTC() : bool
{
return $this->hours === 0 && $this->minutes === 0;
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $timeOffset) : bool
{
return $this->isEqualTo($timeOffset);
}
public function isEqualTo(self $timeOffset) : bool
{
return $this->negative === $timeOffset->negative
&& $this->hours === $timeOffset->hours
&& $this->minutes === $timeOffset->minutes;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/TimeZone.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\Gregorian\TimeZone\TimeOffset;
use Aeon\Calendar\TimeUnit;
/**
* @method static self africaAbidjan()
* @method static self africaAccra()
* @method static self africaAddisAbaba()
* @method static self africaAlgiers()
* @method static self africaAsmara()
* @method static self africaBamako()
* @method static self africaBangui()
* @method static self africaBanjul()
* @method static self africaBissau()
* @method static self africaBlantyre()
* @method static self africaBrazzaville()
* @method static self africaBujumbura()
* @method static self africaCairo()
* @method static self africaCasablanca()
* @method static self africaCeuta()
* @method static self africaConakry()
* @method static self africaDakar()
* @method static self africaDarEsSalaam()
* @method static self africaDjibouti()
* @method static self africaDouala()
* @method static self africaElAaiun()
* @method static self africaFreetown()
* @method static self africaGaborone()
* @method static self africaHarare()
* @method static self africaJohannesburg()
* @method static self africaJuba()
* @method static self africaKampala()
* @method static self africaKhartoum()
* @method static self africaKigali()
* @method static self africaKinshasa()
* @method static self africaLagos()
* @method static self africaLibreville()
* @method static self africaLome()
* @method static self africaLuanda()
* @method static self africaLubumbashi()
* @method static self africaLusaka()
* @method static self africaMalabo()
* @method static self africaMaputo()
* @method static self africaMaseru()
* @method static self africaMbabane()
* @method static self africaMogadishu()
* @method static self africaMonrovia()
* @method static self africaNairobi()
* @method static self africaNdjamena()
* @method static self africaNiamey()
* @method static self africaNouakchott()
* @method static self africaOuagadougou()
* @method static self africaPortoNovo()
* @method static self africaSaoTome()
* @method static self africaTripoli()
* @method static self africaTunis()
* @method static self africaWindhoek()
* @method static self americaAdak()
* @method static self americaAnchorage()
* @method static self americaAnguilla()
* @method static self americaAntigua()
* @method static self americaAraguaina()
* @method static self americaArgentinaBuenosAires()
* @method static self americaArgentinaCatamarca()
* @method static self americaArgentinaCordoba()
* @method static self americaArgentinaJujuy()
* @method static self americaArgentinaLaRioja()
* @method static self americaArgentinaMendoza()
* @method static self americaArgentinaRioGallegos()
* @method static self americaArgentinaSalta()
* @method static self americaArgentinaSanJuan()
* @method static self americaArgentinaSanLuis()
* @method static self americaArgentinaTucuman()
* @method static self americaArgentinaUshuaia()
* @method static self americaAruba()
* @method static self americaAsuncion()
* @method static self americaAtikokan()
* @method static self americaBahia()
* @method static self americaBahiaBanderas()
* @method static self americaBarbados()
* @method static self americaBelem()
* @method static self americaBelize()
* @method static self americaBlancSablon()
* @method static self americaBoaVista()
* @method static self americaBogota()
* @method static self americaBoise()
* @method static self americaCambridgeBay()
* @method static self americaCampoGrande()
* @method static self americaCancun()
* @method static self americaCaracas()
* @method static self americaCayenne()
* @method static self americaCayman()
* @method static self americaChicago()
* @method static self americaChihuahua()
* @method static self americaCostaRica()
* @method static self americaCreston()
* @method static self americaCuiaba()
* @method static self americaCuracao()
* @method static self americaDanmarkshavn()
* @method static self americaDawson()
* @method static self americaDawsonCreek()
* @method static self americaDenver()
* @method static self americaDetroit()
* @method static self americaDominica()
* @method static self americaEdmonton()
* @method static self americaEirunepe()
* @method static self americaElSalvador()
* @method static self americaFortNelson()
* @method static self americaFortaleza()
* @method static self americaGlaceBay()
* @method static self americaGooseBay()
* @method static self americaGrandTurk()
* @method static self americaGrenada()
* @method static self americaGuadeloupe()
* @method static self americaGuatemala()
* @method static self americaGuayaquil()
* @method static self americaGuyana()
* @method static self americaHalifax()
* @method static self americaHavana()
* @method static self americaHermosillo()
* @method static self americaIndianaIndianapolis()
* @method static self americaIndianaKnox()
* @method static self americaIndianaMarengo()
* @method static self americaIndianaPetersburg()
* @method static self americaIndianaTellCity()
* @method static self americaIndianaVevay()
* @method static self americaIndianaVincennes()
* @method static self americaIndianaWinamac()
* @method static self americaInuvik()
* @method static self americaIqaluit()
* @method static self americaJamaica()
* @method static self americaJuneau()
* @method static self americaKentuckyLouisville()
* @method static self americaKentuckyMonticello()
* @method static self americaKralendijk()
* @method static self americaLaPaz()
* @method static self americaLima()
* @method static self americaLosAngeles()
* @method static self americaLowerPrinces()
* @method static self americaMaceio()
* @method static self americaManagua()
* @method static self americaManaus()
* @method static self americaMarigot()
* @method static self americaMartinique()
* @method static self americaMatamoros()
* @method static self americaMazatlan()
* @method static self americaMenominee()
* @method static self americaMerida()
* @method static self americaMetlakatla()
* @method static self americaMexicoCity()
* @method static self americaMiquelon()
* @method static self americaMoncton()
* @method static self americaMonterrey()
* @method static self americaMontevideo()
* @method static self americaMontserrat()
* @method static self americaNassau()
* @method static self americaNewYork()
* @method static self americaNipigon()
* @method static self americaNome()
* @method static self americaNoronha()
* @method static self americaNorthDakotaBeulah()
* @method static self americaNorthDakotaCenter()
* @method static self americaNorthDakotaNewSalem()
* @method static self americaNuuk()
* @method static self americaOjinaga()
* @method static self americaPanama()
* @method static self americaPangnirtung()
* @method static self americaParamaribo()
* @method static self americaPhoenix()
* @method static self americaPortAuPrince()
* @method static self americaPortOfSpain()
* @method static self americaPortoVelho()
* @method static self americaPuertoRico()
* @method static self americaPuntaArenas()
* @method static self americaRainyRiver()
* @method static self americaRankinInlet()
* @method static self americaRecife()
* @method static self americaRegina()
* @method static self americaResolute()
* @method static self americaRioBranco()
* @method static self americaSantarem()
* @method static self americaSantiago()
* @method static self americaSantoDomingo()
* @method static self americaSaoPaulo()
* @method static self americaScoresbysund()
* @method static self americaSitka()
* @method static self americaStBarthelemy()
* @method static self americaStJohns()
* @method static self americaStKitts()
* @method static self americaStLucia()
* @method static self americaStThomas()
* @method static self americaStVincent()
* @method static self americaSwiftCurrent()
* @method static self americaTegucigalpa()
* @method static self americaThule()
* @method static self americaThunderBay()
* @method static self americaTijuana()
* @method static self americaToronto()
* @method static self americaTortola()
* @method static self americaVancouver()
* @method static self americaWhitehorse()
* @method static self americaWinnipeg()
* @method static self americaYakutat()
* @method static self americaYellowknife()
* @method static self antarcticaCasey()
* @method static self antarcticaDavis()
* @method static self antarcticaDumontDUrville()
* @method static self antarcticaMacquarie()
* @method static self antarcticaMawson()
* @method static self antarcticaMcMurdo()
* @method static self antarcticaPalmer()
* @method static self antarcticaRothera()
* @method static self antarcticaSyowa()
* @method static self antarcticaTroll()
* @method static self antarcticaVostok()
* @method static self arcticLongyearbyen()
* @method static self asiaAden()
* @method static self asiaAlmaty()
* @method static self asiaAmman()
* @method static self asiaAnadyr()
* @method static self asiaAqtau()
* @method static self asiaAqtobe()
* @method static self asiaAshgabat()
* @method static self asiaAtyrau()
* @method static self asiaBaghdad()
* @method static self asiaBahrain()
* @method static self asiaBaku()
* @method static self asiaBangkok()
* @method static self asiaBarnaul()
* @method static self asiaBeirut()
* @method static self asiaBishkek()
* @method static self asiaBrunei()
* @method static self asiaChita()
* @method static self asiaChoibalsan()
* @method static self asiaColombo()
* @method static self asiaDamascus()
* @method static self asiaDhaka()
* @method static self asiaDili()
* @method static self asiaDubai()
* @method static self asiaDushanbe()
* @method static self asiaFamagusta()
* @method static self asiaGaza()
* @method static self asiaHebron()
* @method static self asiaHoChiMinh()
* @method static self asiaHongKong()
* @method static self asiaHovd()
* @method static self asiaIrkutsk()
* @method static self asiaJakarta()
* @method static self asiaJayapura()
* @method static self asiaJerusalem()
* @method static self asiaKabul()
* @method static self asiaKamchatka()
* @method static self asiaKarachi()
* @method static self asiaKathmandu()
* @method static self asiaKhandyga()
* @method static self asiaKolkata()
* @method static self asiaKrasnoyarsk()
* @method static self asiaKualaLumpur()
* @method static self asiaKuching()
* @method static self asiaKuwait()
* @method static self asiaMacau()
* @method static self asiaMagadan()
* @method static self asiaMakassar()
* @method static self asiaManila()
* @method static self asiaMuscat()
* @method static self asiaNicosia()
* @method static self asiaNovokuznetsk()
* @method static self asiaNovosibirsk()
* @method static self asiaOmsk()
* @method static self asiaOral()
* @method static self asiaPhnomPenh()
* @method static self asiaPontianak()
* @method static self asiaPyongyang()
* @method static self asiaQatar()
* @method static self asiaQostanay()
* @method static self asiaQyzylorda()
* @method static self asiaRiyadh()
* @method static self asiaSakhalin()
* @method static self asiaSamarkand()
* @method static self asiaSeoul()
* @method static self asiaShanghai()
* @method static self asiaSingapore()
* @method static self asiaSrednekolymsk()
* @method static self asiaTaipei()
* @method static self asiaTashkent()
* @method static self asiaTbilisi()
* @method static self asiaTehran()
* @method static self asiaThimphu()
* @method static self asiaTokyo()
* @method static self asiaTomsk()
* @method static self asiaUlaanbaatar()
* @method static self asiaUrumqi()
* @method static self asiaUstNera()
* @method static self asiaVientiane()
* @method static self asiaVladivostok()
* @method static self asiaYakutsk()
* @method static self asiaYangon()
* @method static self asiaYekaterinburg()
* @method static self asiaYerevan()
* @method static self atlanticAzores()
* @method static self atlanticBermuda()
* @method static self atlanticCanary()
* @method static self atlanticCapeVerde()
* @method static self atlanticFaroe()
* @method static self atlanticMadeira()
* @method static self atlanticReykjavik()
* @method static self atlanticSouthGeorgia()
* @method static self atlanticStHelena()
* @method static self atlanticStanley()
* @method static self australiaAdelaide()
* @method static self australiaBrisbane()
* @method static self australiaBrokenHill()
* @method static self australiaCurrie()
* @method static self australiaDarwin()
* @method static self australiaEucla()
* @method static self australiaHobart()
* @method static self australiaLindeman()
* @method static self australiaLordHowe()
* @method static self australiaMelbourne()
* @method static self australiaPerth()
* @method static self australiaSydney()
* @method static self europeAmsterdam()
* @method static self europeAndorra()
* @method static self europeAstrakhan()
* @method static self europeAthens()
* @method static self europeBelgrade()
* @method static self europeBerlin()
* @method static self europeBratislava()
* @method static self europeBrussels()
* @method static self europeBucharest()
* @method static self europeBudapest()
* @method static self europeBusingen()
* @method static self europeChisinau()
* @method static self europeCopenhagen()
* @method static self europeDublin()
* @method static self europeGibraltar()
* @method static self europeGuernsey()
* @method static self europeHelsinki()
* @method static self europeIsleOfMan()
* @method static self europeIstanbul()
* @method static self europeJersey()
* @method static self europeKaliningrad()
* @method static self europeKiev()
* @method static self europeKirov()
* @method static self europeLisbon()
* @method static self europeLjubljana()
* @method static self europeLondon()
* @method static self europeLuxembourg()
* @method static self europeMadrid()
* @method static self europeMalta()
* @method static self europeMariehamn()
* @method static self europeMinsk()
* @method static self europeMonaco()
* @method static self europeMoscow()
* @method static self europeOslo()
* @method static self europeParis()
* @method static self europePodgorica()
* @method static self europePrague()
* @method static self europeRiga()
* @method static self europeRome()
* @method static self europeSamara()
* @method static self europeSanMarino()
* @method static self europeSarajevo()
* @method static self europeSaratov()
* @method static self europeSimferopol()
* @method static self europeSkopje()
* @method static self europeSofia()
* @method static self europeStockholm()
* @method static self europeTallinn()
* @method static self europeTirane()
* @method static self europeUlyanovsk()
* @method static self europeUzhgorod()
* @method static self europeVaduz()
* @method static self europeVatican()
* @method static self europeVienna()
* @method static self europeVilnius()
* @method static self europeVolgograd()
* @method static self europeWarsaw()
* @method static self europeZagreb()
* @method static self europeZaporozhye()
* @method static self europeZurich()
* @method static self indianAntananarivo()
* @method static self indianChagos()
* @method static self indianChristmas()
* @method static self indianCocos()
* @method static self indianComoro()
* @method static self indianKerguelen()
* @method static self indianMahe()
* @method static self indianMaldives()
* @method static self indianMauritius()
* @method static self indianMayotte()
* @method static self indianReunion()
* @method static self pacificApia()
* @method static self pacificAuckland()
* @method static self pacificBougainville()
* @method static self pacificChatham()
* @method static self pacificChuuk()
* @method static self pacificEaster()
* @method static self pacificEfate()
* @method static self pacificEnderbury()
* @method static self pacificFakaofo()
* @method static self pacificFiji()
* @method static self pacificFunafuti()
* @method static self pacificGalapagos()
* @method static self pacificGambier()
* @method static self pacificGuadalcanal()
* @method static self pacificGuam()
* @method static self pacificHonolulu()
* @method static self pacificKiritimati()
* @method static self pacificKosrae()
* @method static self pacificKwajalein()
* @method static self pacificMajuro()
* @method static self pacificMarquesas()
* @method static self pacificMidway()
* @method static self pacificNauru()
* @method static self pacificNiue()
* @method static self pacificNorfolk()
* @method static self pacificNoumea()
* @method static self pacificPagoPago()
* @method static self pacificPalau()
* @method static self pacificPitcairn()
* @method static self pacificPohnpei()
* @method static self pacificPortMoresby()
* @method static self pacificRarotonga()
* @method static self pacificSaipan()
* @method static self pacificTahiti()
* @method static self pacificTarawa()
* @method static self pacificTongatapu()
* @method static self pacificWake()
* @method static self pacificWallis()
* @method static self ACDT()
* @method static self ACST()
* @method static self ADDT()
* @method static self ADT()
* @method static self AEDT()
* @method static self AEST()
* @method static self AHDT()
* @method static self AHST()
* @method static self AKDT()
* @method static self AKST()
* @method static self AMT()
* @method static self APT()
* @method static self AST()
* @method static self AWDT()
* @method static self AWST()
* @method static self AWT()
* @method static self BDST()
* @method static self BDT()
* @method static self BMT()
* @method static self BST()
* @method static self CAST()
* @method static self CAT()
* @method static self CDDT()
* @method static self CDT()
* @method static self CEMT()
* @method static self CEST()
* @method static self CET()
* @method static self CMT()
* @method static self CPT()
* @method static self CST()
* @method static self CWT()
* @method static self CHST()
* @method static self DMT()
* @method static self EAT()
* @method static self EDDT()
* @method static self EDT()
* @method static self EEST()
* @method static self EET()
* @method static self EMT()
* @method static self EPT()
* @method static self EST()
* @method static self EWT()
* @method static self FFMT()
* @method static self FMT()
* @method static self GDT()
* @method static self GMT()
* @method static self GST()
* @method static self HDT()
* @method static self HKST()
* @method static self HKT()
* @method static self HMT()
* @method static self HPT()
* @method static self HST()
* @method static self HWT()
* @method static self IDDT()
* @method static self IDT()
* @method static self IMT()
* @method static self IST()
* @method static self JDT()
* @method static self JMT()
* @method static self JST()
* @method static self KDT()
* @method static self KMT()
* @method static self KST()
* @method static self LST()
* @method static self MDDT()
* @method static self MDST()
* @method static self MDT()
* @method static self MEST()
* @method static self MET()
* @method static self MMT()
* @method static self MPT()
* @method static self MSD()
* @method static self MSK()
* @method static self MST()
* @method static self MWT()
* @method static self NDDT()
* @method static self NDT()
* @method static self NPT()
* @method static self NST()
* @method static self NWT()
* @method static self NZDT()
* @method static self NZMT()
* @method static self NZST()
* @method static self PDDT()
* @method static self PDT()
* @method static self PKST()
* @method static self PKT()
* @method static self PLMT()
* @method static self PMT()
* @method static self PPMT()
* @method static self PPT()
* @method static self PST()
* @method static self PWT()
* @method static self QMT()
* @method static self RMT()
* @method static self SAST()
* @method static self SDMT()
* @method static self SJMT()
* @method static self SMT()
* @method static self SST()
* @method static self TBMT()
* @method static self TMT()
* @method static self UCT()
* @method static self WAST()
* @method static self WAT()
* @method static self WEMT()
* @method static self WEST()
* @method static self WET()
* @method static self WIB()
* @method static self WITA()
* @method static self WIT()
* @method static self WMT()
* @method static self YDDT()
* @method static self YDT()
* @method static self YPT()
* @method static self YST()
* @method static self YWT()
*
* @psalm-immutable
*/
final class TimeZone
{
private const TYPE_OFFSET = 1;
private const TYPE_ABBREVIATION = 2;
private const TYPE_IDENTIFIER = 3;
private string $name;
private int $type;
private function __construct(string $name, int $type)
{
$this->name = $name;
$this->type = $type;
}
/**
* @throws InvalidArgumentException
*
* @psalm-pure
*/
public static function UTC() : self
{
return self::abbreviation('UTC');
}
/**
* @psalm-suppress PossiblyFalseIterator
*
* @psalm-pure
*/
public static function id(string $identifier) : self
{
$normalized = \strtolower($identifier);
if ($normalized === 'utc') {
throw new InvalidArgumentException('"UTC" is timezone abbreviation, not identifier.');
}
/** @var string $dateTimeZoneIdentifier */
foreach (\DateTimeZone::listIdentifiers() as $dateTimeZoneIdentifier) {
$normalizedDateTimeZoneIdentifier = \strtolower($dateTimeZoneIdentifier);
if (\strtolower($dateTimeZoneIdentifier) === $normalized) {
return new self($dateTimeZoneIdentifier, self::TYPE_IDENTIFIER);
}
if (\str_replace(['/', '_'], '', $normalizedDateTimeZoneIdentifier) === $normalized) {
return new self($dateTimeZoneIdentifier, self::TYPE_IDENTIFIER);
}
}
throw new InvalidArgumentException("\"{$identifier}\" is not a valid timezone identifier.");
}
/**
* @psalm-suppress PossiblyFalseArgument
*
* @psalm-pure
*/
public static function abbreviation(string $abbreviation) : self
{
$normalized = \strtoupper($abbreviation);
/**
* @var string $dateTimeZoneAbbreviation
*/
foreach (\array_keys(\DateTimeZone::listAbbreviations()) as $dateTimeZoneAbbreviation) {
if (\strtoupper($dateTimeZoneAbbreviation) === $normalized) {
return new self(\strtoupper($dateTimeZoneAbbreviation), self::TYPE_ABBREVIATION);
}
}
throw new InvalidArgumentException("\"{$abbreviation}\" is not a valid timezone abbreviation.");
}
/**
* @psalm-pure
*/
public static function offset(string $offset) : self
{
if (!TimeOffset::isValid($offset)) {
throw new InvalidArgumentException("\"{$offset}\" is not a valid time offset.");
}
return new self(TimeOffset::fromString($offset)->toString(), self::TYPE_OFFSET);
}
/**
* @psalm-pure
*/
public static function fromString(string $name) : self
{
try {
return self::id($name);
} catch (InvalidArgumentException $identifierException) {
try {
return self::abbreviation($name);
} catch (InvalidArgumentException $abbreviationException) {
try {
return self::offset($name);
} catch (InvalidArgumentException $offsetException) {
throw new InvalidArgumentException("\"{$name}\" is not a valid time zone.");
}
}
}
}
/**
* @psalm-pure
*/
public static function isValid(string $name) : bool
{
try {
new \DateTimeZone($name);
return true;
} catch (\Exception $e) {
return false;
}
}
/**
* @psalm-pure
*/
public static function fromDateTimeZone(\DateTimeZone $dateTimeZone) : self
{
$name = $dateTimeZone->getName();
$type = self::TYPE_IDENTIFIER;
if ($name === 'UTC') {
$type = self::TYPE_ABBREVIATION;
}
if (TimeOffset::isValid($name)) {
$type = self::TYPE_OFFSET;
}
if (\timezone_name_from_abbr($name) !== false) {
$type = self::TYPE_ABBREVIATION;
}
return new self($name, $type);
}
/**
* @psalm-pure
*
* @psalm-suppress PossiblyFalseArgument
*
* @return array<TimeZone>
*/
public static function allIdentifiers() : array
{
return \array_map(
fn (string $identifier) : self => self::id($identifier),
\array_filter(\DateTimeZone::listIdentifiers(), fn (string $identifier) : bool => $identifier !== 'UTC')
);
}
/**
* @psalm-pure
*
* @psalm-suppress PossiblyFalseArgument
*
* @return array<TimeZone>
*/
public static function allAbbreviations() : array
{
/** @var array<string> $abbreviations */
$abbreviations = \array_keys(\DateTimeZone::listAbbreviations());
return \array_map(
fn (string $abbreviation) : self => self::abbreviation($abbreviation),
\array_filter($abbreviations, fn (string $abbreviation) : bool => \strlen($abbreviation) > 1)
);
}
/**
* @param string $name
* @param array<mixed> $arguments
*
* @psalm-pure
*/
public static function __callStatic(string $name, array $arguments) : self
{
try {
return self::id($name);
} catch (InvalidArgumentException $identifierException) {
try {
return self::abbreviation($name);
} catch (InvalidArgumentException $abbreviationException) {
throw new InvalidArgumentException("\"{$name}\" is not a valid time zone identifier or abbreviation.");
}
}
}
/**
* @return array{name: string, type: int}
*/
public function __serialize() : array
{
return [
'name' => $this->name,
'type' => $this->type,
];
}
/**
* @param array{name: string, type: int} $data
*/
public function __unserialize(array $data) : void
{
$this->name = $data['name'];
$this->type = $data['type'];
}
public function isOffset() : bool
{
return $this->type === self::TYPE_OFFSET;
}
public function isAbbreviation() : bool
{
return $this->type === self::TYPE_ABBREVIATION;
}
public function isIdentifier() : bool
{
return $this->type === self::TYPE_IDENTIFIER;
}
public function toDateTimeZone() : \DateTimeZone
{
return new \DateTimeZone($this->name);
}
public function name() : string
{
return $this->name;
}
/**
* Offset depends on date because daylight & saving time will have it different and
* the only way to get it is to take it from date time.
*/
public function timeOffset(DateTime $dateTime) : TimeOffset
{
return TimeOffset::fromTimeUnit(TimeUnit::seconds($this->toDateTimeZone()->getOffset($dateTime->toDateTimeImmutable())));
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Year.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\RelativeTimeUnit;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class Year
{
private int $year;
private YearMonths $months;
public function __construct(int $year)
{
$this->year = $year;
$this->months = new YearMonths($this);
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
*/
public static function fromDateTime(\DateTimeInterface $dateTime) : self
{
return new self((int) $dateTime->format('Y'));
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
*/
public static function fromString(string $date) : self
{
try {
if (\is_numeric($date)) {
return new self((int) $date);
}
return self::fromDateTime(new \DateTimeImmutable($date));
} catch (\Exception $e) {
throw new InvalidArgumentException("Value \"{$date}\" is not valid year format.");
}
}
/**
* @return array{year:int}
*/
public function __debugInfo() : array
{
return [
'year' => $this->year,
];
}
/**
* @return array{year:int}
*/
public function __serialize() : array
{
return [
'year' => $this->year,
];
}
/**
* @param array{year:int} $data
*/
public function __unserialize(array $data) : void
{
$this->year = $data['year'];
$this->months = new YearMonths($this);
}
public function toString() : string
{
return (string) $this->year;
}
public function january() : Month
{
return $this->months()->byNumber(1);
}
public function february() : Month
{
return $this->months()->byNumber(2);
}
public function march() : Month
{
return $this->months()->byNumber(3);
}
public function april() : Month
{
return $this->months()->byNumber(4);
}
public function may() : Month
{
return $this->months()->byNumber(5);
}
public function june() : Month
{
return $this->months()->byNumber(6);
}
public function july() : Month
{
return $this->months()->byNumber(7);
}
public function august() : Month
{
return $this->months()->byNumber(8);
}
public function september() : Month
{
return $this->months()->byNumber(9);
}
public function october() : Month
{
return $this->months()->byNumber(10);
}
public function november() : Month
{
return $this->months()->byNumber(11);
}
public function december() : Month
{
return $this->months()->byNumber(12);
}
public function months() : YearMonths
{
return $this->months;
}
public function number() : int
{
return $this->year;
}
/**
* @infection-ignore-all
*
* @deprecated Use `add` instead. Will be removed with 2.0
*/
public function plus(int $years) : self
{
return $this->add($years);
}
public function add(int $years) : self
{
return new self($this->year + $years);
}
/**
* @infection-ignore-all
*
* @deprecated Use `sub` instead. Will be removed with 2.0
*/
public function minus(int $years) : self
{
return $this->sub($years);
}
public function sub(int $years) : self
{
return new self($this->year - $years);
}
public function next() : self
{
return new self($this->year + 1);
}
public function previous() : self
{
return new self($this->year - 1);
}
public function numberOfMonths() : int
{
return 12;
}
public function numberOfDays() : int
{
return $this->isLeap() ? 366 : 365;
}
public function quarter(int $number) : Quarter
{
switch ($number) {
case 1:
return new Quarter($number, $this->months()->slice(0, 3));
case 2:
return new Quarter($number, $this->months()->slice(3, 3));
case 3:
return new Quarter($number, $this->months()->slice(6, 3));
case 4:
return new Quarter($number, $this->months()->slice(9, 3));
default:
throw new InvalidArgumentException('Quarter number must be greater or equal 1 and less or equal than 4');
}
}
/**
* @param callable(Day $day) : void $iterator
*
* @psalm-param pure-callable(Day $day) : void $iterator
*
* @return array<mixed>
*/
public function mapDays(callable $iterator) : array
{
/** @psalm-suppress ImpureFunctionCall */
return \array_map(
$iterator,
\array_merge(
...\array_map(
fn (int $month) : array => $this->months()->byNumber($month)->days()->all(),
\range(1, 12)
)
)
);
}
/**
* @param callable(Day $day) : bool $iterator
*
* @psalm-param pure-callable(Day $day) : bool $iterator
*
* @return Days
*/
public function filterDays(callable $iterator) : Days
{
/** @psalm-suppress ImpureFunctionCall */
return Days::fromArray(...\array_filter(
\array_merge(
...\array_map(
fn (int $month) : array => $this->months()->byNumber($month)->days()->all(),
\range(1, 12)
)
),
$iterator
));
}
public function isLeap() : bool
{
return $this->year % 4 == 0 && ($this->year % 100 != 0 || $this->year % 400 == 0);
}
public function toDateTimeImmutable() : \DateTimeImmutable
{
return new \DateTimeImmutable(\sprintf('%d-01-01 00:00:00.000000 UTC', $this->number()));
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $year) : bool
{
return $this->isEqualTo($year);
}
public function isEqualTo(self $year) : bool
{
return $this->number() === $year->number();
}
public function isBefore(self $year) : bool
{
return $this->number() < $year->number();
}
/**
* @infection-ignore-all
*
* @deprecated Use `isBeforeOrEqualTo` instead. Will be removed with 2.0
*/
public function isBeforeOrEqual(self $year) : bool
{
return $this->isBeforeOrEqualTo($year);
}
public function isBeforeOrEqualTo(self $year) : bool
{
return $this->number() <= $year->number();
}
public function isAfter(self $year) : bool
{
return $this->number() > $year->number();
}
/**
* @infection-ignore-all
*
* @deprecated Use `isAfterOrEqualTo` instead. Will be removed with 2.0
*/
public function isAfterOrEqual(self $year) : bool
{
return $this->isAfterOrEqualTo($year);
}
public function isAfterOrEqualTo(self $year) : bool
{
return $this->number() >= $year->number();
}
public function iterate(self $destination, Interval $interval) : Years
{
return $this->isAfter($destination)
? $this->since($destination, $interval)
: $this->until($destination, $interval);
}
public function until(self $month, Interval $interval) : Years
{
if ($this->isAfter($month)) {
throw new InvalidArgumentException(
\sprintf(
'%d is after %d',
$this->number(),
$month->number(),
)
);
}
/**
* @var array<DateTime> $years
*
* @psalm-suppress ImpureMethodCall
* @psalm-suppress ImpureFunctionCall
*/
$years = \iterator_to_array(
new DateTimeIntervalIterator(
$this->january()->firstDay()->midnight(TimeZone::UTC()),
$month->january()->firstDay()->midnight(TimeZone::UTC()),
RelativeTimeUnit::year(),
$interval
)
);
return new Years(
...\array_map(
function (DateTime $dateTime) : self {
return $dateTime->year();
},
$years
)
);
}
public function since(self $month, Interval $interval) : Years
{
if ($this->isBefore($month)) {
throw new InvalidArgumentException(
\sprintf(
'%d is before %d',
$this->number(),
$month->number(),
)
);
}
/**
* @var array<DateTime> $years
*
* @psalm-suppress ImpureMethodCall
* @psalm-suppress ImpureFunctionCall
*/
$years = \iterator_to_array(
new DateTimeIntervalIterator(
$this->january()->firstDay()->midnight(TimeZone::UTC()),
$month->january()->firstDay()->midnight(TimeZone::UTC()),
RelativeTimeUnit::year()->toNegative(),
$interval
)
);
return new Years(
...\array_map(
function (DateTime $dateTime) : self {
return $dateTime->year();
},
\array_reverse($years)
)
);
}
public function distance(self $to) : TimeUnit
{
return (new TimePeriod($this->january()->firstDay()->midnight(TimeZone::UTC()), $to->january()->firstDay()->midnight(TimeZone::UTC())))->distance();
}
public function compareTo(self $year) : int
{
if ($this->isEqualTo($year)) {
return 0;
}
return $this->isBefore($year)
? -1
: 1;
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/YearMonths.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
use Aeon\Calendar\Exception\InvalidArgumentException;
/**
* @psalm-immutable
*/
final class YearMonths implements \Countable
{
private Year $year;
public function __construct(Year $year)
{
$this->year = $year;
}
public function count() : int
{
return $this->year->numberOfMonths();
}
public function byNumber(int $number) : Month
{
return new Month($this->year, $number);
}
/**
* @return array<int, Month>
*/
public function all() : array
{
/** @psalm-suppress ImpureFunctionCall */
return \array_map(
fn (int $monthNumber) : Month => new Month($this->year, $monthNumber),
\range(1, $this->year->numberOfMonths())
);
}
/**
* @param callable(Month $day) : void $iterator
*
* @psalm-param pure-callable(Month $day) : void $iterator
*
* @return array<mixed>
*/
public function map(callable $iterator) : array
{
return \array_map(
$iterator,
$this->all()
);
}
/**
* @param callable(Month $day) : bool $iterator
*
* @psalm-param pure-callable(Month $day) : bool $iterator
*
* @return array<Month>
*/
public function filter(callable $iterator) : array
{
return \array_filter(
$this->all(),
$iterator
);
}
public function slice(int $from, int $size) : Months
{
if ($from < 0) {
throw new InvalidArgumentException('Slice out of range.');
}
if ($from + $size > 12) {
throw new InvalidArgumentException('Slice out of range.');
}
return Months::fromArray(...\array_slice($this->all(), $from, $size));
}
}
================================================
FILE: src/Aeon/Calendar/Gregorian/Years.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\Gregorian;
/**
* @psalm-immutable
*
* @implements \IteratorAggregate<int, Year>
* @implements \ArrayAccess<int, Year>
*/
final class Years implements \ArrayAccess, \Countable, \IteratorAggregate
{
/**
* @var array<Year>
*/
private array $years;
public function __construct(Year ...$years)
{
$this->years = $years;
}
public function offsetExists($offset) : bool
{
return isset($this->all()[\intval($offset)]);
}
public function offsetGet($offset) : ?Year
{
return isset($this->all()[\intval($offset)]) ? $this->all()[\intval($offset)] : null;
}
public function offsetSet($offset, $value) : void
{
throw new \RuntimeException(__CLASS__ . ' is immutable.');
}
public function offsetUnset($offset) : void
{
throw new \RuntimeException(__CLASS__ . ' is immutable.');
}
/**
* @return array<Year>
*/
public function all() : array
{
return $this->years;
}
/**
* @param callable(Year $year) : mixed $iterator
*
* @psalm-param pure-callable(Year $year) : mixed $iterator
*
* @return array<mixed>
*/
public function map(callable $iterator) : array
{
return \array_map($iterator, $this->all());
}
/**
* @param callable(Year $year) : bool $iterator
*
* @psalm-param pure-callable(Year $year) : bool $iterator
*/
public function filter(callable $iterator) : self
{
return new self(...\array_filter($this->all(), $iterator));
}
public function count() : int
{
return \count($this->all());
}
public function getIterator() : \Traversable
{
return new \ArrayIterator($this->all());
}
}
================================================
FILE: src/Aeon/Calendar/RelativeTimeUnit.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar;
/**
* @psalm-immutable
*/
final class RelativeTimeUnit implements Unit
{
private ?int $months;
private ?int $years;
private function __construct(?int $months = null, ?int $years = null)
{
$this->months = $months;
$this->years = $years;
}
/** @psalm-pure */
public static function month() : self
{
return new self(1, null);
}
/** @psalm-pure */
public static function months(int $number) : self
{
return new self($number, null);
}
/** @psalm-pure */
public static function years(int $number) : self
{
return new self(null, $number);
}
/** @psalm-pure */
public static function year() : self
{
return new self(null, 1);
}
public function toDateInterval() : \DateInterval
{
$dateInterval = new \DateInterval(\sprintf('P%dY%dM', $this->inYears() ? \abs($this->inYears()) : 0, $this->inCalendarMonths() ? \abs($this->inCalendarMonths()) : 0));
if ($this->isNegative()) {
/** @psalm-suppress ImpurePropertyAssignment */
$dateInterval->invert = 1;
}
return $dateInterval;
}
public function invert() : self
{
if ($this->years) {
return $this->isNegative() ? self::years(\abs($this->years)) : self::years(-$this->years);
}
/**
* @psalm-suppress PossiblyNullArgument
*
* @phpstan-ignore-next-line
*/
return $this->isNegative() ? self::months(\abs($this->months)) : self::months(-$this->months);
}
public function inCalendarMonths() : int
{
if ($this->months === null) {
return 0;
}
return \abs($this->months % 12);
}
public function isNegative() : bool
{
return $this->years < 0 || $this->months < 0;
}
/**
* @psalm-suppress PossiblyNullOperand
* @psalm-suppress InvalidNullableReturnType
*/
public function inYears() : int
{
if ($this->years !== null) {
return $this->years;
}
/**
* @psalm-suppress PossiblyNullArgument
*
* @phpstan-ignore-next-line
*/
$years = (int) \floor(\abs($this->months) / 12);
return $this->isNegative() ? -$years : $years;
}
public function toNegative() : self
{
if ($this->isNegative()) {
return $this;
}
return $this->invert();
}
public function toPositive() : self
{
if (!$this->isNegative()) {
return $this;
}
return $this->invert();
}
/**
* @psalm-suppress NullableReturnStatement
* @psalm-suppress InvalidNullableReturnType
*/
public function inMonths() : int
{
if ($this->years !== null) {
return $this->years * 12;
}
/**
* @phpstan-ignore-next-line
*/
return $this->months;
}
}
================================================
FILE: src/Aeon/Calendar/Stopwatch.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar;
use Aeon\Calendar\Exception\Exception;
use Aeon\Calendar\TimeUnit\HRTime;
/**
* @psalm-pure
*/
final class Stopwatch
{
/**
* @var null|array{int, int}
*/
private ?array $start;
/**
* @var array<array{int, int}>
*/
private array $laps;
/**
* @var null|array{int, int}
*/
private ?array $end;
public function __construct()
{
$this->start = null;
$this->laps = [];
$this->end = null;
}
public function isStarted() : bool
{
return $this->start !== null;
}
public function isStopped() : bool
{
return $this->end !== null;
}
/**
* Stopwatch::lap() used once will generate two laps, first between start and lap[0] and
* second between lap[0] and end.
*/
public function laps() : int
{
return \count($this->laps) > 0
? \count($this->laps) + 1
: 0;
}
public function start() : void
{
$this->start = \hrtime(false);
}
public function lap() : void
{
if ($this->start === null) {
throw new Exception('Stopwatch not started');
}
$this->laps[] = \hrtime(false);
}
public function stop() : void
{
if ($this->start === null) {
throw new Exception('Stopwatch not started');
}
if ($this->end !== null) {
throw new Exception('Stopwatch already stopped');
}
$this->end = \hrtime(false);
}
public function elapsedTime(int $lap) : TimeUnit
{
if ($this->start === null) {
throw new Exception('Stopwatch not started');
}
if (\count($this->laps) === 0) {
throw new Exception('Stopwatch does not have any laps.');
}
if ($lap === 1) {
return $this->firstLapElapsedTime();
}
if ($lap - 1 === \count($this->laps)) {
return $this->lastLapElapsedTime();
}
if (!isset($this->laps[$lap - 1])) {
throw new Exception(\sprintf('Lap %d not exists', $lap));
}
return HRTime::convert($this->laps[$lap - 1][0], $this->laps[$lap - 1][1])
->sub(HRTime::convert($this->laps[$lap - 2][0], $this->laps[$lap - 2][1]));
}
public function firstLapElapsedTime() : TimeUnit
{
if ($this->start === null) {
throw new Exception('Stopwatch not started');
}
if (\count($this->laps) === 0) {
throw new Exception('Stopwatch does not have any laps.');
}
return HRTime::convert($this->laps[0][0], $this->laps[0][1])
->sub(HRTime::convert($this->start[0], $this->start[1]));
}
public function lastLapElapsedTime() : TimeUnit
{
if ($this->start === null) {
throw new Exception('Stopwatch not started');
}
if ($this->end === null) {
throw new Exception('Stopwatch not stopped');
}
if (\count($this->laps) === 0) {
throw new Exception('Stopwatch does not have any laps.');
}
return HRTime::convert($this->end[0], $this->end[1])
->sub(HRTime::convert(\end($this->laps)[0], \end($this->laps)[1]));
}
public function totalElapsedTime() : TimeUnit
{
if ($this->start === null) {
throw new Exception('Stopwatch not started');
}
if ($this->end === null) {
throw new Exception('Stopwatch not stopped');
}
return HRTime::convert($this->end[0], $this->end[1])
->sub(HRTime::convert($this->start[0], $this->start[1]));
}
}
================================================
FILE: src/Aeon/Calendar/TimeUnit/HRTime.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar\TimeUnit;
use Aeon\Calendar\Exception\InvalidArgumentException;
use Aeon\Calendar\TimeUnit;
/**
* @psalm-immutable
*/
final class HRTime
{
/**
* @psalm-pure
*/
public static function convert(int $seconds, int $nanosecond) : TimeUnit
{
if ($nanosecond < 0) {
throw new InvalidArgumentException("Nanoseconds can't be less than 0, given " . $nanosecond);
}
return TimeUnit::precise(\floatval(\sprintf(
'%d.%s',
$seconds,
\str_pad(\strval($nanosecond), 9, '0', STR_PAD_LEFT)
)));
}
}
================================================
FILE: src/Aeon/Calendar/TimeUnit.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calendar;
use Aeon\Calculator\PreciseCalculator;
use Aeon\Calendar\Exception\Exception;
use Aeon\Calendar\Exception\InvalidArgumentException;
/**
* @psalm-immutable
*/
final class TimeUnit implements Unit
{
private const PRECISION_MICROSECOND = 6;
private const MICROSECONDS_IN_SECOND = 1_000_000;
private const MICROSECONDS_IN_MILLISECOND = 1_000;
private const MILLISECONDS_IN_SECOND = 1_000;
private const SECONDS_IN_MINUTE = 60;
private const MINUTES_IN_HOUR = 60;
private const HOURS_IN_DAY = 24;
/**
* @var null|\ReflectionClass<TimeUnit>
*/
private static ?\ReflectionClass $reflectionClass = null;
private ?int $seconds = null;
private ?int $microsecond = null;
private ?\DateInterval $dateInterval = null;
private bool $negative = false;
private function __construct(bool $negative, int $seconds, int $microsecond)
{
if ($seconds < 0) {
throw new InvalidArgumentException('Seconds must be greater or equal 0, got ' . $seconds);
}
if ($microsecond < 0 || $microsecond >= self::MICROSECONDS_IN_SECOND) {
throw new InvalidArgumentException('Microsecond must be greater or equal 0 and less than 1000000, got ' . $microsecond);
}
$this->negative = $negative;
$this->seconds = $seconds;
$this->microsecond = $microsecond;
$this->dateInterval = null;
}
/**
* @psalm-pure
* Create from number of seconds with 6 decimal point precision.
* 0.500000 is half of the second, 500000 represents number of microseconds.
*/
public static function precise(float $seconds) : self
{
$secondsString = \number_format(\round($seconds, self::PRECISION_MICROSECOND, PHP_ROUND_HALF_UP), self::PRECISION_MICROSECOND, '.', '');
$secondsStringParts = \explode('.', $secondsString);
return new self(
\floatval($secondsString) < 0,
\abs(\intval($secondsStringParts[0])),
\abs(\intval($secondsStringParts[1])),
);
}
/**
* @psalm-pure
*
* @psalm-suppress ImpureMethodCall
* @psalm-suppress ImpurePropertyFetch
* @psalm-suppress ImpureStaticProperty
* @psalm-suppress ImpurePropertyAssignment
* @psalm-suppress InaccessibleProperty
*
* Limitations: TimeUnit can't be created from relative DateIntervals like \DateInterval::createFromDateString('4 months')
* or \DateInterval::createFromDateString('1 years'). It's because years and months are can't be precisely
* converted into seconds/days/hours.
*/
public static function fromDateInterval(\DateInterval $dateInterval) : self
{
if ($dateInterval->y && !$dateInterval->days) {
throw new Exception('Can\'t convert ' . $dateInterval->format('P%yY%mM%dDT%hH%iM%sS') . ' precisely to time unit because year can\'t be directly converted to number of seconds.');
}
if ($dateInterval->m && !$dateInterval->days) {
throw new Exception('Can\'t convert ' . $dateInterval->format('P%yY%mM%dDT%hH%iM%sS') . ' precisely to time unit because month can\'t be directly converted to number of seconds.');
}
if (self::$reflectionClass === null) {
self::$reflectionClass = new \ReflectionClass(self::class);
}
$newTimeUnit = self::$reflectionClass->newInstanceWithoutConstructor();
$newTimeUnit->dateInterval = $dateInterval;
return $newTimeUnit;
}
public static function fromDateString(string $dateString) : self
{
/** @var \DateInterval $interval */
$interval = \DateInterval::createFromDateString($dateString);
return self::fromDateInterval($interval);
}
/** @psalm-pure */
public static function millisecond() : self
{
return new self(false, 0, self::MICROSECONDS_IN_MILLISECOND);
}
/** @psalm-pure */
public static function milliseconds(int $milliseconds) : self
{
return new self(
$milliseconds < 0,
\abs(\intval($milliseconds / self::MILLISECONDS_IN_SECOND)),
\abs(($milliseconds * self::MICROSECONDS_IN_MILLISECOND) % self::MICROSECONDS_IN_SECOND)
);
}
/** @psalm-pure */
public static function day() : self
{
return new self(false, self::HOURS_IN_DAY * self::MINUTES_IN_HOUR * self::SECONDS_IN_MINUTE, 0);
}
/** @psalm-pure */
public static function days(int $days) : self
{
return new self($days < 0, \abs($days * self::HOURS_IN_DAY * self::MINUTES_IN_HOUR * self::SECONDS_IN_MINUTE), 0);
}
/** @psalm-pure */
public static function hour() : self
{
return new self(false, self::MINUTES_IN_HOUR * self::SECONDS_IN_MINUTE, 0);
}
/** @psalm-pure */
public static function hours(int $hours) : self
{
return new self($hours < 0, \abs($hours * self::MINUTES_IN_HOUR * self::SECONDS_IN_MINUTE), 0);
}
/** @psalm-pure */
public static function minute() : self
{
return new self(false, self::SECONDS_IN_MINUTE, 0);
}
/** @psalm-pure */
public static function minutes(int $minutes) : self
{
return new self($minutes < 0, \abs($minutes * self::SECONDS_IN_MINUTE), 0);
}
/** @psalm-pure */
public static function second() : self
{
return new self(false, 1, 0);
}
/** @psalm-pure */
public static function seconds(int $seconds) : self
{
return new self($seconds < 0, \abs($seconds), 0);
}
/** @psalm-pure */
public static function negative(int $seconds, int $microsecond) : self
{
return new self(true, $seconds, $microsecond);
}
/** @psalm-pure */
public static function positive(int $seconds, int $microsecond) : self
{
return new self(false, $seconds, $microsecond);
}
/**
* @return array{seconds: int, microsecond: int, negative: bool}
*/
public function __serialize() : array
{
return [
'seconds' => $this->getSeconds(),
'microsecond' => $this->microsecond(),
'negative' => $this->isNegative(),
];
}
/**
* @psalm-suppress InaccessibleProperty
* @psalm-suppress NullableReturnStatement
* @psalm-suppress InvalidNullableReturnType
*/
public function toDateInterval() : \DateInterval
{
if ($this->dateInterval === null) {
$interval = new \DateInterval(\sprintf('PT%dS', $this->getSeconds()));
if ($this->negative) {
/** @psalm-suppress ImpurePropertyAssignment */
$interval->invert = 1;
}
if ($this->microsecond) {
/** @psalm-suppress ImpurePropertyAssignment */
$interval->f = $this->microsecond / self::MICROSECONDS_IN_SECOND;
}
$this->dateInterval = $interval;
}
return $this->dateInterval;
}
public function isZero() : bool
{
return $this->getSeconds() === 0 && $this->microsecond() === 0;
}
public function isNegative() : bool
{
/** @psalm-suppress UnusedMethodCall */
$this->getSeconds();
return $this->negative;
}
public function isPositive() : bool
{
return !$this->isNegative();
}
public function add(self $timeUnit) : self
{
return self::precise((float) (PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->add($this->inSecondsPrecise(), $timeUnit->inSecondsPrecise())));
}
public function sub(self $timeUnit) : self
{
return self::precise((float) (PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->sub($this->inSecondsPrecise(), $timeUnit->inSecondsPrecise())));
}
public function multiply(self $multiplier) : self
{
return self::precise((float) (PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->multiply($this->inSecondsPrecise(), $multiplier->inSecondsPrecise())));
}
public function divide(self $divider) : self
{
return self::precise((float) (PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->divide($this->inSecondsPrecise(), $divider->inSecondsPrecise())));
}
public function modulo(self $divider) : self
{
return self::precise((float) (PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->modulo($this->inSecondsPrecise(), $divider->inSecondsPrecise())));
}
public function isGreaterThan(self $timeUnit) : bool
{
return PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->isGreaterThan($this->inSecondsPrecise(), $timeUnit->inSecondsPrecise());
}
/** @deprecated Use `isGreaterThanOrEqualTo` instead. Will be removed with 2.0 */
public function isGreaterThanEq(self $timeUnit) : bool
{
return $this->isGreaterThanOrEqualTo($timeUnit);
}
public function isGreaterThanOrEqualTo(self $timeUnit) : bool
{
return PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->isGreaterThanOrEqualTo($this->inSecondsPrecise(), $timeUnit->inSecondsPrecise());
}
public function isLessThan(self $timeUnit) : bool
{
return PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->isLessThan($this->inSecondsPrecise(), $timeUnit->inSecondsPrecise());
}
/** @deprecated Use `isLessThanOrEqualTo` instead. Will be removed with 2.0 */
public function isLessThanEq(self $timeUnit) : bool
{
return $this->isLessThanOrEqualTo($timeUnit);
}
public function isLessThanOrEqualTo(self $timeUnit) : bool
{
return PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->isLessThanOrEqualTo($this->inSecondsPrecise(), $timeUnit->inSecondsPrecise());
}
/**
* @infection-ignore-all
*
* @deprecated Use `isEqualTo` instead. Will be removed with 2.0
*/
public function isEqual(self $timeUnit) : bool
{
return $this->isEqualTo($timeUnit);
}
public function isEqualTo(self $timeUnit) : bool
{
return PreciseCalculator::initialize(self::PRECISION_MICROSECOND)->isEqualTo($this->inSecondsPrecise(), $timeUnit->inSecondsPrecise());
}
/**
* @psalm-suppress InvalidNullableReturnType
*/
public function inSeconds() : int
{
return $this->isNegative() ? -$this->getSeconds() : $this->getSeconds();
}
public function inSecondsPrecise() : string
{
return \sprintf(
'%s%d.%s',
$this->isNegative() === true ? '-' : '',
$this->getSeconds(),
$this->microsecondString()
);
}
public function inSecondsAbs() : int
{
return \abs($this->getSeconds());
}
public function inTimeSeconds() : int
{
return \abs($this->getSeconds() % 60);
}
public function inHours() : int
{
return $this->isNegative()
? -\intval(($this->getSeconds() / self::SECONDS_IN_MINUTE) / self::MINUTES_IN_HOUR)
: \intval(($this->getSeconds() / self::SECONDS_IN_MINUTE) / self::MINUTES_IN_HOUR);
}
public function inHoursAbs() : int
{
return \abs($this->inHours());
}
public function inTimeHours() : int
{
return \abs($this->inHours() % 24);
}
public function inMinutes() : int
{
return $this->negative
? -\intval($this->getSeconds() / self::SECONDS_IN_MINUTE)
: \intval($this->getSeconds() / self::SECONDS_IN_MINUTE);
}
public function inMinutesAbs() : int
{
return \abs($this->inMinutes());
}
public function inTimeMinutes() : int
{
return \abs($this->inMinutes() % 60);
}
public function inDays() : int
{
return $this->isNegative()
? -\intval((($this->getSeconds() / self::SECONDS_IN_MINUTE) / self::MINUTES_IN_HOUR) / self::HOURS_IN_DAY)
: \intval((($this->getSeconds() / self::SECONDS_IN_MINUTE) / self::MINUTES_IN_HOUR) / self::HOURS_IN_DAY);
}
public function inDaysAbs() : int
{
return \abs($this->inDays());
}
/**
* @psalm-suppress NullableReturnStatement
* @psalm-suppress InvalidNullableReturnType
*
* Number of microseconds from last full second to the next full second.
* Do not use this method to combine float seconds because for 50000 it returns 50000 not "050000".
*/
public function microsecond() : int
{
/** @psalm-suppress UnusedMethodCall */
$this->getSeconds();
/** @phpstan-ignore-next-line */
return $this->microsecond;
}
/**
* Number of microseconds from last full second to the next full second.
* Use this method to combine float seconds because for 50000 it returns "050000" not 50000.
*/
public function microsecondString() : string
{
return \str_pad((string) $this->microsecond(), self::PRECISION_MICROSECOND, '0', STR_PAD_LEFT);
}
public function inMilliseconds() : int
{
return $this->isNegative()
? -($this->getSeconds() * 1000 + \intval($this->microsecond() / self::MICROSECONDS_IN_MILLISECOND))
: ($this->getSeconds() * 1000 + \intval($this->microsecond() / self::MICROSECONDS_IN_MILLISECOND));
}
public function inTimeMilliseconds() : int
{
return \abs($this->inMilliseconds() % 1000);
}
public function inMillisecondsAbs() : int
{
return \abs($this->inMilliseconds());
}
public function invert() : self
{
return new self(!$this->isNegative(), $this->getSeconds(), $this->microsecond());
}
public function toNegative() : self
{
if ($this->isNegative()) {
return $this;
}
return $this->invert();
}
public function toPositive() : self
{
if (!$this->isNegative()) {
return $this;
}
return $this->invert();
}
/**
* @psalm-suppress PossiblyNullArgument
* @psalm-suppress PossiblyNullPropertyFetch
* @psalm-suppress InaccessibleProperty
* @psalm-suppress NullableReturnStatement
* @psalm-suppress InvalidNullableReturnType
*/
private function getSeconds() : int
{
if ($this->seconds === null) {
/** @phpstan-ignore-next-line */
$timeUnit = self::days($this->dateInterval->days ? \intval($this->dateInterval->days) : $this->dateInterval->d)
/** @phpstan-ignore-next-line */
->add(self::hours($this->dateInterval->h))
/** @phpstan-ignore-next-line */
->add(self::minutes($this->dateInterval->i))
/** @phpstan-ignore-next-line */
->add(self::seconds($this->dateInterval->s))
/** @phpstan-ignore-next-line */
->add(self::precise($this->dateInterval->f));
/** @phpstan-ignore-next-line */
$timeUnit = $this->dateInterval->invert === 1 ? $timeUnit->invert() : $timeUnit;
$this->negative = $timeUnit->isNegative();
$this->seconds = $timeUnit->getSeconds();
$this->microsecond = $timeUnit->microsecond();
}
return $this->seconds;
}
}
================================================
FILE: src/Aeon/Calendar/Unit.php
================================================
<?php declare(strict_types=1);
namespace Aeon\Calendar;
/**
* @psalm-immutable
*/
interface Unit
{
public function toDateInterval() : \DateInterval;
public function invert() : self;
public function isNegative() : bool;
public function toNegative() : self;
public function toPositive() : self;
}
================================================
FILE: tests/Aeon/Calculator/Tests/Unit/BCMathCalculatorTest.php
================================================
<?php
declare(strict_types=1);
namespace Aeon\Calculator\Tests\Unit;
use Aeon\Calculator\BCMathCalculator;
use Aeon\Calculator\Exception\InvalidTypeException;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
final class BCMathCalculatorTest extends TestCase
{
/**
* @return \Generator<int, array{string, float, float}, mixed, void>
*/
public static function add_data_provider() : \Generator
{
yield ['3.000000', 2.0, 1.0];
yield ['3.000000', 2, 1];
yield ['-1.000000', -2, 1];
yield ['0.000200', 0.000_100, 0.000_100];
yield ['0.000201', 0.000_101, 0.000_100];
y
gitextract_0agqa1a6/
├── .gitattributes
├── .github/
│ └── workflows/
│ └── readonly.yaml
├── .gitignore
├── README.md
├── benchmark/
│ └── Aeon/
│ └── Calendar/
│ └── Benchmark/
│ └── Gregorian/
│ ├── DateTimeFormatBench.php
│ ├── DateTimeInitBench.php
│ ├── DateTimeUnixTimestampBench.php
│ ├── DayIterationBench.php
│ ├── TimeUnitInitBench.php
│ └── TimeZoneInitBench.php
├── composer.json
├── phpbench.json
├── src/
│ └── Aeon/
│ ├── Calculator/
│ │ ├── BCMathCalculator.php
│ │ ├── Calculator.php
│ │ ├── Exception/
│ │ │ ├── Exception.php
│ │ │ └── InvalidTypeException.php
│ │ ├── PHPCalculator.php
│ │ └── PreciseCalculator.php
│ └── Calendar/
│ ├── Exception/
│ │ ├── Exception.php
│ │ └── InvalidArgumentException.php
│ ├── Gregorian/
│ │ ├── Calendar.php
│ │ ├── DateTime.php
│ │ ├── DateTimeIntervalIterator.php
│ │ ├── DateTimeIterator.php
│ │ ├── Day/
│ │ │ └── WeekDay.php
│ │ ├── Day.php
│ │ ├── Days.php
│ │ ├── DaysIterator.php
│ │ ├── GregorianCalendar.php
│ │ ├── GregorianCalendarStub.php
│ │ ├── Interval.php
│ │ ├── LeapSecond.php
│ │ ├── LeapSeconds.php
│ │ ├── Month.php
│ │ ├── MonthDays.php
│ │ ├── Months.php
│ │ ├── MonthsIterator.php
│ │ ├── Psr20CalendarAdapter.php
│ │ ├── Quarter.php
│ │ ├── Time.php
│ │ ├── TimeEpoch.php
│ │ ├── TimePeriod.php
│ │ ├── TimePeriods.php
│ │ ├── TimePeriodsIterator.php
│ │ ├── TimePeriodsSort.php
│ │ ├── TimeZone/
│ │ │ └── TimeOffset.php
│ │ ├── TimeZone.php
│ │ ├── Year.php
│ │ ├── YearMonths.php
│ │ └── Years.php
│ ├── RelativeTimeUnit.php
│ ├── Stopwatch.php
│ ├── TimeUnit/
│ │ └── HRTime.php
│ ├── TimeUnit.php
│ └── Unit.php
└── tests/
└── Aeon/
├── Calculator/
│ └── Tests/
│ └── Unit/
│ ├── BCMathCalculatorTest.php
│ ├── PHPCalculatorTest.php
│ └── PreciseCalculatorTest.php
└── Calendar/
└── Tests/
├── Functional/
│ └── Gregorian/
│ └── GregorianCalendarTest.php
└── Unit/
├── Gregorian/
│ ├── DateTimeIntervalIteratorTest.php
│ ├── DateTimeIteratorTest.php
│ ├── DateTimeTest.php
│ ├── Day/
│ │ └── WeekDayTest.php
│ ├── DayTest.php
│ ├── DaysIteratorTest.php
│ ├── DaysTest.php
│ ├── LeapSecondTest.php
│ ├── LeapSecondsTest.php
│ ├── MonthDaysTest.php
│ ├── MonthTest.php
│ ├── MonthsIteratorTest.php
│ ├── MonthsTest.php
│ ├── Psr20ClockAdapterTest.php
│ ├── QuarterTest.php
│ ├── TimeEpochTest.php
│ ├── TimePeriodTest.php
│ ├── TimePeriodsIteratorTest.php
│ ├── TimePeriodsSortTest.php
│ ├── TimePeriodsTest.php
│ ├── TimeTest.php
│ ├── TimeZone/
│ │ └── TimeOffsetTest.php
│ ├── TimeZoneTest.php
│ ├── YearMonthsTest.php
│ ├── YearTest.php
│ └── YearsTest.php
├── IntervalTest.php
├── RelativeTimeUnitTest.php
├── StopwatchTest.php
├── TimeUnit/
│ └── HRTimeTest.php
└── TimeUnitTest.php
SYMBOL INDEX (1331 symbols across 84 files)
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeFormatBench.php
class DateTimeFormatBench (line 18) | final class DateTimeFormatBench
method init (line 24) | public function init() : void
method bench_aeon_format (line 30) | public function bench_aeon_format() : void
method bench_php_format (line 35) | public function bench_php_format() : void
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeInitBench.php
class DateTimeInitBench (line 21) | final class DateTimeInitBench
method bench_datetime_immutable_constructor (line 23) | public function bench_datetime_immutable_constructor() : void
method bench_datetime_constructor (line 28) | public function bench_datetime_constructor() : void
method bench_aeon_datetime_from_datetime_immutable (line 33) | public function bench_aeon_datetime_from_datetime_immutable() : void
method bench_aeon_datetime_create (line 38) | public function bench_aeon_datetime_create() : void
method bench_aeon_datetime_constructor (line 43) | public function bench_aeon_datetime_constructor() : void
method bench_aeon_datetime_from_string (line 52) | public function bench_aeon_datetime_from_string() : void
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeUnixTimestampBench.php
class DateTimeUnixTimestampBench (line 16) | final class DateTimeUnixTimestampBench
method __construct (line 22) | public function __construct()
method bench_aeon_unix_timestamp (line 28) | public function bench_aeon_unix_timestamp() : void
method bench_php_unix_timestamp (line 33) | public function bench_php_unix_timestamp() : void
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/DayIterationBench.php
class DayIterationBench (line 17) | final class DayIterationBench
method bench_aeon_iteration_over_last_half_of_the_year (line 19) | public function bench_aeon_iteration_over_last_half_of_the_year() : void
method bench_php_iteration_over_last_half_of_the_year (line 31) | public function bench_php_iteration_over_last_half_of_the_year() : void
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/TimeUnitInitBench.php
class TimeUnitInitBench (line 16) | final class TimeUnitInitBench
method bench_time_unit_positive (line 18) | public function bench_time_unit_positive() : void
method bench_time_unit_negative (line 23) | public function bench_time_unit_negative() : void
FILE: benchmark/Aeon/Calendar/Benchmark/Gregorian/TimeZoneInitBench.php
class TimeZoneInitBench (line 16) | final class TimeZoneInitBench
method bench_time_zone_init_by_static_name (line 18) | public function bench_time_zone_init_by_static_name() : void
method bench_time_zone_init_by_abbreviation (line 23) | public function bench_time_zone_init_by_abbreviation() : void
method bench_time_zone_init_by_id (line 28) | public function bench_time_zone_init_by_id() : void
method bench_time_zone_init_by_offset (line 33) | public function bench_time_zone_init_by_offset() : void
method bench_time_zone_init_by_string (line 38) | public function bench_time_zone_init_by_string() : void
method bench_php_datetime_zone_constructor (line 43) | public function bench_php_datetime_zone_constructor() : void
FILE: src/Aeon/Calculator/BCMathCalculator.php
class BCMathCalculator (line 12) | final class BCMathCalculator implements Calculator
method __construct (line 16) | public function __construct(int $precision)
method supported (line 24) | public static function supported() : bool
method precision (line 29) | public function precision() : int
method divide (line 38) | public function divide(string $value, string $divisor) : string
method modulo (line 55) | public function modulo(string $value, string $divisor) : string
method multiply (line 68) | public function multiply(string $value, string $multiplier) : string
method add (line 77) | public function add(string $value, string $nextValue) : string
method sub (line 86) | public function sub(string $value, string $nextValue) : string
method isGreaterThan (line 95) | public function isGreaterThan(string $value, string $nextValue) : bool
method isGreaterThanEq (line 109) | public function isGreaterThanEq(string $value, string $nextValue) : bool
method isGreaterThanOrEqualTo (line 114) | public function isGreaterThanOrEqualTo(string $value, string $nextValu...
method isLessThan (line 123) | public function isLessThan(string $value, string $nextValue) : bool
method isLessThanEq (line 137) | public function isLessThanEq(string $value, string $nextValue) : bool
method isLessThanOrEqualTo (line 142) | public function isLessThanOrEqualTo(string $value, string $nextValue) ...
method isEqual (line 156) | public function isEqual(string $value, string $nextValue) : bool
method isEqualTo (line 161) | public function isEqualTo(string $value, string $nextValue) : bool
FILE: src/Aeon/Calculator/Calculator.php
type Calculator (line 10) | interface Calculator
method precision (line 12) | public function precision() : int;
method modulo (line 14) | public function modulo(string $value, string $divisor) : string;
method divide (line 16) | public function divide(string $value, string $divisor) : string;
method multiply (line 18) | public function multiply(string $value, string $multiplier) : string;
method add (line 20) | public function add(string $value, string $nextValue) : string;
method sub (line 22) | public function sub(string $value, string $nextValue) : string;
method isGreaterThan (line 24) | public function isGreaterThan(string $value, string $nextValue) : bool;
method isGreaterThanEq (line 31) | public function isGreaterThanEq(string $value, string $nextValue) : bool;
method isGreaterThanOrEqualTo (line 33) | public function isGreaterThanOrEqualTo(string $value, string $nextValu...
method isLessThan (line 35) | public function isLessThan(string $value, string $nextValue) : bool;
method isLessThanEq (line 42) | public function isLessThanEq(string $value, string $nextValue) : bool;
method isLessThanOrEqualTo (line 44) | public function isLessThanOrEqualTo(string $value, string $nextValue) ...
method isEqual (line 51) | public function isEqual(string $value, string $nextValue) : bool;
method isEqualTo (line 53) | public function isEqualTo(string $value, string $nextValue) : bool;
FILE: src/Aeon/Calculator/Exception/Exception.php
class Exception (line 7) | class Exception extends \Exception
FILE: src/Aeon/Calculator/Exception/InvalidTypeException.php
class InvalidTypeException (line 7) | final class InvalidTypeException extends Exception
FILE: src/Aeon/Calculator/PHPCalculator.php
class PHPCalculator (line 10) | final class PHPCalculator implements Calculator
method __construct (line 14) | public function __construct(int $precision)
method precision (line 19) | public function precision() : int
method divide (line 24) | public function divide(string $value, string $divisor) : string
method modulo (line 29) | public function modulo(string $value, string $divisor) : string
method multiply (line 34) | public function multiply(string $value, string $multiplier) : string
method add (line 39) | public function add(string $value, string $nextValue) : string
method sub (line 44) | public function sub(string $value, string $nextValue) : string
method isGreaterThan (line 49) | public function isGreaterThan(string $value, string $nextValue) : bool
method isGreaterThanEq (line 60) | public function isGreaterThanEq(string $value, string $nextValue) : bool
method isGreaterThanOrEqualTo (line 65) | public function isGreaterThanOrEqualTo(string $value, string $nextValu...
method isLessThan (line 71) | public function isLessThan(string $value, string $nextValue) : bool
method isLessThanEq (line 82) | public function isLessThanEq(string $value, string $nextValue) : bool
method isLessThanOrEqualTo (line 87) | public function isLessThanOrEqualTo(string $value, string $nextValue) ...
method isEqual (line 98) | public function isEqual(string $value, string $nextValue) : bool
method isEqualTo (line 103) | public function isEqualTo(string $value, string $nextValue) : bool
FILE: src/Aeon/Calculator/PreciseCalculator.php
class PreciseCalculator (line 7) | final class PreciseCalculator
method initialize (line 16) | public static function initialize(int $precision) : Calculator
FILE: src/Aeon/Calendar/Exception/Exception.php
class Exception (line 7) | class Exception extends \Exception
FILE: src/Aeon/Calendar/Exception/InvalidArgumentException.php
class InvalidArgumentException (line 7) | final class InvalidArgumentException extends Exception
FILE: src/Aeon/Calendar/Gregorian/Calendar.php
type Calendar (line 10) | interface Calendar
method timeZone (line 12) | public function timeZone() : TimeZone;
method currentYear (line 14) | public function currentYear() : Year;
method currentMonth (line 16) | public function currentMonth() : Month;
method currentDay (line 18) | public function currentDay() : Day;
method yesterday (line 20) | public function yesterday() : DateTime;
method tomorrow (line 22) | public function tomorrow() : DateTime;
method now (line 24) | public function now() : DateTime;
FILE: src/Aeon/Calendar/Gregorian/DateTime.php
class DateTime (line 16) | final class DateTime
method __construct (line 24) | public function __construct(Day $day, Time $time, TimeZone $timeZone)
method create (line 34) | public static function create(int $year, int $month, int $day, int $ho...
method fromDateTime (line 58) | public static function fromDateTime(\DateTimeInterface $dateTime) : self
method fromString (line 77) | public static function fromString(string $date) : self
method fromTimestampUnix (line 101) | public static function fromTimestampUnix(int $timestamp) : self
method __toString (line 116) | public function __toString() : string
method __debugInfo (line 124) | public function __debugInfo() : array
method __serialize (line 137) | public function __serialize() : array
method __unserialize (line 149) | public function __unserialize(array $data) : void
method year (line 156) | public function year() : Year
method month (line 161) | public function month() : Month
method day (line 166) | public function day() : Day
method time (line 171) | public function time() : Time
method setTime (line 176) | public function setTime(Time $time) : self
method setTimeIn (line 185) | public function setTimeIn(Time $time, TimeZone $timeZone) : self
method setDay (line 195) | public function setDay(Day $day) : self
method toDateTimeImmutable (line 204) | public function toDateTimeImmutable() : \DateTimeImmutable
method toAtomicTime (line 221) | public function toAtomicTime() : self
method toGPSTime (line 226) | public function toGPSTime() : self
method format (line 233) | public function format(string $format) : string
method timeZone (line 238) | public function timeZone() : TimeZone
method timeZoneAbbreviation (line 243) | public function timeZoneAbbreviation() : TimeZone
method toTimeZone (line 252) | public function toTimeZone(TimeZone $dateTimeZone) : self
method toISO8601 (line 257) | public function toISO8601(bool $extended = true) : string
method isDaylightSaving (line 264) | public function isDaylightSaving() : bool
method isDaylight (line 269) | public function isDaylight() : bool
method timestamp (line 274) | public function timestamp(TimeEpoch $timeEpoch) : TimeUnit
method timestampUNIX (line 305) | public function timestampUNIX() : TimeUnit
method modify (line 316) | public function modify(string $modifier) : self
method addHour (line 371) | public function addHour() : self
method subHour (line 376) | public function subHour() : self
method addHours (line 381) | public function addHours(int $hours) : self
method subHours (line 386) | public function subHours(int $hours) : self
method addMinute (line 391) | public function addMinute() : self
method subMinute (line 396) | public function subMinute() : self
method addMinutes (line 401) | public function addMinutes(int $minutes) : self
method subMinutes (line 406) | public function subMinutes(int $minutes) : self
method addSecond (line 411) | public function addSecond() : self
method subSecond (line 416) | public function subSecond() : self
method addSeconds (line 421) | public function addSeconds(int $seconds) : self
method subSeconds (line 426) | public function subSeconds(int $seconds) : self
method addDay (line 431) | public function addDay() : self
method subDay (line 436) | public function subDay() : self
method addDays (line 441) | public function addDays(int $days) : self
method subDays (line 446) | public function subDays(int $days) : self
method addMonth (line 451) | public function addMonth() : self
method subMonth (line 456) | public function subMonth() : self
method addMonths (line 461) | public function addMonths(int $months) : self
method subMonths (line 466) | public function subMonths(int $months) : self
method addYear (line 471) | public function addYear() : self
method subYear (line 476) | public function subYear() : self
method addYears (line 481) | public function addYears(int $years) : self
method subYears (line 486) | public function subYears(int $years) : self
method midnight (line 491) | public function midnight() : self
method noon (line 500) | public function noon() : self
method endOfDay (line 509) | public function endOfDay() : self
method yesterday (line 518) | public function yesterday() : self
method tomorrow (line 523) | public function tomorrow() : self
method add (line 534) | public function add(Unit $timeUnit) : self
method sub (line 560) | public function sub(Unit $timeUnit) : self
method isEqual (line 570) | public function isEqual(self $dateTime) : bool
method isEqualTo (line 575) | public function isEqualTo(self $dateTime) : bool
method isAfter (line 580) | public function isAfter(self $dateTime) : bool
method isAfterOrEqual (line 590) | public function isAfterOrEqual(self $dateTime) : bool
method isAfterOrEqualTo (line 595) | public function isAfterOrEqualTo(self $dateTime) : bool
method isBeforeOrEqual (line 605) | public function isBeforeOrEqual(self $dateTime) : bool
method isBeforeOrEqualTo (line 610) | public function isBeforeOrEqualTo(self $dateTime) : bool
method isBefore (line 615) | public function isBefore(self $dateTime) : bool
method until (line 620) | public function until(self $dateTime) : TimePeriod
method since (line 625) | public function since(self $dateTime) : TimePeriod
method distance (line 630) | public function distance(self $dateTime) : TimeUnit
method distanceSince (line 635) | public function distanceSince(self $dateTime) : TimeUnit
method distanceUntil (line 640) | public function distanceUntil(self $dateTime) : TimeUnit
method iterate (line 645) | public function iterate(self $pointInTime, TimeUnit $by) : TimePeriods
method isAmbiguous (line 652) | public function isAmbiguous() : bool
method quarter (line 679) | public function quarter() : Quarter
method compareTo (line 684) | public function compareTo(self $dateTime) : int
FILE: src/Aeon/Calendar/Gregorian/DateTimeIntervalIterator.php
class DateTimeIntervalIterator (line 9) | final class DateTimeIntervalIterator extends \FilterIterator
method __construct (line 13) | public function __construct(DateTime $start, DateTime $end, Unit $time...
method start (line 19) | public function start() : DateTime
method end (line 24) | public function end() : DateTime
method unit (line 29) | public function unit() : Unit
method isForward (line 34) | public function isForward() : bool
method interval (line 39) | public function interval() : Interval
method hasNext (line 44) | public function hasNext() : bool
method accept (line 71) | public function accept() : bool
method key (line 96) | public function key() : int
method current (line 116) | public function current() : ?DateTime
method getInnerIterator (line 128) | public function getInnerIterator() : DateTimeIterator
FILE: src/Aeon/Calendar/Gregorian/DateTimeIterator.php
class DateTimeIterator (line 13) | final class DateTimeIterator implements \Iterator
method __construct (line 32) | public function __construct(DateTime $start, DateTime $end, Unit $time...
method isForward (line 51) | public function isForward() : bool
method unit (line 56) | public function unit() : Unit
method start (line 61) | public function start() : DateTime
method end (line 66) | public function end() : DateTime
method current (line 71) | public function current() : DateTime
method next (line 76) | public function next() : void
method hasNext (line 82) | public function hasNext() : bool
method key (line 91) | public function key() : int
method isFirst (line 96) | public function isFirst() : bool
method valid (line 101) | public function valid() : bool
method rewind (line 114) | public function rewind() : void
FILE: src/Aeon/Calendar/Gregorian/Day.php
class Day (line 15) | final class Day
method __construct (line 21) | public function __construct(Month $month, int $number)
method create (line 34) | public static function create(int $year, int $month, int $day) : self
method fromDateTime (line 53) | public static function fromDateTime(\DateTimeInterface $dateTime) : self
method fromString (line 69) | public static function fromString(string $date) : self
method __debugInfo (line 81) | public function __debugInfo() : array
method __serialize (line 93) | public function __serialize() : array
method __unserialize (line 104) | public function __unserialize(array $data) : void
method toString (line 110) | public function toString() : string
method timeBetween (line 115) | public function timeBetween(self $day) : TimeUnit
method plus (line 121) | public function plus(int $years, int $months, int $days) : self
method add (line 126) | public function add(int $years, int $months, int $days) : self
method minus (line 146) | public function minus(int $years, int $months, int $days) : self
method sub (line 151) | public function sub(int $years, int $months, int $days) : self
method plusDays (line 175) | public function plusDays(int $days) : self
method addDays (line 180) | public function addDays(int $days) : self
method minusDays (line 190) | public function minusDays(int $days) : self
method subDays (line 195) | public function subDays(int $days) : self
method plusMonths (line 205) | public function plusMonths(int $months) : self
method addMonths (line 210) | public function addMonths(int $months) : self
method minusMonths (line 220) | public function minusMonths(int $months) : self
method subMonths (line 225) | public function subMonths(int $months) : self
method plusYears (line 235) | public function plusYears(int $years) : self
method addYears (line 240) | public function addYears(int $years) : self
method minusYears (line 250) | public function minusYears(int $years) : self
method subYears (line 255) | public function subYears(int $years) : self
method previous (line 260) | public function previous() : self
method next (line 265) | public function next() : self
method midnight (line 270) | public function midnight(TimeZone $timeZone) : DateTime
method noon (line 275) | public function noon(TimeZone $timeZone) : DateTime
method endOfDay (line 280) | public function endOfDay(TimeZone $timeZone) : DateTime
method setTime (line 285) | public function setTime(Time $time, TimeZone $timeZone) : DateTime
method month (line 294) | public function month() : Month
method year (line 299) | public function year() : Year
method number (line 304) | public function number() : int
method weekDay (line 309) | public function weekDay() : WeekDay
method weekOfYear (line 317) | public function weekOfYear() : int
method weekOfMonth (line 325) | public function weekOfMonth() : int
method dayOfYear (line 333) | public function dayOfYear() : int
method isWeekend (line 338) | public function isWeekend() : bool
method toDateTimeImmutable (line 343) | public function toDateTimeImmutable() : \DateTimeImmutable
method format (line 353) | public function format(string $format) : string
method isEqual (line 363) | public function isEqual(self $day) : bool
method isEqualTo (line 368) | public function isEqualTo(self $day) : bool
method isBefore (line 374) | public function isBefore(self $day) : bool
method isBeforeOrEqual (line 392) | public function isBeforeOrEqual(self $day) : bool
method isBeforeOrEqualTo (line 397) | public function isBeforeOrEqualTo(self $day) : bool
method isAfter (line 410) | public function isAfter(self $day) : bool
method isAfterOrEqual (line 428) | public function isAfterOrEqual(self $day) : bool
method isAfterOrEqualTo (line 433) | public function isAfterOrEqualTo(self $day) : bool
method iterate (line 446) | public function iterate(self $destination, Interval $interval) : Days
method until (line 453) | public function until(self $day, Interval $interval) : Days
method since (line 479) | public function since(self $day, Interval $interval) : Days
method distance (line 505) | public function distance(self $to) : TimeUnit
method quarter (line 510) | public function quarter() : Quarter
method compareTo (line 515) | public function compareTo(self $day) : int
FILE: src/Aeon/Calendar/Gregorian/Day/WeekDay.php
class WeekDay (line 12) | final class WeekDay
method __construct (line 36) | public function __construct(int $number)
method monday (line 48) | public static function monday() : self
method tuesday (line 56) | public static function tuesday() : self
method wednesday (line 64) | public static function wednesday() : self
method thursday (line 72) | public static function thursday() : self
method friday (line 80) | public static function friday() : self
method saturday (line 88) | public static function saturday() : self
method sunday (line 96) | public static function sunday() : self
method number (line 101) | public function number() : int
method name (line 106) | public function name() : string
method shortName (line 111) | public function shortName() : string
method isEqual (line 121) | public function isEqual(self $weekDay) : bool
method isEqualTo (line 126) | public function isEqualTo(self $weekDay) : bool
method isWeekend (line 131) | public function isWeekend() : bool
FILE: src/Aeon/Calendar/Gregorian/Days.php
class Days (line 12) | final class Days implements \Countable, \IteratorAggregate
method __construct (line 22) | private function __construct(\Iterator $days)
method fromArray (line 30) | public static function fromArray(Day ...$days) : self
method fromDateTimeIterator (line 39) | public static function fromDateTimeIterator(DateTimeIntervalIterator $...
method all (line 50) | public function all() : array
method map (line 64) | public function map(callable $iterator) : array
method filter (line 76) | public function filter(callable $iterator) : self
method count (line 81) | public function count() : int
method getIterator (line 89) | public function getIterator() : \Traversable
FILE: src/Aeon/Calendar/Gregorian/DaysIterator.php
class DaysIterator (line 7) | final class DaysIterator extends \IteratorIterator
method __construct (line 12) | private function __construct(\Traversable $iterator)
method fromDateTimeIterator (line 20) | public static function fromDateTimeIterator(DateTimeIntervalIterator $...
method current (line 25) | public function current() : ?Day
method reverse (line 41) | public function reverse() : self
FILE: src/Aeon/Calendar/Gregorian/GregorianCalendar.php
class GregorianCalendar (line 10) | final class GregorianCalendar implements Calendar
method __construct (line 14) | public function __construct(TimeZone $timeZone)
method UTC (line 22) | public static function UTC() : self
method systemDefault (line 32) | public static function systemDefault() : self
method timeZone (line 37) | public function timeZone() : TimeZone
method currentYear (line 42) | public function currentYear() : Year
method currentMonth (line 47) | public function currentMonth() : Month
method currentDay (line 52) | public function currentDay() : Day
method now (line 57) | public function now() : DateTime
method yesterday (line 67) | public function yesterday() : DateTime
method tomorrow (line 72) | public function tomorrow() : DateTime
FILE: src/Aeon/Calendar/Gregorian/GregorianCalendarStub.php
class GregorianCalendarStub (line 12) | final class GregorianCalendarStub implements Calendar
method __construct (line 18) | public function __construct(TimeZone $timeZone, ?DateTime $currentDate...
method UTC (line 27) | public static function UTC(?DateTime $currentDate = null) : self
method systemDefault (line 37) | public static function systemDefault(?DateTime $currentDate = null) : ...
method timeZone (line 42) | public function timeZone() : TimeZone
method currentYear (line 47) | public function currentYear() : Year
method currentMonth (line 52) | public function currentMonth() : Month
method currentDay (line 57) | public function currentDay() : Day
method now (line 62) | public function now() : DateTime
method yesterday (line 69) | public function yesterday() : DateTime
method tomorrow (line 74) | public function tomorrow() : DateTime
method setNow (line 82) | public function setNow(DateTime $dateTime) : void
FILE: src/Aeon/Calendar/Gregorian/Interval.php
class Interval (line 10) | final class Interval
method __construct (line 22) | private function __construct(int $type)
method closed (line 32) | public static function closed() : self
method rightOpen (line 42) | public static function rightOpen() : self
method leftOpen (line 52) | public static function leftOpen() : self
method open (line 62) | public static function open() : self
method isOpen (line 67) | public function isOpen() : bool
method isLeftOpen (line 72) | public function isLeftOpen() : bool
method isRightOpen (line 77) | public function isRightOpen() : bool
method isClosed (line 82) | public function isClosed() : bool
FILE: src/Aeon/Calendar/Gregorian/LeapSecond.php
class LeapSecond (line 13) | final class LeapSecond
method __construct (line 19) | public function __construct(DateTime $dateTime, TimeUnit $offsetTAI)
method __serialize (line 32) | public function __serialize() : array
method dateTime (line 40) | public function dateTime() : DateTime
method offsetTAI (line 45) | public function offsetTAI() : TimeUnit
method isEqual (line 55) | public function isEqual(self $second) : bool
method isEqualTo (line 60) | public function isEqualTo(self $second) : bool
FILE: src/Aeon/Calendar/Gregorian/LeapSeconds.php
class LeapSeconds (line 12) | final class LeapSeconds
method __construct (line 23) | private function __construct(DateTime $listExpiration, LeapSecond ...$...
method load (line 39) | public static function load() : self
method expirationDate (line 80) | public function expirationDate() : DateTime
method since (line 85) | public function since(DateTime $dateTime) : self
method until (line 95) | public function until(DateTime $dateTime) : self
method findAllBetween (line 105) | public function findAllBetween(TimePeriod $timePeriod) : self
method offsetTAI (line 118) | public function offsetTAI() : TimeUnit
method filter (line 128) | public function filter(callable $filter) : self
method count (line 136) | public function count() : TimeUnit
method all (line 144) | public function all() : array
FILE: src/Aeon/Calendar/Gregorian/Month.php
class Month (line 14) | final class Month
method __construct (line 24) | public function __construct(Year $year, int $number)
method create (line 38) | public static function create(int $year, int $month) : self
method fromDateTime (line 51) | public static function fromDateTime(\DateTimeInterface $dateTime) : self
method fromString (line 64) | public static function fromString(string $date) : self
method __debugInfo (line 76) | public function __debugInfo() : array
method __serialize (line 87) | public function __serialize() : array
method __unserialize (line 98) | public function __unserialize(array $data) : void
method __toString (line 105) | public function __toString() : string
method toString (line 110) | public function toString() : string
method previous (line 115) | public function previous() : self
method next (line 120) | public function next() : self
method plus (line 130) | public function plus(int $years, int $months) : self
method add (line 135) | public function add(int $years, int $months) : self
method minus (line 155) | public function minus(int $years, int $months) : self
method sub (line 160) | public function sub(int $years, int $months) : self
method plusMonths (line 180) | public function plusMonths(int $months) : self
method addMonths (line 185) | public function addMonths(int $months) : self
method minusMonths (line 210) | public function minusMonths(int $months) : self
method subMonths (line 215) | public function subMonths(int $months) : self
method plusYears (line 241) | public function plusYears(int $years) : self
method addYears (line 246) | public function addYears(int $years) : self
method minusYears (line 256) | public function minusYears(int $years) : self
method subYears (line 261) | public function subYears(int $years) : self
method firstDay (line 266) | public function firstDay() : Day
method lastDay (line 271) | public function lastDay() : Day
method number (line 276) | public function number() : int
method year (line 281) | public function year() : Year
method days (line 286) | public function days() : MonthDays
method numberOfDays (line 291) | public function numberOfDays() : int
method shortName (line 297) | public function shortName() : string
method name (line 302) | public function name() : string
method toDateTimeImmutable (line 307) | public function toDateTimeImmutable() : \DateTimeImmutable
method iterate (line 316) | public function iterate(self $destination, Interval $interval) : Months
method until (line 323) | public function until(self $month, Interval $interval) : Months
method since (line 347) | public function since(self $month, Interval $interval) : Months
method isEqual (line 376) | public function isEqual(self $month) : bool
method isEqualTo (line 381) | public function isEqualTo(self $month) : bool
method isBefore (line 387) | public function isBefore(self $month) : bool
method isBeforeOrEqual (line 405) | public function isBeforeOrEqual(self $month) : bool
method isBeforeOrEqualTo (line 410) | public function isBeforeOrEqualTo(self $month) : bool
method isAfter (line 423) | public function isAfter(self $month) : bool
method isAfterOrEqual (line 441) | public function isAfterOrEqual(self $month) : bool
method isAfterOrEqualTo (line 446) | public function isAfterOrEqualTo(self $month) : bool
method distance (line 459) | public function distance(self $to) : TimeUnit
method quarter (line 464) | public function quarter() : Quarter
method compareTo (line 469) | public function compareTo(self $month) : int
FILE: src/Aeon/Calendar/Gregorian/MonthDays.php
class MonthDays (line 10) | final class MonthDays implements \Countable
method __construct (line 14) | public function __construct(Month $month)
method count (line 19) | public function count() : int
method first (line 24) | public function first() : Day
method last (line 29) | public function last() : Day
method all (line 37) | public function all() : array
method map (line 53) | public function map(callable $iterator) : array
method filter (line 68) | public function filter(callable $iterator) : Days
FILE: src/Aeon/Calendar/Gregorian/Months.php
class Months (line 12) | final class Months implements \Countable, \IteratorAggregate
method __construct (line 22) | private function __construct(\Iterator $months)
method fromArray (line 30) | public static function fromArray(Month ...$days) : self
method fromDateTimeIterator (line 39) | public static function fromDateTimeIterator(DateTimeIntervalIterator $...
method all (line 50) | public function all() : array
method map (line 62) | public function map(callable $iterator) : array
method filter (line 74) | public function filter(callable $iterator) : self
method count (line 79) | public function count() : int
method getIterator (line 87) | public function getIterator() : \Traversable
FILE: src/Aeon/Calendar/Gregorian/MonthsIterator.php
class MonthsIterator (line 7) | final class MonthsIterator extends \IteratorIterator
method __construct (line 12) | private function __construct(\Traversable $iterator)
method fromDateTimeIterator (line 20) | public static function fromDateTimeIterator(DateTimeIntervalIterator $...
method current (line 25) | public function current() : ?Month
method reverse (line 41) | public function reverse() : self
FILE: src/Aeon/Calendar/Gregorian/Psr20CalendarAdapter.php
class Psr20CalendarAdapter (line 8) | final class Psr20CalendarAdapter implements ClockInterface
method __construct (line 10) | public function __construct(private readonly Calendar $calendar)
method now (line 14) | public function now() : \DateTimeImmutable
FILE: src/Aeon/Calendar/Gregorian/Quarter.php
class Quarter (line 12) | final class Quarter
method __construct (line 18) | public function __construct(int $number, Months $months)
method number (line 63) | public function number() : int
method months (line 68) | public function months() : Months
FILE: src/Aeon/Calendar/Gregorian/Time.php
class Time (line 13) | final class Time
method __construct (line 25) | public function __construct(int $hour, int $minute, int $second, int $...
method fromDateTime (line 56) | public static function fromDateTime(\DateTimeInterface $dateTime) : self
method fromString (line 72) | public static function fromString(string $time) : self
method __debugInfo (line 84) | public function __debugInfo() : array
method __serialize (line 97) | public function __serialize() : array
method __unserialize (line 110) | public function __unserialize(array $data) : void
method format (line 118) | public function format(string $format) : string
method toTimeUnit (line 123) | public function toTimeUnit() : TimeUnit
method toString (line 130) | public function toString() : string
method hour (line 138) | public function hour() : int
method minute (line 143) | public function minute() : int
method second (line 148) | public function second() : int
method microsecond (line 153) | public function microsecond() : int
method millisecond (line 158) | public function millisecond() : int
method isAM (line 163) | public function isAM() : bool
method isPM (line 168) | public function isPM() : bool
method isGreaterThan (line 178) | public function isGreaterThan(self $time) : bool
method isAfter (line 183) | public function isAfter(self $time) : bool
method isGreaterThanEq (line 196) | public function isGreaterThanEq(self $time) : bool
method isAfterOrEqualTo (line 201) | public function isAfterOrEqualTo(self $time) : bool
method isEqual (line 214) | public function isEqual(self $time) : bool
method isEqualTo (line 219) | public function isEqualTo(self $time) : bool
method isLessThan (line 232) | public function isLessThan(self $time) : bool
method isBefore (line 237) | public function isBefore(self $time) : bool
method isLessThanEq (line 250) | public function isLessThanEq(self $time) : bool
method isBeforeOrEqualTo (line 255) | public function isBeforeOrEqualTo(self $time) : bool
method isMidnight (line 263) | public function isMidnight() : bool
method isNotMidnight (line 271) | public function isNotMidnight() : bool
method add (line 276) | public function add(TimeUnit $timeUnit) : self
method sub (line 281) | public function sub(TimeUnit $timeUnit) : self
method compareTo (line 287) | public function compareTo(self $time) : int
method toDateTimeImmutable (line 298) | private function toDateTimeImmutable() : \DateTimeImmutable
FILE: src/Aeon/Calendar/Gregorian/TimeEpoch.php
class TimeEpoch (line 12) | final class TimeEpoch
method __construct (line 26) | private function __construct(int $type, DateTime $dateTime)
method UNIX (line 37) | public static function UNIX() : self
method POSIX (line 47) | public static function POSIX() : self
method UTC (line 57) | public static function UTC() : self
method GPS (line 68) | public static function GPS() : self
method TAI (line 78) | public static function TAI() : self
method type (line 83) | public function type() : int
method date (line 88) | public function date() : DateTime
method distanceTo (line 96) | public function distanceTo(self $timeEpoch) : TimeUnit
FILE: src/Aeon/Calendar/Gregorian/TimePeriod.php
class TimePeriod (line 14) | final class TimePeriod
method __construct (line 20) | public function __construct(DateTime $start, DateTime $end)
method __serialize (line 29) | public function __serialize() : array
method start (line 37) | public function start() : DateTime
method end (line 42) | public function end() : DateTime
method isForward (line 47) | public function isForward() : bool
method isBackward (line 52) | public function isBackward() : bool
method distance (line 60) | public function distance() : TimeUnit
method leapSeconds (line 72) | public function leapSeconds() : LeapSeconds
method iterate (line 80) | public function iterate(Unit $timeUnit, Interval $interval) : TimePeriods
method iterateBackward (line 88) | public function iterateBackward(Unit $timeUnit, Interval $interval) : ...
method overlaps (line 93) | public function overlaps(self $timePeriod) : bool
method contains (line 144) | public function contains(self $timePeriod) : bool
method revert (line 149) | public function revert() : self
method merge (line 154) | public function merge(self $timePeriod) : self
method abuts (line 170) | public function abuts(self $timePeriod) : bool
method isEqual (line 196) | public function isEqual(self $period) : bool
method isEqualTo (line 201) | public function isEqualTo(self $period) : bool
FILE: src/Aeon/Calendar/Gregorian/TimePeriods.php
class TimePeriods (line 10) | final class TimePeriods implements \Countable, \IteratorAggregate
method __construct (line 20) | private function __construct(\Iterator $periods)
method fromArray (line 25) | public static function fromArray(TimePeriod ...$periods) : self
method fromIterator (line 30) | public static function fromIterator(TimePeriodsIterator $timePeriodsIt...
method all (line 38) | public function all() : array
method each (line 48) | public function each(callable $iterator) : void
method map (line 62) | public function map(callable $iterator) : array
method filter (line 76) | public function filter(callable $iterator) : self
method count (line 81) | public function count() : int
method getIterator (line 89) | public function getIterator() : \Traversable
method gaps (line 97) | public function gaps() : self
method sort (line 125) | public function sort() : self
method sortBy (line 130) | public function sortBy(TimePeriodsSort $sort) : self
method first (line 152) | public function first() : ?TimePeriod
method last (line 159) | public function last() : ?TimePeriod
method add (line 170) | public function add(TimePeriod ...$timePeriods) : self
method merge (line 175) | public function merge(self $timePeriods) : self
method isEqual (line 185) | public function isEqual(self $periods) : bool
method isEqualTo (line 190) | public function isEqualTo(self $periods) : bool
FILE: src/Aeon/Calendar/Gregorian/TimePeriodsIterator.php
class TimePeriodsIterator (line 9) | final class TimePeriodsIterator extends \FilterIterator
method __construct (line 13) | public function __construct(DateTime $start, DateTime $end, Unit $time...
method current (line 20) | public function current() : ?TimePeriod
method accept (line 42) | public function accept() : bool
method key (line 77) | public function key() : int
method getInnerIterator (line 98) | public function getInnerIterator() : DateTimeIterator
FILE: src/Aeon/Calendar/Gregorian/TimePeriodsSort.php
class TimePeriodsSort (line 10) | final class TimePeriodsSort
method __construct (line 22) | private function __construct(int $type)
method asc (line 30) | public static function asc() : self
method desc (line 38) | public static function desc() : self
method startDate (line 46) | public static function startDate(bool $ascending = true) : self
method endDate (line 54) | public static function endDate(bool $ascending = true) : self
method byStartDate (line 59) | public function byStartDate() : bool
method isAscending (line 64) | public function isAscending() : bool
FILE: src/Aeon/Calendar/Gregorian/TimeZone.php
class TimeZone (line 558) | final class TimeZone
method __construct (line 570) | private function __construct(string $name, int $type)
method UTC (line 581) | public static function UTC() : self
method id (line 591) | public static function id(string $identifier) : self
method abbreviation (line 620) | public static function abbreviation(string $abbreviation) : self
method offset (line 639) | public static function offset(string $offset) : self
method fromString (line 651) | public static function fromString(string $name) : self
method isValid (line 671) | public static function isValid(string $name) : bool
method fromDateTimeZone (line 685) | public static function fromDateTimeZone(\DateTimeZone $dateTimeZone) :...
method allIdentifiers (line 712) | public static function allIdentifiers() : array
method allAbbreviations (line 727) | public static function allAbbreviations() : array
method __callStatic (line 744) | public static function __callStatic(string $name, array $arguments) : ...
method __serialize (line 760) | public function __serialize() : array
method __unserialize (line 771) | public function __unserialize(array $data) : void
method isOffset (line 777) | public function isOffset() : bool
method isAbbreviation (line 782) | public function isAbbreviation() : bool
method isIdentifier (line 787) | public function isIdentifier() : bool
method toDateTimeZone (line 792) | public function toDateTimeZone() : \DateTimeZone
method name (line 797) | public function name() : string
method timeOffset (line 806) | public function timeOffset(DateTime $dateTime) : TimeOffset
FILE: src/Aeon/Calendar/Gregorian/TimeZone/TimeOffset.php
class TimeOffset (line 13) | final class TimeOffset
method __construct (line 23) | private function __construct(bool $negative, int $hours, int $minutes)
method UTC (line 31) | public static function UTC() : self
method fromString (line 37) | public static function fromString(string $offset) : self
method isValid (line 47) | public static function isValid(string $offset) : bool
method fromTimeUnit (line 53) | public static function fromTimeUnit(TimeUnit $timeUnit) : self
method __serialize (line 65) | public function __serialize() : array
method toString (line 74) | public function toString() : string
method toTimeUnit (line 80) | public function toTimeUnit() : TimeUnit
method toDateTimeZone (line 87) | public function toDateTimeZone() : \DateTimeZone
method isUTC (line 92) | public function isUTC() : bool
method isEqual (line 102) | public function isEqual(self $timeOffset) : bool
method isEqualTo (line 107) | public function isEqualTo(self $timeOffset) : bool
FILE: src/Aeon/Calendar/Gregorian/Year.php
class Year (line 14) | final class Year
method __construct (line 20) | public function __construct(int $year)
method fromDateTime (line 31) | public static function fromDateTime(\DateTimeInterface $dateTime) : self
method fromString (line 41) | public static function fromString(string $date) : self
method __debugInfo (line 57) | public function __debugInfo() : array
method __serialize (line 67) | public function __serialize() : array
method __unserialize (line 77) | public function __unserialize(array $data) : void
method toString (line 83) | public function toString() : string
method january (line 88) | public function january() : Month
method february (line 93) | public function february() : Month
method march (line 98) | public function march() : Month
method april (line 103) | public function april() : Month
method may (line 108) | public function may() : Month
method june (line 113) | public function june() : Month
method july (line 118) | public function july() : Month
method august (line 123) | public function august() : Month
method september (line 128) | public function september() : Month
method october (line 133) | public function october() : Month
method november (line 138) | public function november() : Month
method december (line 143) | public function december() : Month
method months (line 148) | public function months() : YearMonths
method number (line 153) | public function number() : int
method plus (line 163) | public function plus(int $years) : self
method add (line 168) | public function add(int $years) : self
method minus (line 178) | public function minus(int $years) : self
method sub (line 183) | public function sub(int $years) : self
method next (line 188) | public function next() : self
method previous (line 193) | public function previous() : self
method numberOfMonths (line 198) | public function numberOfMonths() : int
method numberOfDays (line 203) | public function numberOfDays() : int
method quarter (line 208) | public function quarter(int $number) : Quarter
method mapDays (line 232) | public function mapDays(callable $iterator) : array
method filterDays (line 253) | public function filterDays(callable $iterator) : Days
method isLeap (line 267) | public function isLeap() : bool
method toDateTimeImmutable (line 272) | public function toDateTimeImmutable() : \DateTimeImmutable
method isEqual (line 282) | public function isEqual(self $year) : bool
method isEqualTo (line 287) | public function isEqualTo(self $year) : bool
method isBefore (line 292) | public function isBefore(self $year) : bool
method isBeforeOrEqual (line 302) | public function isBeforeOrEqual(self $year) : bool
method isBeforeOrEqualTo (line 307) | public function isBeforeOrEqualTo(self $year) : bool
method isAfter (line 312) | public function isAfter(self $year) : bool
method isAfterOrEqual (line 322) | public function isAfterOrEqual(self $year) : bool
method isAfterOrEqualTo (line 327) | public function isAfterOrEqualTo(self $year) : bool
method iterate (line 332) | public function iterate(self $destination, Interval $interval) : Years
method until (line 339) | public function until(self $month, Interval $interval) : Years
method since (line 376) | public function since(self $month, Interval $interval) : Years
method distance (line 413) | public function distance(self $to) : TimeUnit
method compareTo (line 418) | public function compareTo(self $year) : int
FILE: src/Aeon/Calendar/Gregorian/YearMonths.php
class YearMonths (line 12) | final class YearMonths implements \Countable
method __construct (line 16) | public function __construct(Year $year)
method count (line 21) | public function count() : int
method byNumber (line 26) | public function byNumber(int $number) : Month
method all (line 34) | public function all() : array
method map (line 50) | public function map(callable $iterator) : array
method filter (line 65) | public function filter(callable $iterator) : array
method slice (line 73) | public function slice(int $from, int $size) : Months
FILE: src/Aeon/Calendar/Gregorian/Years.php
class Years (line 13) | final class Years implements \ArrayAccess, \Countable, \IteratorAggregate
method __construct (line 20) | public function __construct(Year ...$years)
method offsetExists (line 25) | public function offsetExists($offset) : bool
method offsetGet (line 30) | public function offsetGet($offset) : ?Year
method offsetSet (line 35) | public function offsetSet($offset, $value) : void
method offsetUnset (line 40) | public function offsetUnset($offset) : void
method all (line 48) | public function all() : array
method map (line 60) | public function map(callable $iterator) : array
method filter (line 70) | public function filter(callable $iterator) : self
method count (line 75) | public function count() : int
method getIterator (line 80) | public function getIterator() : \Traversable
FILE: src/Aeon/Calendar/RelativeTimeUnit.php
class RelativeTimeUnit (line 10) | final class RelativeTimeUnit implements Unit
method __construct (line 16) | private function __construct(?int $months = null, ?int $years = null)
method month (line 23) | public static function month() : self
method months (line 29) | public static function months(int $number) : self
method years (line 35) | public static function years(int $number) : self
method year (line 41) | public static function year() : self
method toDateInterval (line 46) | public function toDateInterval() : \DateInterval
method invert (line 58) | public function invert() : self
method inCalendarMonths (line 72) | public function inCalendarMonths() : int
method isNegative (line 81) | public function isNegative() : bool
method inYears (line 90) | public function inYears() : int
method toNegative (line 106) | public function toNegative() : self
method toPositive (line 115) | public function toPositive() : self
method inMonths (line 128) | public function inMonths() : int
FILE: src/Aeon/Calendar/Stopwatch.php
class Stopwatch (line 13) | final class Stopwatch
method __construct (line 30) | public function __construct()
method isStarted (line 37) | public function isStarted() : bool
method isStopped (line 42) | public function isStopped() : bool
method laps (line 51) | public function laps() : int
method start (line 58) | public function start() : void
method lap (line 63) | public function lap() : void
method stop (line 72) | public function stop() : void
method elapsedTime (line 85) | public function elapsedTime(int $lap) : TimeUnit
method firstLapElapsedTime (line 111) | public function firstLapElapsedTime() : TimeUnit
method lastLapElapsedTime (line 125) | public function lastLapElapsedTime() : TimeUnit
method totalElapsedTime (line 143) | public function totalElapsedTime() : TimeUnit
FILE: src/Aeon/Calendar/TimeUnit.php
class TimeUnit (line 14) | final class TimeUnit implements Unit
method __construct (line 43) | private function __construct(bool $negative, int $seconds, int $micros...
method precise (line 64) | public static function precise(float $seconds) : self
method fromDateInterval (line 90) | public static function fromDateInterval(\DateInterval $dateInterval) :...
method fromDateString (line 111) | public static function fromDateString(string $dateString) : self
method millisecond (line 120) | public static function millisecond() : self
method milliseconds (line 126) | public static function milliseconds(int $milliseconds) : self
method day (line 136) | public static function day() : self
method days (line 142) | public static function days(int $days) : self
method hour (line 148) | public static function hour() : self
method hours (line 154) | public static function hours(int $hours) : self
method minute (line 160) | public static function minute() : self
method minutes (line 166) | public static function minutes(int $minutes) : self
method second (line 172) | public static function second() : self
method seconds (line 178) | public static function seconds(int $seconds) : self
method negative (line 184) | public static function negative(int $seconds, int $microsecond) : self
method positive (line 190) | public static function positive(int $seconds, int $microsecond) : self
method __serialize (line 198) | public function __serialize() : array
method toDateInterval (line 212) | public function toDateInterval() : \DateInterval
method isZero (line 233) | public function isZero() : bool
method isNegative (line 238) | public function isNegative() : bool
method isPositive (line 246) | public function isPositive() : bool
method add (line 251) | public function add(self $timeUnit) : self
method sub (line 256) | public function sub(self $timeUnit) : self
method multiply (line 261) | public function multiply(self $multiplier) : self
method divide (line 266) | public function divide(self $divider) : self
method modulo (line 271) | public function modulo(self $divider) : self
method isGreaterThan (line 276) | public function isGreaterThan(self $timeUnit) : bool
method isGreaterThanEq (line 282) | public function isGreaterThanEq(self $timeUnit) : bool
method isGreaterThanOrEqualTo (line 287) | public function isGreaterThanOrEqualTo(self $timeUnit) : bool
method isLessThan (line 292) | public function isLessThan(self $timeUnit) : bool
method isLessThanEq (line 298) | public function isLessThanEq(self $timeUnit) : bool
method isLessThanOrEqualTo (line 303) | public function isLessThanOrEqualTo(self $timeUnit) : bool
method isEqual (line 313) | public function isEqual(self $timeUnit) : bool
method isEqualTo (line 318) | public function isEqualTo(self $timeUnit) : bool
method inSeconds (line 326) | public function inSeconds() : int
method inSecondsPrecise (line 331) | public function inSecondsPrecise() : string
method inSecondsAbs (line 341) | public function inSecondsAbs() : int
method inTimeSeconds (line 346) | public function inTimeSeconds() : int
method inHours (line 351) | public function inHours() : int
method inHoursAbs (line 358) | public function inHoursAbs() : int
method inTimeHours (line 363) | public function inTimeHours() : int
method inMinutes (line 368) | public function inMinutes() : int
method inMinutesAbs (line 375) | public function inMinutesAbs() : int
method inTimeMinutes (line 380) | public function inTimeMinutes() : int
method inDays (line 385) | public function inDays() : int
method inDaysAbs (line 392) | public function inDaysAbs() : int
method microsecond (line 404) | public function microsecond() : int
method microsecondString (line 417) | public function microsecondString() : string
method inMilliseconds (line 422) | public function inMilliseconds() : int
method inTimeMilliseconds (line 429) | public function inTimeMilliseconds() : int
method inMillisecondsAbs (line 434) | public function inMillisecondsAbs() : int
method invert (line 439) | public function invert() : self
method toNegative (line 444) | public function toNegative() : self
method toPositive (line 453) | public function toPositive() : self
method getSeconds (line 469) | private function getSeconds() : int
FILE: src/Aeon/Calendar/TimeUnit/HRTime.php
class HRTime (line 13) | final class HRTime
method convert (line 18) | public static function convert(int $seconds, int $nanosecond) : TimeUnit
FILE: src/Aeon/Calendar/Unit.php
type Unit (line 8) | interface Unit
method toDateInterval (line 10) | public function toDateInterval() : \DateInterval;
method invert (line 12) | public function invert() : self;
method isNegative (line 14) | public function isNegative() : bool;
method toNegative (line 16) | public function toNegative() : self;
method toPositive (line 18) | public function toPositive() : self;
FILE: tests/Aeon/Calculator/Tests/Unit/BCMathCalculatorTest.php
class BCMathCalculatorTest (line 12) | final class BCMathCalculatorTest extends TestCase
method add_data_provider (line 17) | public static function add_data_provider() : \Generator
method sub_provider (line 31) | public static function sub_provider() : \Generator
method multiply_provider (line 44) | public static function multiply_provider() : \Generator
method divide_provider (line 57) | public static function divide_provider() : \Generator
method modulo_provider (line 70) | public static function modulo_provider() : \Generator
method is_equal_data_provider (line 85) | public static function is_equal_data_provider() : \Generator
method is_less_data_provider (line 98) | public static function is_less_data_provider() : \Generator
method is_greater_data_provider (line 109) | public static function is_greater_data_provider() : \Generator
method is_greater_than_eq_data_provider (line 121) | public static function is_greater_than_eq_data_provider() : \Generator
method is_less_than_eq_data_provider (line 132) | public static function is_less_than_eq_data_provider() : \Generator
method test_add (line 141) | #[DataProvider('add_data_provider')]
method test_sub (line 147) | #[DataProvider('sub_provider')]
method test_multiply (line 153) | #[DataProvider('multiply_provider')]
method test_divide (line 159) | #[DataProvider('divide_provider')]
method test_modulo (line 165) | #[DataProvider('modulo_provider')]
method test_is_equal (line 171) | #[DataProvider('is_equal_data_provider')]
method test_is_less (line 177) | #[DataProvider('is_less_data_provider')]
method test_is_greater (line 183) | #[DataProvider('is_greater_data_provider')]
method test_is_greater_than_eq (line 189) | #[DataProvider('is_greater_than_eq_data_provider')]
method test_is_less_than_eq (line 195) | #[DataProvider('is_less_than_eq_data_provider')]
method test_invalid_value_in_divide (line 201) | public function test_invalid_value_in_divide() : void
method test_invalid_division_in_divide (line 207) | public function test_invalid_division_in_divide() : void
method test_invalid_value_in_modulo (line 213) | public function test_invalid_value_in_modulo() : void
method test_invalid_division_in_modulo (line 219) | public function test_invalid_division_in_modulo() : void
method test_invalid_value_in_multiply (line 225) | public function test_invalid_value_in_multiply() : void
method test_invalid_next_value_in_multiply (line 231) | public function test_invalid_next_value_in_multiply() : void
method test_invalid_value_in_add (line 237) | public function test_invalid_value_in_add() : void
method test_invalid_next_value_in_add (line 243) | public function test_invalid_next_value_in_add() : void
method test_invalid_value_in_sub (line 249) | public function test_invalid_value_in_sub() : void
method test_invalid_next_value_in_sub (line 255) | public function test_invalid_next_value_in_sub() : void
method test_invalid_value_in_is_greater_than (line 261) | public function test_invalid_value_in_is_greater_than() : void
method test_invalid_next_value_in_is_greater_than (line 267) | public function test_invalid_next_value_in_is_greater_than() : void
method test_invalid_value_in_less_than (line 273) | public function test_invalid_value_in_less_than() : void
method test_invalid_next_value_in_less_than (line 279) | public function test_invalid_next_value_in_less_than() : void
method test_invalid_value_in_is_greater_than_eq (line 285) | public function test_invalid_value_in_is_greater_than_eq() : void
method test_invalid_next_value_in_is_greater_than_eq (line 291) | public function test_invalid_next_value_in_is_greater_than_eq() : void
method test_invalid_value_in_is_less_than_eq (line 297) | public function test_invalid_value_in_is_less_than_eq() : void
method test_invalid_next_value_in_is_less_than_eq (line 303) | public function test_invalid_next_value_in_is_less_than_eq() : void
method test_invalid_value_in_is_equal (line 309) | public function test_invalid_value_in_is_equal() : void
method test_invalid_next_value_in_is_equal (line 315) | public function test_invalid_next_value_in_is_equal() : void
method test_division_by_zero (line 321) | public function test_division_by_zero() : void
method test_mod_by_zero (line 328) | public function test_mod_by_zero() : void
FILE: tests/Aeon/Calculator/Tests/Unit/PHPCalculatorTest.php
class PHPCalculatorTest (line 11) | final class PHPCalculatorTest extends TestCase
method add_data_provider (line 16) | public static function add_data_provider() : \Generator
method add_sub_provider (line 29) | public static function add_sub_provider() : \Generator
method multiply_provider (line 42) | public static function multiply_provider() : \Generator
method divide_provider (line 55) | public static function divide_provider() : \Generator
method modulo_provider (line 68) | public static function modulo_provider() : \Generator
method is_equal_data_provider (line 83) | public static function is_equal_data_provider() : \Generator
method is_less_data_provider (line 96) | public static function is_less_data_provider() : \Generator
method is_greater_data_provider (line 108) | public static function is_greater_data_provider() : \Generator
method is_greater_than_eq_data_provider (line 120) | public static function is_greater_than_eq_data_provider() : \Generator
method is_less_than_eq_data_provider (line 132) | public static function is_less_than_eq_data_provider() : \Generator
method test_precision (line 141) | public function test_precision() : void
method test_add (line 146) | #[DataProvider('add_data_provider')]
method test_sub (line 152) | #[DataProvider('add_sub_provider')]
method test_multiply (line 158) | #[DataProvider('multiply_provider')]
method test_divide (line 164) | #[DataProvider('divide_provider')]
method test_modulo (line 170) | #[DataProvider('modulo_provider')]
method test_is_equal (line 176) | #[DataProvider('is_equal_data_provider')]
method test_is_less (line 182) | #[DataProvider('is_less_data_provider')]
method test_is_greater (line 188) | #[DataProvider('is_greater_data_provider')]
method test_is_greater_than_eq (line 194) | #[DataProvider('is_greater_than_eq_data_provider')]
method test_is_less_than_eq (line 200) | #[DataProvider('is_less_than_eq_data_provider')]
FILE: tests/Aeon/Calculator/Tests/Unit/PreciseCalculatorTest.php
class PreciseCalculatorTest (line 10) | final class PreciseCalculatorTest extends TestCase
method test_initialization (line 12) | public function test_initialization() : void
FILE: tests/Aeon/Calendar/Tests/Functional/Gregorian/GregorianCalendarTest.php
class GregorianCalendarTest (line 14) | final class GregorianCalendarTest extends TestCase
method setUp (line 16) | public function setUp() : void
method test_creating_calendar_with_system_default_tz (line 21) | public function test_creating_calendar_with_system_default_tz() : void
method test_current_date (line 33) | public function test_current_date() : void
method test_timezone (line 41) | public function test_timezone() : void
method test_current_year (line 49) | public function test_current_year() : void
method test_current_month (line 57) | public function test_current_month() : void
method test_yesterday (line 65) | public function test_yesterday() : void
method test_tomorrow (line 73) | public function test_tomorrow() : void
method test_today_midnight (line 81) | public function test_today_midnight() : void
method test_today_midnight_with_custom_tz (line 89) | public function test_today_midnight_with_custom_tz() : void
method test_today_noon (line 97) | public function test_today_noon() : void
method test_today_noon_with_custom_tz (line 105) | public function test_today_noon_with_custom_tz() : void
method test_today_end_of_day (line 113) | public function test_today_end_of_day() : void
method test_today_end_of_day_with_custom_tz (line 121) | public function test_today_end_of_day_with_custom_tz() : void
method test_iterating_overt_time (line 129) | public function test_iterating_overt_time() : void
method test_iterating_overt_time_and_taking_every_second_hour (line 153) | public function test_iterating_overt_time_and_taking_every_second_hour...
method test_iterating_overt_time_backward (line 167) | public function test_iterating_overt_time_backward() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/DateTimeIntervalIteratorTest.php
class DateTimeIntervalIteratorTest (line 13) | final class DateTimeIntervalIteratorTest extends TestCase
method test_forward_even_iteration_right_open (line 15) | public function test_forward_even_iteration_right_open() : void
method test_forward_even_iteration_left_open (line 53) | public function test_forward_even_iteration_left_open() : void
method test_forward_even_iteration_open (line 77) | public function test_forward_even_iteration_open() : void
method test_forward_even_iteration_closed (line 96) | public function test_forward_even_iteration_closed() : void
method test_forward_exceeded_iteration_right_open (line 125) | public function test_forward_exceeded_iteration_right_open() : void
method test_forward_exceeded_iteration_left_open (line 141) | public function test_forward_exceeded_iteration_left_open() : void
method test_forward_exceeded_iteration_open (line 157) | public function test_forward_exceeded_iteration_open() : void
method test_forward_exceeded_iteration_closed (line 173) | public function test_forward_exceeded_iteration_closed() : void
method test_forward_odd_iteration_right_open (line 193) | public function test_forward_odd_iteration_right_open() : void
method test_forward_odd_iteration_left_open (line 212) | public function test_forward_odd_iteration_left_open() : void
method test_forward_odd_iteration_open (line 231) | public function test_forward_odd_iteration_open() : void
method test_forward_odd_iteration_closed (line 247) | public function test_forward_odd_iteration_closed() : void
method test_backward_even_iteration_right_open (line 271) | public function test_backward_even_iteration_right_open() : void
method test_backward_even_iteration_left_open (line 301) | public function test_backward_even_iteration_left_open() : void
method test_backward_even_iteration_open (line 329) | public function test_backward_even_iteration_open() : void
method test_backward_even_iteration_closed (line 353) | public function test_backward_even_iteration_closed() : void
method test_backward_exceeded_iteration_right_open (line 385) | public function test_backward_exceeded_iteration_right_open() : void
method test_backward_exceeded_iteration_left_open (line 401) | public function test_backward_exceeded_iteration_left_open() : void
method test_backward_exceeded_iteration_open (line 417) | public function test_backward_exceeded_iteration_open() : void
method test_backward_exceeded_iteration_closed (line 433) | public function test_backward_exceeded_iteration_closed() : void
method test_backward_odd_iteration_right_open (line 452) | public function test_backward_odd_iteration_right_open() : void
method test_backward_odd_iteration_left_open (line 471) | public function test_backward_odd_iteration_left_open() : void
method test_backward_odd_iteration_open (line 490) | public function test_backward_odd_iteration_open() : void
method test_backward_odd_iteration_closed (line 506) | public function test_backward_odd_iteration_closed() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/DateTimeIteratorTest.php
class DateTimeIteratorTest (line 13) | final class DateTimeIteratorTest extends TestCase
method test_forward_even_iteration (line 15) | public function test_forward_even_iteration() : void
method test_forward_exceeded_iteration (line 44) | public function test_forward_exceeded_iteration() : void
method test_forward_odd_iteration (line 62) | public function test_forward_odd_iteration() : void
method test_backward_even_iteration (line 85) | public function test_backward_even_iteration() : void
method test_backward_exceeded_iteration (line 116) | public function test_backward_exceeded_iteration() : void
method test_backward_odd_iteration (line 134) | public function test_backward_odd_iteration() : void
method test_forward_with_negative_time_unit (line 157) | public function test_forward_with_negative_time_unit() : void
method test_backward_with_positive_time_unit (line 169) | public function test_backward_with_positive_time_unit() : void
method test_empty (line 181) | public function test_empty() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/DateTimeTest.php
class DateTimeTest (line 23) | final class DateTimeTest extends TestCase
method creating_datetime_data_provider (line 28) | public static function creating_datetime_data_provider() : \Generator
method creating_datetime_data_provider_from_string (line 46) | public static function creating_datetime_data_provider_from_string() :...
method invalid_date_time_string (line 120) | public static function invalid_date_time_string() : \Generator
method modify_datetime (line 130) | public static function modify_datetime() : \Generator
method add_relative_timeunit_months (line 159) | public static function add_relative_timeunit_months() : \Generator
method sub_relative_timeunit_months (line 170) | public static function sub_relative_timeunit_months() : \Generator
method ambiguous_time_data_provider (line 181) | public static function ambiguous_time_data_provider() : \Generator
method not_ambiguous_time_data_provider (line 192) | public static function not_ambiguous_time_data_provider() : \Generator
method timezone_abbreviation_provider (line 212) | public static function timezone_abbreviation_provider() : \Generator
method compare_to_provider (line 224) | public static function compare_to_provider() : \Generator
method setUp (line 236) | public function setUp() : void
method test_creating_datetime (line 241) | #[DataProvider('creating_datetime_data_provider')]
method test_creating_datetime_from_string (line 251) | #[DataProvider('creating_datetime_data_provider_from_string')]
method test_creating_datetime_from_invalid_string (line 261) | #[DataProvider('invalid_date_time_string')]
method test_creating_datetime_from_string_relative_with_system_default_timezone_different_from_UTC (line 270) | public function test_creating_datetime_from_string_relative_with_syste...
method test_creating_datetime_from_string_relative_with_timezone_and_with_system_default_timezone_different_from_UTC (line 280) | public function test_creating_datetime_from_string_relative_with_timez...
method test_debug_info (line 290) | public function test_debug_info() : void
method test_create_with_timezone_and_without_time_offset (line 305) | public function test_create_with_timezone_and_without_time_offset() : ...
method test_create_from_string_without_offset_and_timezone (line 313) | public function test_create_from_string_without_offset_and_timezone() ...
method test_create_from_string_with_default_system_timezone (line 321) | public function test_create_from_string_with_default_system_timezone()...
method test_create_from_timestamp_with_default_system_timezone (line 332) | public function test_create_from_timestamp_with_default_system_timezon...
method test_compare_objects_create_through_different_constructors (line 344) | public function test_compare_objects_create_through_different_construc...
method test_compare_source_datetime_immutable_with_converted_one (line 363) | public function test_compare_source_datetime_immutable_with_converted_...
method test_compare_source_datetime_immutable_with_timezone_with_converted_one (line 372) | public function test_compare_source_datetime_immutable_with_timezone_w...
method test_compare_source_from_string_with_timezone_with_converted_one (line 381) | public function test_compare_source_from_string_with_timezone_with_con...
method test_create_from_string_with_timezone (line 390) | public function test_create_from_string_with_timezone() : void
method test_to_string (line 398) | public function test_to_string() : void
method test_to_iso8601_extended_format (line 404) | public function test_to_iso8601_extended_format() : void
method test_to_iso8601_basic_format (line 410) | public function test_to_iso8601_basic_format() : void
method test_create (line 416) | public function test_create() : void
method test_create_with_default_values (line 424) | public function test_create_with_default_values() : void
method test_from_timestamp (line 432) | public function test_from_timestamp() : void
method test_year (line 439) | public function test_year() : void
method test_month (line 446) | public function test_month() : void
method test_day (line 453) | public function test_day() : void
method test_midnight (line 460) | public function test_midnight() : void
method test_noon (line 467) | public function test_noon() : void
method test_end_of_day (line 474) | public function test_end_of_day() : void
method test_modify_with_non_relative_value (line 481) | public function test_modify_with_non_relative_value() : void
method test_modify (line 489) | #[DataProvider('modify_datetime')]
method test_time (line 498) | public function test_time() : void
method test_timezone_conversion (line 509) | public function test_timezone_conversion() : void
method test_daylight (line 521) | public function test_daylight() : void
method test_saving_time (line 530) | public function test_saving_time() : void
method test_unix_timestamp (line 539) | public function test_unix_timestamp() : void
method test_unix_zero_timestamp (line 546) | public function test_unix_zero_timestamp() : void
method test_timestamp (line 554) | public function test_timestamp() : void
method test_to_atomic_time (line 566) | public function test_to_atomic_time() : void
method test_to_gps_time (line 573) | public function test_to_gps_time() : void
method test_timestamp_before_epoch_start (line 580) | public function test_timestamp_before_epoch_start() : void
method test_add_hour (line 590) | public function test_add_hour() : void
method test_add_hour_during_ambiguous_time (line 597) | public function test_add_hour_during_ambiguous_time() : void
method test_sub_hour (line 607) | public function test_sub_hour() : void
method test_add_hours (line 614) | public function test_add_hours() : void
method test_sub_hours (line 621) | public function test_sub_hours() : void
method test_iterating_until_forward (line 628) | public function test_iterating_until_forward() : void
method test_iterating_until_backward (line 642) | public function test_iterating_until_backward() : void
method test_equal_dates_in_different_timezones (line 656) | public function test_equal_dates_in_different_timezones() : void
method test_add_second (line 667) | public function test_add_second() : void
method test_add_seconds (line 674) | public function test_add_seconds() : void
method test_sub_second (line 681) | public function test_sub_second() : void
method test_sub_seconds (line 688) | public function test_sub_seconds() : void
method test_add_minute (line 695) | public function test_add_minute() : void
method test_add_minutes (line 702) | public function test_add_minutes() : void
method test_sub_minute (line 709) | public function test_sub_minute() : void
method test_sub_minutes (line 716) | public function test_sub_minutes() : void
method test_add_day (line 723) | public function test_add_day() : void
method test_add_days (line 730) | public function test_add_days() : void
method test_sub_day (line 737) | public function test_sub_day() : void
method test_sub_days (line 744) | public function test_sub_days() : void
method test_add_month (line 751) | public function test_add_month() : void
method test_add_months (line 758) | public function test_add_months() : void
method test_add_2_months_to_the_last_day_of_march (line 765) | public function test_add_2_months_to_the_last_day_of_march() : void
method test_sub_month (line 772) | public function test_sub_month() : void
method test_sub_month_from_day_before_last_day_of_march (line 779) | public function test_sub_month_from_day_before_last_day_of_march() : void
method test_sub_months (line 786) | public function test_sub_months() : void
method test_add_year (line 793) | public function test_add_year() : void
method test_add_years (line 800) | public function test_add_years() : void
method test_sub_year (line 807) | public function test_sub_year() : void
method test_sub_years (line 814) | public function test_sub_years() : void
method test_add_timeunit_hour (line 821) | public function test_add_timeunit_hour() : void
method test_add_relative_timeunit_months (line 829) | #[DataProvider('add_relative_timeunit_months')]
method test_sub_relative_timeunit_months (line 838) | #[DataProvider('sub_relative_timeunit_months')]
method test_add_precse_timeunit (line 847) | public function test_add_precse_timeunit() : void
method test_sub_timeunit (line 855) | public function test_sub_timeunit() : void
method test_sub_precse_timeunit (line 863) | public function test_sub_precse_timeunit() : void
method test_is_after (line 871) | public function test_is_after() : void
method test_is_before (line 879) | public function test_is_before() : void
method test_is_after_or_equal (line 891) | public function test_is_after_or_equal() : void
method test_is_before_or_equal (line 899) | public function test_is_before_or_equal() : void
method test_until (line 907) | public function test_until() : void
method test_until_with_date_before_datetime (line 918) | public function test_until_with_date_before_datetime() : void
method test_since_with_date_after_datetime (line 928) | public function test_since_with_date_after_datetime() : void
method test_distance_until (line 938) | public function test_distance_until() : void
method test_since (line 948) | public function test_since() : void
method test_distance_since (line 959) | public function test_distance_since() : void
method test_checking_is_ambiguous (line 969) | #[DataProvider('ambiguous_time_data_provider')]
method test_checking_is_not_ambiguous (line 975) | #[DataProvider('not_ambiguous_time_data_provider')]
method test_using_create_constructor_during_dst_gap (line 981) | public function test_using_create_constructor_during_dst_gap() : void
method test_using_constructor_during_dst_gap (line 989) | public function test_using_constructor_during_dst_gap() : void
method test_timezone_when_not_explicitly_provided (line 1001) | public function test_timezone_when_not_explicitly_provided() : void
method test_time_zone_when_only_time_offset_explicitly_provided (line 1009) | public function test_time_zone_when_only_time_offset_explicitly_provid...
method test_yesterday (line 1014) | public function test_yesterday() : void
method test_yesterday_with_tz (line 1019) | public function test_yesterday_with_tz() : void
method test_tomorrow (line 1024) | public function test_tomorrow() : void
method test_tomorrow_with_tz (line 1029) | public function test_tomorrow_with_tz() : void
method test_set_time (line 1034) | public function test_set_time() : void
method test_set_time_in (line 1045) | public function test_set_time_in() : void
method test_set_day (line 1056) | public function test_set_day() : void
method test_distance_to (line 1067) | public function test_distance_to() : void
method test_quarter (line 1072) | public function test_quarter() : void
method test_serialization (line 1080) | public function test_serialization() : void
method test_timezone_abbreviation (line 1091) | #[DataProvider('timezone_abbreviation_provider')]
method test_timezone_abbreviation_from_time_offset (line 1097) | public function test_timezone_abbreviation_from_time_offset() : void
method test_from_date_time_immutable (line 1104) | public function test_from_date_time_immutable() : void
method test_from_date_time (line 1109) | public function test_from_date_time() : void
method test_equals_works (line 1114) | public function test_equals_works() : void
method test_compare_to (line 1137) | #[DataProvider('compare_to_provider')]
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/Day/WeekDayTest.php
class WeekDayTest (line 11) | final class WeekDayTest extends TestCase
method test_equals (line 13) | public function test_equals() : void
method test_create_for_week_day_less_than_0 (line 24) | public function test_create_for_week_day_less_than_0() : void
method test_create_for_week_day_greater_than_12 (line 31) | public function test_create_for_week_day_greater_than_12() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/DayTest.php
class DayTest (line 18) | final class DayTest extends TestCase
method create_day_with_invalid_number_provider (line 23) | public static function create_day_with_invalid_number_provider() : \Ge...
method creating_day_data_provider_from_string (line 33) | public static function creating_day_data_provider_from_string() : \Gen...
method invalid_string_day_format (line 60) | public static function invalid_string_day_format() : \Generator
method valid_string_day_format (line 68) | public static function valid_string_day_format() : \Generator
method compare_to_provider (line 77) | public static function compare_to_provider() : \Generator
method test_create_day_with_invalid_number (line 89) | #[DataProvider('create_day_with_invalid_number_provider')]
method test_debug_info (line 98) | public function test_debug_info() : void
method test_creating_day_from_string (line 110) | #[DataProvider('creating_day_data_provider_from_string')]
method test_to_string (line 120) | public function test_to_string() : void
method test_from_invalid_string (line 128) | #[DataProvider('invalid_string_day_format')]
method test_from_string (line 137) | #[DataProvider('valid_string_day_format')]
method test_midnight (line 143) | public function test_midnight() : void
method test_noon (line 151) | public function test_noon() : void
method test_end_of_day (line 158) | public function test_end_of_day() : void
method test_set_time (line 165) | public function test_set_time() : void
method test_next (line 175) | public function test_next() : void
method test_previous (line 182) | public function test_previous() : void
method test_week_of_year (line 189) | public function test_week_of_year() : void
method test_week_of_month (line 196) | public function test_week_of_month() : void
method test_day_of_year (line 210) | public function test_day_of_year() : void
method test_week_day (line 217) | public function test_week_day() : void
method test_format (line 224) | public function test_format() : void
method test_is_weekend (line 229) | public function test_is_weekend() : void
method test_is_equal (line 237) | public function test_is_equal() : void
method test_is_before (line 243) | public function test_is_before() : void
method test_is_after (line 255) | public function test_is_after() : void
method test_reset_time_in_to_datetime_immutable (line 265) | public function test_reset_time_in_to_datetime_immutable() : void
method test_modify_months (line 276) | public function test_modify_months() : void
method test_until_with_wrong_destination_month (line 297) | public function test_until_with_wrong_destination_month() : void
method test_since_with_wrong_destination_month (line 304) | public function test_since_with_wrong_destination_month() : void
method test_until (line 311) | public function test_until() : void
method test_since (line 320) | public function test_since() : void
method test_iterate_until (line 329) | public function test_iterate_until() : void
method test_iterate_since (line 338) | public function test_iterate_since() : void
method test_days_between (line 347) | public function test_days_between() : void
method test_day_static_create (line 356) | public function test_day_static_create() : void
method test_distance_to (line 362) | public function test_distance_to() : void
method test_quarter (line 367) | public function test_quarter() : void
method test_serialization (line 375) | public function test_serialization() : void
method test_compare_to (line 386) | #[DataProvider('compare_to_provider')]
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/DaysIteratorTest.php
class DaysIteratorTest (line 18) | final class DaysIteratorTest extends TestCase
method test_reverse_days_iterator (line 20) | public function test_reverse_days_iterator() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/DaysTest.php
class DaysTest (line 11) | final class DaysTest extends TestCase
method test_array_access (line 13) | public function test_array_access() : void
method test_map (line 27) | public function test_map() : void
method test_filter (line 43) | public function test_filter() : void
method test_foreach (line 60) | public function test_foreach() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/LeapSecondTest.php
class LeapSecondTest (line 13) | final class LeapSecondTest extends TestCase
method test_serialization (line 15) | public function test_serialization() : void
method test_is_equal (line 26) | public function test_is_equal() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/LeapSecondsTest.php
class LeapSecondsTest (line 15) | final class LeapSecondsTest extends TestCase
method test_expiration_of_current_leap_seconds_list (line 25) | public function test_expiration_of_current_leap_seconds_list() : void
method test_finding_leap_seconds_between_1970_jan_1_and_1980_jan_1 (line 43) | public function test_finding_leap_seconds_between_1970_jan_1_and_1980_...
method test_finding_leap_seconds_since_date (line 65) | public function test_finding_leap_seconds_since_date() : void
method test_creating_leap_second_with_invalid_offset (line 78) | public function test_creating_leap_second_with_invalid_offset() : void
method test_all_leap_seconds (line 89) | public function test_all_leap_seconds() : void
method test_filter_leap_seconds (line 111) | public function test_filter_leap_seconds() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/MonthDaysTest.php
class MonthDaysTest (line 12) | final class MonthDaysTest extends TestCase
method test_count (line 14) | public function test_count() : void
method test_first_day (line 22) | public function test_first_day() : void
method test_last_day (line 30) | public function test_last_day() : void
method test_map_days (line 38) | public function test_map_days() : void
method test_filter_days (line 46) | public function test_filter_days() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/MonthTest.php
class MonthTest (line 14) | final class MonthTest extends TestCase
method creating_month_data_provider_from_string (line 19) | public static function creating_month_data_provider_from_string() : \G...
method invalid_string_day_format (line 46) | public static function invalid_string_day_format() : \Generator
method valid_string_day_format (line 54) | public static function valid_string_day_format() : \Generator
method compare_to_provider (line 65) | public static function compare_to_provider() : \Generator
method test_create_with_month_number_lower_than_0 (line 77) | public function test_create_with_month_number_lower_than_0() : void
method test_create_with_month_number_greater_than_12 (line 84) | public function test_create_with_month_number_greater_than_12() : void
method test_first_day_of_month (line 91) | public function test_first_day_of_month() : void
method test_create_from_datetime (line 98) | public function test_create_from_datetime() : void
method test_creating_month_from_string (line 105) | #[DataProvider('creating_month_data_provider_from_string')]
method test_from_invalid_string (line 115) | #[DataProvider('invalid_string_day_format')]
method test_from_string (line 124) | #[DataProvider('valid_string_day_format')]
method test_debug_info (line 130) | public function test_debug_info() : void
method test_to_string (line 141) | public function test_to_string() : void
method test_last_day_of_month (line 154) | public function test_last_day_of_month() : void
method test_next_month (line 161) | public function test_next_month() : void
method test_previous_month (line 166) | public function test_previous_month() : void
method test_name (line 171) | public function test_name() : void
method test_short_name (line 176) | public function test_short_name() : void
method test_reset_time_in_to_datetime_immutable (line 181) | public function test_reset_time_in_to_datetime_immutable() : void
method test_is_equal (line 192) | public function test_is_equal() : void
method test_is_before (line 198) | public function test_is_before() : void
method test_is_after (line 210) | public function test_is_after() : void
method test_until_with_wrong_destination_month (line 219) | public function test_until_with_wrong_destination_month() : void
method test_since_with_wrong_destination_month (line 226) | public function test_since_with_wrong_destination_month() : void
method test_until (line 233) | public function test_until() : void
method test_since (line 242) | public function test_since() : void
method test_iterate_until (line 252) | public function test_iterate_until() : void
method test_iterate_since (line 261) | public function test_iterate_since() : void
method test_modify_months (line 271) | public function test_modify_months() : void
method test_day_static_create (line 305) | public function test_day_static_create() : void
method test_distance_to (line 311) | public function test_distance_to() : void
method test_quarter (line 316) | public function test_quarter() : void
method test_serialization (line 324) | public function test_serialization() : void
method test_number_of_days (line 335) | public function test_number_of_days() : void
method test_compare_to (line 353) | #[DataProvider('compare_to_provider')]
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/MonthsIteratorTest.php
class MonthsIteratorTest (line 18) | final class MonthsIteratorTest extends TestCase
method test_reverse_days_iterator (line 20) | public function test_reverse_days_iterator() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/MonthsTest.php
class MonthsTest (line 13) | final class MonthsTest extends TestCase
method test_array_access (line 15) | public function test_array_access() : void
method test_map (line 28) | public function test_map() : void
method test_filter (line 44) | public function test_filter() : void
method test_slice_below_lower_limit (line 60) | public function test_slice_below_lower_limit() : void
method test_slice_above_upper_limit (line 67) | public function test_slice_above_upper_limit() : void
method test_slice (line 74) | public function test_slice() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/Psr20ClockAdapterTest.php
class Psr20ClockAdapterTest (line 12) | final class Psr20ClockAdapterTest extends TestCase
method test_now (line 14) | public function test_now() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/QuarterTest.php
class QuarterTest (line 13) | final class QuarterTest extends TestCase
method test_number_below_range (line 15) | public function test_number_below_range() : void
method test_number_above_range (line 22) | public function test_number_above_range() : void
method test_invalid_number_of_months (line 29) | public function test_invalid_number_of_months() : void
method test_invalid_months_quarter_1 (line 36) | public function test_invalid_months_quarter_1() : void
method test_invalid_months_quarter_2 (line 43) | public function test_invalid_months_quarter_2() : void
method test_invalid_months_quarter_3 (line 50) | public function test_invalid_months_quarter_3() : void
method test_invalid_months_quarter_4 (line 57) | public function test_invalid_months_quarter_4() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/TimeEpochTest.php
class TimeEpochTest (line 12) | final class TimeEpochTest extends TestCase
method seconds_since_data_provider (line 17) | public static function seconds_since_data_provider() : \Generator
method test_distance_to_epoch (line 40) | #[DataProvider('seconds_since_data_provider')]
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/TimePeriodTest.php
class TimePeriodTest (line 16) | final class TimePeriodTest extends TestCase
method iterating_through_intervals_provider (line 18) | public static function iterating_through_intervals_provider() : \Gener...
method overlapping_time_periods_data_provider (line 44) | public static function overlapping_time_periods_data_provider() : \Gen...
method period_abuts_other_period_data_provider (line 170) | public static function period_abuts_other_period_data_provider() : \Ge...
method test_distance_in_time_unit_from_start_to_end_date (line 203) | public function test_distance_in_time_unit_from_start_to_end_date() : ...
method test_distance_in_time_unit_before_and_after_unix_epoch (line 214) | public function test_distance_in_time_unit_before_and_after_unix_epoch...
method test_distance_in_time_unit_before_and_after_unix_epoch_inverse (line 225) | public function test_distance_in_time_unit_before_and_after_unix_epoch...
method test_distance_in_time_unit_before_and_before_unix_epoch (line 236) | public function test_distance_in_time_unit_before_and_before_unix_epoc...
method test_distance_in_time_unit_before_and_before_unix_epoch_inverse (line 247) | public function test_distance_in_time_unit_before_and_before_unix_epoc...
method test_precise_distance_in_time_unit_from_start_to_end (line 258) | public function test_precise_distance_in_time_unit_from_start_to_end()...
method test_distance_in_time_unit_from_start_to_end_date_between_years (line 268) | public function test_distance_in_time_unit_from_start_to_end_date_betw...
method test_iterating_through_intervals (line 280) | #[DataProvider('iterating_through_intervals_provider')]
method test_iterating_through_day_by_hour (line 295) | public function test_iterating_through_day_by_hour() : void
method test_iterating_through_day_backward_by_hour (line 321) | public function test_iterating_through_day_backward_by_hour() : void
method test_iterating_by_2days_interval_closed_both_ways (line 347) | public function test_iterating_by_2days_interval_closed_both_ways() : ...
method test_iterating_by_day_interval_closed_both_ways (line 371) | public function test_iterating_by_day_interval_closed_both_ways() : void
method test_iterating_by_day_interval_left_open_both_ways (line 398) | public function test_iterating_by_day_interval_left_open_both_ways() :...
method test_iterating_by_day_interval_right_open_forward (line 426) | public function test_iterating_by_day_interval_right_open_forward() : ...
method test_iterating_by_day_interval_right_open_backward (line 445) | public function test_iterating_by_day_interval_right_open_backward() :...
method test_iterating_by_month_interval_closed_both_ways (line 464) | public function test_iterating_by_month_interval_closed_both_ways() : ...
method test_iterating_by_year_interval_closed_both_ways (line 518) | public function test_iterating_by_year_interval_closed_both_ways() : void
method test_iterating_through_day_backward_by_2_days (line 546) | public function test_iterating_through_day_backward_by_2_days() : void
method test_overlapping_time_periods (line 561) | #[DataProvider('overlapping_time_periods_data_provider')]
method test_period_is_forward (line 567) | public function test_period_is_forward() : void
method test_period_is_backward (line 579) | public function test_period_is_backward() : void
method test_period_abuts_other_period (line 591) | #[DataProvider('period_abuts_other_period_data_provider')]
method test_one_period_contains_the_same_period (line 597) | public function test_one_period_contains_the_same_period() : void
method test_one_period_contains_shorted_period (line 605) | public function test_one_period_contains_shorted_period() : void
method test_one_period_not_contains_other_overlapping_period (line 613) | public function test_one_period_not_contains_other_overlapping_period(...
method test_merge_not_overlapping_time_periods (line 621) | public function test_merge_not_overlapping_time_periods() : void
method test_merge_left_overlapping_time_periods (line 630) | public function test_merge_left_overlapping_time_periods() : void
method test_merge_abuts_time_periods (line 646) | public function test_merge_abuts_time_periods() : void
method test_merge_right_overlapping_time_periods (line 662) | public function test_merge_right_overlapping_time_periods() : void
method test_serialization (line 678) | public function test_serialization() : void
method test_is_equal (line 692) | public function test_is_equal() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/TimePeriodsIteratorTest.php
class TimePeriodsIteratorTest (line 13) | final class TimePeriodsIteratorTest extends TestCase
method test_forward_even_iterator_right_open (line 15) | public function test_forward_even_iterator_right_open() : void
method test_forward_even_iterator_left_open (line 32) | public function test_forward_even_iterator_left_open() : void
method test_forward_even_iterator_open (line 49) | public function test_forward_even_iterator_open() : void
method test_forward_even_iterator_closed (line 68) | public function test_forward_even_iterator_closed() : void
method test_backward_even_iterator_left_open (line 85) | public function test_backward_even_iterator_left_open() : void
method test_backward_even_iterator_right_open (line 102) | public function test_backward_even_iterator_right_open() : void
method test_backward_even_iterator_open (line 121) | public function test_backward_even_iterator_open() : void
method test_backward_even_iterator_closed (line 140) | public function test_backward_even_iterator_closed() : void
method test_forward_exceeded_iteration_closed (line 157) | public function test_forward_exceeded_iteration_closed() : void
method test_backward_exceeded_iteration_closed (line 177) | public function test_backward_exceeded_iteration_closed() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/TimePeriodsSortTest.php
class TimePeriodsSortTest (line 13) | final class TimePeriodsSortTest extends TestCase
method test_sort_by_start_date (line 15) | public function test_sort_by_start_date() : void
method test_sort_by_end_date (line 24) | public function test_sort_by_end_date() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/TimePeriodsTest.php
class TimePeriodsTest (line 15) | final class TimePeriodsTest extends TestCase
method test_each (line 17) | public function test_each() : void
method test_get_iterator (line 31) | public function test_get_iterator() : void
method test_gap_for_empty_periods (line 40) | public function test_gap_for_empty_periods() : void
method test_gap_for_periods_with_one_period (line 45) | public function test_gap_for_periods_with_one_period() : void
method test_gap_for_periods_with_equal_time_periods (line 55) | public function test_gap_for_periods_with_equal_time_periods() : void
method test_gap_periods (line 66) | public function test_gap_periods() : void
method test_compare_different_periods (line 83) | public function test_compare_different_periods() : void
method test_compare_identical_periods (line 108) | public function test_compare_identical_periods() : void
method test_no_gaps_in_overlapping_periods (line 121) | public function test_no_gaps_in_overlapping_periods() : void
method test_no_gaps_in_abuts_periods (line 134) | public function test_no_gaps_in_abuts_periods() : void
method test_map_periods (line 146) | public function test_map_periods() : void
method test_filter_periods (line 162) | public function test_filter_periods() : void
method test_sort_by_start_date_asc (line 178) | public function test_sort_by_start_date_asc() : void
method test_sort_by_start_date_desc (line 198) | public function test_sort_by_start_date_desc() : void
method test_sort_by_end_date_asc (line 218) | public function test_sort_by_end_date_asc() : void
method test_sort_by_end_date_desc (line 238) | public function test_sort_by_end_date_desc() : void
method test_first (line 258) | public function test_first() : void
method test_first_empty (line 273) | public function test_first_empty() : void
method test_last (line 280) | public function test_last() : void
method test_last_empty (line 295) | public function test_last_empty() : void
method test_add (line 302) | public function test_add() : void
method test_merge (line 324) | public function test_merge() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/TimeTest.php
class TimeTest (line 13) | final class TimeTest extends TestCase
method invalid_string_day_format (line 18) | public static function invalid_string_day_format() : \Generator
method valid_string_day_format (line 26) | public static function valid_string_day_format() : \Generator
method creating_time_data_provider_from_string (line 38) | public static function creating_time_data_provider_from_string() : \Ge...
method compare_to_provider (line 55) | public static function compare_to_provider() : \Generator
method test_debug_info (line 67) | public function test_debug_info() : void
method test_from_invalid_string (line 80) | #[DataProvider('invalid_string_day_format')]
method test_each_part_of_time (line 89) | public function test_each_part_of_time() : void
method test_from_string (line 99) | #[DataProvider('valid_string_day_format')]
method test_creating_time_from_string (line 105) | #[DataProvider('creating_time_data_provider_from_string')]
method test_time_millisecond (line 120) | public function test_time_millisecond() : void
method test_to_string (line 126) | public function test_to_string() : void
method test_format (line 132) | public function test_format() : void
method test_is_am (line 137) | public function test_is_am() : void
method test_is_pm (line 143) | public function test_is_pm() : void
method test_equal (line 149) | public function test_equal() : void
method test_greater (line 156) | public function test_greater() : void
method test_greater_or_equal (line 163) | public function test_greater_or_equal() : void
method test_less (line 170) | public function test_less() : void
method test_less_or_equal (line 177) | public function test_less_or_equal() : void
method test_to_time_unit (line 184) | public function test_to_time_unit() : void
method test_creating_using_invalid_hour (line 189) | public function test_creating_using_invalid_hour() : void
method test_creating_using_invalid_minute (line 195) | public function test_creating_using_invalid_minute() : void
method test_creating_using_invalid_second (line 201) | public function test_creating_using_invalid_second() : void
method test_creating_using_invalid_microsecond (line 207) | public function test_creating_using_invalid_microsecond() : void
method test_add (line 213) | public function test_add() : void
method test_sub (line 220) | public function test_sub() : void
method test_serialization (line 227) | public function test_serialization() : void
method test_is_midnight (line 250) | public function test_is_midnight() : void
method test_is_not_midnight (line 261) | public function test_is_not_midnight() : void
method test_compare_to (line 272) | #[DataProvider('compare_to_provider')]
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/TimeZone/TimeOffsetTest.php
class TimeOffsetTest (line 14) | final class TimeOffsetTest extends TestCase
method valid_time_offset_data_provider (line 19) | public static function valid_time_offset_data_provider() : \Generator
method invalid_time_offset_data_provider (line 41) | public static function invalid_time_offset_data_provider() : \Generator
method test_create_from_invalid_string (line 48) | public function test_create_from_invalid_string() : void
method test_create_from_time_unit_zero (line 55) | public function test_create_from_time_unit_zero() : void
method test_create_UTC (line 63) | public function test_create_UTC() : void
method test_create_from_time_unit_one_and_half_hours__positive (line 72) | public function test_create_from_time_unit_one_and_half_hours__positiv...
method test_create_from_time_unit_one_and_half_hours_negative (line 80) | public function test_create_from_time_unit_one_and_half_hours_negative...
method test_is_equal (line 88) | public function test_is_equal() : void
method test_create_from_time_unit_zero_negative (line 94) | public function test_create_from_time_unit_zero_negative() : void
method test_valid_time_offset (line 102) | #[DataProvider('valid_time_offset_data_provider')]
method test_invalid_time_offset (line 108) | #[DataProvider('invalid_time_offset_data_provider')]
method test_to_date_time_zone (line 114) | public function test_to_date_time_zone() : void
method test_serialization (line 119) | public function test_serialization() : void
method test_creat_timezone_abbreviation (line 141) | public function test_creat_timezone_abbreviation() : void
method test_creat_timezone_id (line 146) | public function test_creat_timezone_id() : void
method test_creat_timezone_offset (line 151) | public function test_creat_timezone_offset() : void
method test_creat_timezone_offset_from_date_time_zone (line 156) | public function test_creat_timezone_offset_from_date_time_zone() : void
method test_creat_timezone_id_from_date_time_zone (line 161) | public function test_creat_timezone_id_from_date_time_zone() : void
method test_creat_timezone_abbreviation_from_date_Time_zone (line 166) | public function test_creat_timezone_abbreviation_from_date_Time_zone()...
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/TimeZoneTest.php
class TimeZoneTest (line 11) | final class TimeZoneTest extends TestCase
method test_creating_from_invalid_string (line 13) | public function test_creating_from_invalid_string() : void
method test_creating_from_invalid_abbreviation (line 20) | public function test_creating_from_invalid_abbreviation() : void
method test_creating_from_invalid_identifier (line 27) | public function test_creating_from_invalid_identifier() : void
method test_creating_UTC_as_identifier (line 34) | public function test_creating_UTC_as_identifier() : void
method test_creating_from_invalid_offset (line 41) | public function test_creating_from_invalid_offset() : void
method test_creating_from_invalid_static_name (line 48) | public function test_creating_from_invalid_static_name() : void
method test_creating_from_offset (line 54) | public function test_creating_from_offset() : void
method test_creating_from_abbreviation (line 63) | public function test_creating_from_abbreviation() : void
method test_creating_from_id (line 72) | public function test_creating_from_id() : void
method test_creating_from_static_id (line 81) | public function test_creating_from_static_id() : void
method test_creating_from_static_abbreviation (line 87) | public function test_creating_from_static_abbreviation() : void
method test_calculating_offset_for_date (line 93) | public function test_calculating_offset_for_date() : void
method test_is_valid (line 103) | public function test_is_valid() : void
method test_all_timezone_identifiers (line 109) | public function test_all_timezone_identifiers() : void
method test_all_timezones (line 116) | public function test_all_timezones() : void
method test_serialization (line 123) | public function test_serialization() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/YearMonthsTest.php
class YearMonthsTest (line 11) | final class YearMonthsTest extends TestCase
method test_count (line 13) | public function test_count() : void
method test_map_months (line 19) | public function test_map_months() : void
method test_filter_months (line 27) | public function test_filter_months() : void
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/YearTest.php
class YearTest (line 14) | final class YearTest extends TestCase
method month_number_of_days_data_provider (line 19) | public static function month_number_of_days_data_provider() : \Generator
method leap_years (line 40) | public static function leap_years() : \Generator
method compare_to_provider (line 52) | public static function compare_to_provider() : \Generator
method test_months (line 61) | public function test_months() : void
method test_from_string (line 77) | public function test_from_string() : void
method test_from_string_that_is_not_valid_number (line 90) | public function test_from_string_that_is_not_valid_number() : void
method test_from_date_time_immutable (line 97) | public function test_from_date_time_immutable() : void
method test_month_number_of_days (line 102) | #[DataProvider('month_number_of_days_data_provider')]
method test_debug_info (line 108) | public function test_debug_info() : void
method test_to_string (line 118) | public function test_to_string() : void
method test_map_days (line 126) | public function test_map_days() : void
method test_filter_days (line 134) | public function test_filter_days() : void
method test_next_year (line 139) | public function test_next_year() : void
method test_previous_year (line 144) | public function test_previous_year() : void
method test_leap_years (line 149) | public function test_leap_years() : void
method test_reset_time_in_to_datetime_immutable (line 166) | public function test_reset_time_in_to_datetime_immutable() : void
method test_is_equal (line 177) | public function test_is_equal() : void
method test_is_before (line 183) | public function test_is_before() : void
method test_is_after (line 192) | public function test_is_after() : void
method test_until_with_wrong_destination_month (line 201) | public function test_until_with_wrong_destination_month() : void
method test_since_with_wrong_destination_month (line 208) | public function test_since_with_wrong_destination_month() : void
method test_modify_months (line 215) | public function test_modify_months() : void
method test_until (line 224) | public function test_until() : void
method test_since (line 233) | public function test_since() : void
method test_iterate_until (line 242) | public function test_iterate_until() : void
method test_iterate_since (line 251) | public function test_iterate_since() : void
method test_quarter_below_limit (line 260) | public function test_quarter_below_limit() : void
method test_quarter_above_limit (line 267) | public function test_quarter_above_limit() : void
method test_distance_to (line 274) | public function test_distance_to() : void
method test_quarters (line 279) | public function test_quarters() : void
method test_serialization (line 304) | public function test_serialization() : void
method test_leap_year (line 324) | #[DataProvider('leap_years')]
method test_compare_to (line 330) | #[DataProvider('compare_to_provider')]
FILE: tests/Aeon/Calendar/Tests/Unit/Gregorian/YearsTest.php
class YearsTest (line 11) | final class YearsTest extends TestCase
method test_array_access (line 13) | public function test_array_access() : void
method test_map (line 27) | public function test_map() : void
method test_filter (line 43) | public function test_filter() : void
FILE: tests/Aeon/Calendar/Tests/Unit/IntervalTest.php
class IntervalTest (line 10) | final class IntervalTest extends TestCase
method test_open (line 12) | public function test_open() : void
method test_closed (line 22) | public function test_closed() : void
method test_left_open (line 32) | public function test_left_open() : void
method test_right_open (line 42) | public function test_right_open() : void
FILE: tests/Aeon/Calendar/Tests/Unit/RelativeTimeUnitTest.php
class RelativeTimeUnitTest (line 13) | final class RelativeTimeUnitTest extends TestCase
method test_months (line 15) | public function test_months() : void
method test_invert (line 23) | public function test_invert() : void
method test_years (line 33) | public function test_years() : void
method test_in_years (line 40) | public function test_in_years() : void
method test_in_calendar_months (line 50) | public function test_in_calendar_months() : void
method test_in_months (line 57) | public function test_in_months() : void
method test_to_date_interval (line 63) | public function test_to_date_interval() : void
FILE: tests/Aeon/Calendar/Tests/Unit/StopwatchTest.php
class StopwatchTest (line 12) | final class StopwatchTest extends TestCase
method test_stopping_not_stared_stopwatch (line 14) | public function test_stopping_not_stared_stopwatch() : void
method test_elapsed_time_on_not_stopped_stopwatch (line 23) | public function test_elapsed_time_on_not_stopped_stopwatch() : void
method test_stopping_already_stopped_stopwatch (line 33) | public function test_stopping_already_stopped_stopwatch() : void
method test_taking_lap_time_of_non_started_stopwatch (line 44) | public function test_taking_lap_time_of_non_started_stopwatch() : void
method test_getting_last_lap_elapsed_time_from_not_stopped_stopwatch (line 53) | public function test_getting_last_lap_elapsed_time_from_not_stopped_st...
method test_getting_last_lap_elapsed_time_from_not_started_stopwatch (line 64) | public function test_getting_last_lap_elapsed_time_from_not_started_st...
method test_getting_first_lap_elapsed_time_from_not_stopped_stopwatch (line 73) | public function test_getting_first_lap_elapsed_time_from_not_stopped_s...
method test_getting_first_lap_elapsed_time_from_not_started_stopwatch (line 83) | public function test_getting_first_lap_elapsed_time_from_not_started_s...
method test_getting_total_elapsed_time_from_not_stopped_stopwatch (line 92) | public function test_getting_total_elapsed_time_from_not_stopped_stopw...
method test_getting_total_elapsed_time_from_not_started_stopwatch (line 102) | public function test_getting_total_elapsed_time_from_not_started_stopw...
method test_elapsed_time_from_not_stopped_stopwatch (line 111) | public function test_elapsed_time_from_not_stopped_stopwatch() : void
method test_elapsed_time_from_not_started_stopwatch (line 121) | public function test_elapsed_time_from_not_started_stopwatch() : void
method test_elapsed_time_from_not_existing_measure (line 130) | public function test_elapsed_time_from_not_existing_measure() : void
method test_laps_count_without_laps (line 143) | public function test_laps_count_without_laps() : void
method test_elapsed_time_from_not_ended_measure (line 151) | public function test_elapsed_time_from_not_ended_measure() : void
method test_getting_elapsed_time_from_two_laps (line 162) | public function test_getting_elapsed_time_from_two_laps() : void
method test_getting_total_elapsed_time_from_three_laps (line 180) | public function test_getting_total_elapsed_time_from_three_laps() : void
method test_getting_total_elapsed_time_from_one_lap_stop (line 200) | public function test_getting_total_elapsed_time_from_one_lap_stop() : ...
FILE: tests/Aeon/Calendar/Tests/Unit/TimeUnit/HRTimeTest.php
class HRTimeTest (line 12) | final class HRTimeTest extends TestCase
method converting_hr_time_to_timeunit_data_provider (line 17) | public static function converting_hr_time_to_timeunit_data_provider() ...
method test_conversion_with_nanoseconds_smaller_than_0 (line 27) | public function test_conversion_with_nanoseconds_smaller_than_0() : void
method test_converting_hr_time_to_timeunit (line 35) | #[DataProvider('converting_hr_time_to_timeunit_data_provider')]
FILE: tests/Aeon/Calendar/Tests/Unit/TimeUnitTest.php
class TimeUnitTest (line 13) | final class TimeUnitTest extends TestCase
method greater_than_data_provider (line 18) | public static function greater_than_data_provider() : \Generator
method greater_than_eq_data_provider (line 34) | public static function greater_than_eq_data_provider() : \Generator
method less_than_data_provider (line 48) | public static function less_than_data_provider() : \Generator
method less_than_eq_data_provider (line 62) | public static function less_than_eq_data_provider() : \Generator
method equal_data_provider (line 76) | public static function equal_data_provider() : \Generator
method adding_time_test_data_provider (line 90) | public static function adding_time_test_data_provider() : \Generator
method subtracting_time_test_data_provider (line 100) | public static function subtracting_time_test_data_provider() : \Generator
method adding_precise_time_test_data_provider (line 109) | public static function adding_precise_time_test_data_provider() : \Gen...
method subtracting_precise_time_test_data_provider (line 122) | public static function subtracting_precise_time_test_data_provider() :...
method creating_from_date_interval_provider (line 133) | public static function creating_from_date_interval_provider() : \Gener...
method creating_from_date_string_provider (line 153) | public static function creating_from_date_string_provider() : \Generator
method half_round_up_to_microsecond_data_provider (line 171) | public static function half_round_up_to_microsecond_data_provider() : ...
method multiplication_data_provider (line 184) | public static function multiplication_data_provider() : \Generator
method division_data_provider (line 194) | public static function division_data_provider() : \Generator
method modulo_data_provider (line 204) | public static function modulo_data_provider() : \Generator
method test_invert (line 212) | public function test_invert() : void
method test_creating_with_negative_seconds (line 219) | public function test_creating_with_negative_seconds() : void
method test_creating_with_negative_microsecond (line 227) | public function test_creating_with_negative_microsecond() : void
method test_creating_with_invalid_microsecond (line 235) | public function test_creating_with_invalid_microsecond() : void
method test_time_unit_create_from_day (line 243) | public function test_time_unit_create_from_day() : void
method test_time_unit_create_from_days (line 250) | public function test_time_unit_create_from_days() : void
method test_time_unit_create_from_days_negative (line 263) | public function test_time_unit_create_from_days_negative() : void
method test_time_unit_create_with_value_1 (line 282) | public function test_time_unit_create_with_value_1() : void
method test_time_unit_create_with_0_value (line 291) | public function test_time_unit_create_with_0_value() : void
method test_time_unit_create_from_hours (line 300) | public function test_time_unit_create_from_hours() : void
method test_time_unit_create_from_minute (line 310) | public function test_time_unit_create_from_minute() : void
method test_time_unit_create_from_0_minutes (line 317) | public function test_time_unit_create_from_0_minutes() : void
method test_time_unit_create_from_minutes (line 324) | public function test_time_unit_create_from_minutes() : void
method test_in_time_values (line 334) | public function test_in_time_values() : void
method test_complex_time_unit_in_time_values (line 347) | public function test_complex_time_unit_in_time_values() : void
method test_is_zero (line 361) | public function test_is_zero() : void
method test_second (line 367) | public function test_second() : void
method test_millisecond (line 374) | public function test_millisecond() : void
method test_milliseconds (line 382) | public function test_milliseconds() : void
method test_creating_precise_timeunit (line 391) | public function test_creating_precise_timeunit() : void
method test_creating_negative_precise_timeunit (line 400) | public function test_creating_negative_precise_timeunit() : void
method test_greater_than (line 409) | #[DataProvider('greater_than_data_provider')]
method test_greater_than_eq (line 415) | #[DataProvider('greater_than_eq_data_provider')]
method test_less_than (line 421) | #[DataProvider('less_than_data_provider')]
method test_less_than_eq (line 427) | #[DataProvider('less_than_eq_data_provider')]
method test_equal (line 433) | #[DataProvider('equal_data_provider')]
method test_adding_time_units (line 439) | #[DataProvider('adding_time_test_data_provider')]
method test_subtracting_time_units (line 445) | #[DataProvider('subtracting_time_test_data_provider')]
method test_adding_precise_time_units (line 451) | #[DataProvider('adding_precise_time_test_data_provider')]
method test_subtracting_precise_time_units (line 468) | #[DataProvider('subtracting_precise_time_test_data_provider')]
method test_creating_from_date_interval (line 485) | #[DataProvider('creating_from_date_interval_provider')]
method test_creating_from_date_string (line 491) | #[DataProvider('creating_from_date_string_provider')]
method test_creating_from_inaccurate_date_interval_years (line 497) | public function test_creating_from_inaccurate_date_interval_years() : ...
method test_creating_from_inaccurate_date_interval_months (line 505) | public function test_creating_from_inaccurate_date_interval_months() :...
method test_half_round_up_to_microsecond (line 513) | #[DataProvider('half_round_up_to_microsecond_data_provider')]
method test_multiplication (line 523) | #[DataProvider('multiplication_data_provider')]
method test_division (line 529) | #[DataProvider('division_data_provider')]
method test_modulo (line 535) | #[DataProvider('modulo_data_provider')]
method test_to_negative (line 541) | public function test_to_negative() : void
method test_to_positive (line 547) | public function test_to_positive() : void
method test_to_date_interval (line 553) | public function test_to_date_interval() : void
method test_getting_microsecond_string (line 561) | public function test_getting_microsecond_string() : void
method test_serialization (line 566) | public function test_serialization() : void
Condensed preview — 90 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (500K chars).
[
{
"path": ".gitattributes",
"chars": 417,
"preview": "*.php text eol=lf\n*.phpt text eol=lf\n/composer.lock export-ignore\n/tools/ export-ignore\n/.github/ export-ignore\n/docs ex"
},
{
"path": ".github/workflows/readonly.yaml",
"chars": 490,
"preview": "name: Readonly\n\non:\n pull_request_target:\n types: [opened]\n\njobs:\n run:\n runs-on: ubuntu-latest\n steps:\n "
},
{
"path": ".gitignore",
"chars": 18,
"preview": "vendor\n*.cache\nvar"
},
{
"path": "README.md",
"chars": 1489,
"preview": "# Aeon\n\n[](https://php.net/)\n[![Latest S"
},
{
"path": "benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeFormatBench.php",
"chars": 767,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Benchmark\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\n\n/*"
},
{
"path": "benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeInitBench.php",
"chars": 1358,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Benchmark\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nuse"
},
{
"path": "benchmark/Aeon/Calendar/Benchmark/Gregorian/DateTimeUnixTimestampBench.php",
"chars": 738,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Benchmark\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\n\n/*"
},
{
"path": "benchmark/Aeon/Calendar/Benchmark/Gregorian/DayIterationBench.php",
"chars": 1090,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Benchmark\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\GregorianCale"
},
{
"path": "benchmark/Aeon/Calendar/Benchmark/Gregorian/TimeUnitInitBench.php",
"chars": 436,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Benchmark\\Gregorian;\n\nuse Aeon\\Calendar\\TimeUnit;\n\n/**\n * @revs"
},
{
"path": "benchmark/Aeon/Calendar/Benchmark/Gregorian/TimeZoneInitBench.php",
"chars": 922,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Benchmark\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\TimeZone;\n\n/*"
},
{
"path": "composer.json",
"chars": 1012,
"preview": "{\n \"name\": \"aeon-php/calendar\",\n \"type\": \"library\",\n \"description\": \"PHP type safe, immutable calendar library\""
},
{
"path": "phpbench.json",
"chars": 246,
"preview": "{\n \"runner.bootstrap\": \"./vendor/autoload.php\",\n \"runner.path\": \"benchmark\",\n \"runner.retry_threshold\": 5,\n \"runner."
},
{
"path": "src/Aeon/Calculator/BCMathCalculator.php",
"chars": 4975,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator;\n\nuse Aeon\\Calculator\\Exception\\InvalidTypeException;\n\n/**\n *"
},
{
"path": "src/Aeon/Calculator/Calculator.php",
"chars": 1511,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator;\n\n/**\n * @psalm-immutable\n */\ninterface Calculator\n{\n publ"
},
{
"path": "src/Aeon/Calculator/Exception/Exception.php",
"chars": 110,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator\\Exception;\n\nclass Exception extends \\Exception\n{\n}\n"
},
{
"path": "src/Aeon/Calculator/Exception/InvalidTypeException.php",
"chars": 126,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator\\Exception;\n\nfinal class InvalidTypeException extends Exceptio"
},
{
"path": "src/Aeon/Calculator/PHPCalculator.php",
"chars": 3437,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator;\n\n/**\n * @psalm-immutable\n */\nfinal class PHPCalculator imple"
},
{
"path": "src/Aeon/Calculator/PreciseCalculator.php",
"chars": 774,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator;\n\nfinal class PreciseCalculator\n{\n private static ?Calcula"
},
{
"path": "src/Aeon/Calendar/Exception/Exception.php",
"chars": 108,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Exception;\n\nclass Exception extends \\Exception\n{\n}\n"
},
{
"path": "src/Aeon/Calendar/Exception/InvalidArgumentException.php",
"chars": 128,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Exception;\n\nfinal class InvalidArgumentException extends Except"
},
{
"path": "src/Aeon/Calendar/Gregorian/Calendar.php",
"chars": 420,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n */\ninterface Calendar\n{\n "
},
{
"path": "src/Aeon/Calendar/Gregorian/DateTime.php",
"chars": 18979,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\Exception;\nuse Aeon\\Cal"
},
{
"path": "src/Aeon/Calendar/Gregorian/DateTimeIntervalIterator.php",
"chars": 3468,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Unit;\n\nfinal class DateTimeInterv"
},
{
"path": "src/Aeon/Calendar/Gregorian/DateTimeIterator.php",
"chars": 2693,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/Day/WeekDay.php",
"chars": 2421,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian\\Day;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExce"
},
{
"path": "src/Aeon/Calendar/Gregorian/Day.php",
"chars": 13237,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/Days.php",
"chars": 2022,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n *\n * @implements \\Iterator"
},
{
"path": "src/Aeon/Calendar/Gregorian/DaysIterator.php",
"chars": 1001,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nfinal class DaysIterator extends \\IteratorIterator\n"
},
{
"path": "src/Aeon/Calendar/Gregorian/GregorianCalendar.php",
"chars": 1541,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n */\nfinal class GregorianCa"
},
{
"path": "src/Aeon/Calendar/Gregorian/GregorianCalendarStub.php",
"chars": 1808,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n *\n * @codeCoverageIgnore\n "
},
{
"path": "src/Aeon/Calendar/Gregorian/Interval.php",
"chars": 1440,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n */\nfinal class Interval\n{\n"
},
{
"path": "src/Aeon/Calendar/Gregorian/LeapSecond.php",
"chars": 1423,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/LeapSeconds.php",
"chars": 6065,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\TimeUnit;\n\n/**\n * @psalm-immutabl"
},
{
"path": "src/Aeon/Calendar/Gregorian/Month.php",
"chars": 11360,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/MonthDays.php",
"chars": 1556,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n */\nfinal class MonthDays i"
},
{
"path": "src/Aeon/Calendar/Gregorian/Months.php",
"chars": 2004,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n *\n * @implements \\Iterator"
},
{
"path": "src/Aeon/Calendar/Gregorian/MonthsIterator.php",
"chars": 1007,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nfinal class MonthsIterator extends \\IteratorIterato"
},
{
"path": "src/Aeon/Calendar/Gregorian/Psr20CalendarAdapter.php",
"chars": 365,
"preview": "<?php\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Psr\\Clock\\ClockInterface;\n\nfinal class Psr20Cale"
},
{
"path": "src/Aeon/Calendar/Gregorian/Quarter.php",
"chars": 2079,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/Time.php",
"chars": 8450,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/TimeEpoch.php",
"chars": 4721,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\TimeUnit;\n\n/**\n * @psalm-immutabl"
},
{
"path": "src/Aeon/Calendar/Gregorian/TimePeriod.php",
"chars": 5374,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/TimePeriods.php",
"chars": 5403,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @implements \\IteratorAggregate<TimePeriod>\n "
},
{
"path": "src/Aeon/Calendar/Gregorian/TimePeriodsIterator.php",
"chars": 2825,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Unit;\n\nfinal class TimePeriodsIte"
},
{
"path": "src/Aeon/Calendar/Gregorian/TimePeriodsSort.php",
"chars": 1329,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n */\nfinal class TimePeriods"
},
{
"path": "src/Aeon/Calendar/Gregorian/TimeZone/TimeOffset.php",
"chars": 3048,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian\\TimeZone;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumen"
},
{
"path": "src/Aeon/Calendar/Gregorian/TimeZone.php",
"chars": 27692,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/Year.php",
"chars": 10213,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/YearMonths.php",
"chars": 1861,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentExceptio"
},
{
"path": "src/Aeon/Calendar/Gregorian/Years.php",
"chars": 1831,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Gregorian;\n\n/**\n * @psalm-immutable\n *\n * @implements \\Iterator"
},
{
"path": "src/Aeon/Calendar/RelativeTimeUnit.php",
"chars": 3055,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar;\n\n/**\n * @psalm-immutable\n */\nfinal class RelativeTimeUnit impl"
},
{
"path": "src/Aeon/Calendar/Stopwatch.php",
"chars": 3741,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar;\n\nuse Aeon\\Calendar\\Exception\\Exception;\nuse Aeon\\Calendar\\Time"
},
{
"path": "src/Aeon/Calendar/TimeUnit/HRTime.php",
"chars": 648,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\TimeUnit;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgumentException"
},
{
"path": "src/Aeon/Calendar/TimeUnit.php",
"chars": 15445,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar;\n\nuse Aeon\\Calculator\\PreciseCalculator;\nuse Aeon\\Calendar\\Exce"
},
{
"path": "src/Aeon/Calendar/Unit.php",
"chars": 323,
"preview": "<?php declare(strict_types=1);\n\nnamespace Aeon\\Calendar;\n\n/**\n * @psalm-immutable\n */\ninterface Unit\n{\n public functi"
},
{
"path": "tests/Aeon/Calculator/Tests/Unit/BCMathCalculatorTest.php",
"chars": 11530,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator\\Tests\\Unit;\n\nuse Aeon\\Calculator\\BCMathCalculator;\nuse Aeon\\C"
},
{
"path": "tests/Aeon/Calculator/Tests/Unit/PHPCalculatorTest.php",
"chars": 7301,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator\\Tests\\Unit;\n\nuse Aeon\\Calculator\\PHPCalculator;\nuse PHPUnit\\F"
},
{
"path": "tests/Aeon/Calculator/Tests/Unit/PreciseCalculatorTest.php",
"chars": 578,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calculator\\Tests\\Unit;\n\nuse Aeon\\Calculator\\PreciseCalculator;\nuse PHPUn"
},
{
"path": "tests/Aeon/Calendar/Tests/Functional/Gregorian/GregorianCalendarTest.php",
"chars": 6046,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Functional\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\Gregor"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/DateTimeIntervalIteratorTest.php",
"chars": 19674,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nus"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/DateTimeIteratorTest.php",
"chars": 7132,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/DateTimeTest.php",
"chars": 44823,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\Exception;\nu"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/Day/WeekDayTest.php",
"chars": 1238,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian\\Day;\n\nuse Aeon\\Calendar\\Exception\\InvalidA"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/DayTest.php",
"chars": 17098,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/DaysIteratorTest.php",
"chars": 1028,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nus"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/DaysTest.php",
"chars": 1850,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\Day;\nuse Aeo"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/LeapSecondTest.php",
"chars": 893,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nus"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/LeapSecondsTest.php",
"chars": 3567,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/MonthDaysTest.php",
"chars": 1441,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\Day;\nuse Aeo"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/MonthTest.php",
"chars": 16534,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/MonthsIteratorTest.php",
"chars": 1054,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nus"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/MonthsTest.php",
"chars": 2344,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/Psr20ClockAdapterTest.php",
"chars": 643,
"preview": "<?php\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nuse"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/QuarterTest.php",
"chars": 2144,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/TimeEpochTest.php",
"chars": 3254,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nus"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/TimePeriodTest.php",
"chars": 35088,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/TimePeriodsIteratorTest.php",
"chars": 9001,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nus"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/TimePeriodsSortTest.php",
"chars": 999,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\TimePeriodsS"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/TimePeriodsTest.php",
"chars": 19036,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nus"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/TimeTest.php",
"chars": 10081,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/TimeZone/TimeOffsetTest.php",
"chars": 4949,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian\\TimeZone;\n\nuse Aeon\\Calendar\\Exception\\Inv"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/TimeZoneTest.php",
"chars": 4934,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\DateTime;\nus"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/YearMonthsTest.php",
"chars": 970,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\Month;\nuse A"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/YearTest.php",
"chars": 13311,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgum"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/Gregorian/YearsTest.php",
"chars": 1499,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\Gregorian;\n\nuse Aeon\\Calendar\\Gregorian\\Year;\nuse Ae"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/IntervalTest.php",
"chars": 1396,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit;\n\nuse Aeon\\Calendar\\Gregorian\\Interval;\nuse PHPUnit\\"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/RelativeTimeUnitTest.php",
"chars": 2799,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit;\n\nuse Aeon\\Calendar\\RelativeTimeUnit;\nuse PHPUnit\\Fr"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/StopwatchTest.php",
"chars": 6883,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit;\n\nuse Aeon\\Calendar\\Exception\\Exception;\nuse Aeon\\Ca"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/TimeUnit/HRTimeTest.php",
"chars": 1294,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit\\TimeUnit;\n\nuse Aeon\\Calendar\\Exception\\InvalidArgume"
},
{
"path": "tests/Aeon/Calendar/Tests/Unit/TimeUnitTest.php",
"chars": 23701,
"preview": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Aeon\\Calendar\\Tests\\Unit;\n\nuse Aeon\\Calendar\\Exception\\Exception;\nuse Aeon\\Ca"
}
]
About this extraction
This page contains the full source code of the aeon-php/calendar GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 90 files (465.9 KB), approximately 135.2k tokens, and a symbol index with 1331 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.