brick / date-time

Date and time library for PHP
MIT License
336 stars 30 forks source link
date-time php timezone

Brick\DateTime

A powerful set of immutable classes to work with dates and times.

Build Status Coverage Status Latest Stable Version Total Downloads License

Introduction

This library builds an extensive API on top of the native PHP date-time classes, and adds missing concepts such as LocalDate, LocalTime, YearMonth, MonthDay, etc.

The classes follow the ISO 8601 standard for representing date and time concepts.

This component follows an important part of the JSR 310 (Date and Time API) specification from Java. Don't expect an exact match of class and method names though, as a number of differences exist for technical or practical reasons.

All the classes are immutable, they can be safely passed around without being affected.

Installation

This library is installable via Composer:

composer require brick/date-time

Requirements

This library requires PHP 8.1 or later.

Project status & release process

While this library is still under development, it is well tested and should be stable enough to use in production environments.

The current releases are numbered 0.x.y. When a non-breaking change is introduced (adding new methods, optimizing existing code, etc.), y is incremented.

When a breaking change is introduced, a new 0.x version cycle is always started.

It is therefore safe to lock your project to a given release cycle, such as 0.7.*.

If you need to upgrade to a newer release cycle, check the release history for a list of changes introduced by each further 0.x.0 version.

Overview

Main classes

The following classes/enums represent the date-time concepts:

These classes belong to the Brick\DateTime namespace.

Clocks

All objects read the current time from a Clock implementation. The following implementations are available:

These classes belong to the Brick\DateTime\Clock namespace.

In your application, you will most likely never touch the defaults, and always use the default clock:

use Brick\DateTime\LocalDate;
use Brick\DateTime\TimeZone;

echo LocalDate::now(TimeZone::utc()); // 2017-10-04

In your tests however, you might need to set the current time to test your application in known conditions. To do this, you can either explicitly pass a Clock instance to now() methods:

use Brick\DateTime\Clock\FixedClock;
use Brick\DateTime\Instant;
use Brick\DateTime\LocalDate;
use Brick\DateTime\TimeZone;

$clock = new FixedClock(Instant::of(1000000000));
echo LocalDate::now(TimeZone::utc(), $clock); // 2001-09-09

Or you can change the default clock for all date-time classes. All methods such as now(), unless provided with an explicit Clock, will use the default clock you provide:

use Brick\DateTime\Clock\FixedClock;
use Brick\DateTime\DefaultClock;
use Brick\DateTime\Instant;
use Brick\DateTime\LocalDate;
use Brick\DateTime\TimeZone;

DefaultClock::set(new FixedClock(Instant::of(1000000000)));
echo LocalDate::now(TimeZone::utc()); // 2001-09-09

DefaultClock::reset(); // do not forget to reset the clock to the system clock!

There are also useful shortcut methods to use clocks in your tests, inspired by timecop:

Freeze the time to a specific point

use Brick\DateTime\DefaultClock;
use Brick\DateTime\Instant;

DefaultClock::freeze(Instant::of(2000000000));

$a = Instant::now(); sleep(1);
$b = Instant::now();

echo $a, PHP_EOL; // 2033-05-18T03:33:20Z
echo $b, PHP_EOL; // 2033-05-18T03:33:20Z

DefaultClock::reset();

Travel to a specific point in time

use Brick\DateTime\DefaultClock;
use Brick\DateTime\Instant;

DefaultClock::travelTo(Instant::of(2000000000));
$a = Instant::now(); sleep(1);
$b = Instant::now();

echo $a, PHP_EOL; // 2033-05-18T03:33:20.000342Z
echo $b, PHP_EOL; // 2033-05-18T03:33:21.000606Z

DefaultClock::reset();

Make time move at a given pace

use Brick\DateTime\DefaultClock;
use Brick\DateTime\Instant;

DefaultClock::travelTo(Instant::of(2000000000));
DefaultClock::scale(60); // 1 second becomes 60 seconds

$a = Instant::now(); sleep(1);
$b = Instant::now();

echo $a, PHP_EOL; // 2033-05-18T03:33:20.00188Z
echo $b, PHP_EOL; // 2033-05-18T03:34:20.06632Z

DefaultClock::reset();

As you can see, you can even combine travelTo() and scale() methods.

Be very careful to reset() the DefaultClock after each of your tests! If you're using PHPUnit, a good place to do this is in the tearDown() method.

Exceptions

The following exceptions can be thrown:

Doctrine mappings

You can use brick/date-time types in your Doctrine entities using the brick/date-time-doctrine package.

Contributing

Before submitting a pull request, you can check the code using the following tools. Your CI build will fail if any of the following tools reports any issue.

First of all, install dependencies:

composer install

Unit tests

Run PHPUnit tests:

vendor/bin/phpunit

Static analysis

Install Psalm in its own folder:

composer install --working-dir=tools/psalm

Run Psalm static analysis:

tools/psalm/vendor/bin/psalm --no-cache --config=tools/psalm/psalm.xml

Coding Style

Install Easy Coding Standard in its own folder:

composer install --working-dir=tools/ecs

Run coding style analysis checks:

tools/ecs/vendor/bin/ecs check --config tools/ecs/ecs.php

Or fix issues found directly:

tools/ecs/vendor/bin/ecs check --config tools/ecs/ecs.php --fix

Rector automated refactoring

Install Rector in its own folder:

composer install --working-dir=tools/rector

Run automated refactoring:

tools/rector/vendor/bin/rector --config tools/rector/rector.php