Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New PSR for ClockInterface #1224

Merged
merged 58 commits into from
Mar 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
31f93b6
Create Clock PSR
cseufert Mar 4, 2021
faa28e1
Added Clock PSR Meta
cseufert Mar 4, 2021
0065811
added method to retreieve current timezone
cseufert Mar 4, 2021
d6c75b2
Updated timezone return types
cseufert Mar 4, 2021
9974dfb
Update proposed/clock-meta.md to fix typos
cseufert Mar 4, 2021
0c66162
Update proposed/clock-meta.md to fix typos
cseufert Mar 4, 2021
abb943b
Update proposed/clock-meta.md to fix typos
cseufert Mar 4, 2021
0df6d63
Update proposed/clock-meta.md to fix typos
cseufert Mar 4, 2021
072514e
Update purpose of document
cseufert Mar 4, 2021
2bc8e21
DateTime is out
cseufert Mar 4, 2021
fed0313
Update clock.md fixed typo
cseufert Mar 4, 2021
9c3d13f
Update clock.md update code formatting
cseufert Mar 4, 2021
82f07eb
Update proposed/clock-meta.md
cseufert Mar 8, 2021
c8bcefe
Update proposed/clock-meta.md
cseufert Mar 8, 2021
5415f5f
Simplify the ClockInterface
cseufert Mar 8, 2021
3386929
Include example implementations
cseufert Mar 8, 2021
4395fc3
Added names for sponsors and working group
cseufert Mar 9, 2021
d1bf6cf
Updated Working Group Members
cseufert Mar 10, 2021
506b1fc
added Luis to WG
cseufert Mar 11, 2021
380089c
Update proposed/clock.md
cseufert Mar 11, 2021
5c17173
Update proposed/clock-meta.md
cseufert Mar 11, 2021
650f6d2
Update proposed/clock-meta.md
cseufert Mar 15, 2021
05f2fba
Update proposed/clock-meta.md
cseufert Mar 16, 2021
18585b5
escape package names
cseufert Mar 18, 2021
8d3e388
clean up relevant links format
cseufert Mar 18, 2021
0ad441a
code formatted interface name
cseufert Mar 18, 2021
078ec7b
Update proposed/clock-meta.md
cseufert Mar 18, 2021
2e13cb5
Update proposed/clock-meta.md
cseufert Mar 18, 2021
a79da23
Update proposed/clock-meta.md
cseufert Mar 18, 2021
0d7157c
Update proposed/clock-meta.md
cseufert Mar 18, 2021
4f13a8e
Update proposed/clock.md
cseufert Mar 18, 2021
fa9323d
Update proposed/clock.md
cseufert Mar 18, 2021
17f364a
Update proposed/clock.md
cseufert Mar 18, 2021
8a701b2
Update proposed/clock-meta.md
cseufert Mar 18, 2021
509163c
Update proposed/clock-meta.md
cseufert Mar 18, 2021
8b34135
Update proposed/clock-meta.md
cseufert Mar 18, 2021
6bd1916
Update clock-meta.md
cseufert Mar 18, 2021
0338682
Added entrace vote link
cseufert Mar 22, 2021
2734e16
Update proposed/clock-meta.md
cseufert Mar 24, 2021
c279903
Update proposed/clock-meta.md
cseufert Mar 24, 2021
6ada868
Update proposed/clock-meta.md
cseufert Mar 24, 2021
4b53d45
Update proposed/clock-meta.md
cseufert Mar 24, 2021
92c4244
Update proposed/clock-meta.md
cseufert Mar 24, 2021
3a8c4b1
Update proposed/clock-meta.md
cseufert Mar 24, 2021
87c4002
Update proposed/clock-meta.md
cseufert Mar 24, 2021
5e05b77
Update proposed/clock-meta.md
cseufert Mar 24, 2021
9f8115b
Update proposed/clock-meta.md
cseufert Mar 24, 2021
1ced885
Update proposed/clock.md
cseufert Mar 24, 2021
12e1c1c
Update proposed/clock.md
cseufert Mar 24, 2021
2de88c5
Update proposed/clock.md
cseufert Mar 24, 2021
9401671
Re-ordered WG member list
cseufert Mar 24, 2021
3688544
Update Reference example implemtations
cseufert Mar 24, 2021
9ef42e5
Fix Order
cseufert Mar 24, 2021
8826633
Removed timezones from usage patterns
cseufert Mar 24, 2021
8e9aace
Update symfony details & added Chronos details
cseufert Mar 24, 2021
66fac09
Update proposed/clock-meta.md
cseufert Mar 24, 2021
81cb449
Update proposed/clock-meta.md
cseufert Mar 24, 2021
3caffc3
Update proposed/clock-meta.md
cseufert Mar 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions proposed/clock-meta.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Clock Meta Document

## 1. Summary

The purpose of using the `ClockInterface` is to provide a standard way to access the system
time, that would allow interopability when testing code that relies on the current time
rather than relying on installing PHP extensions or use hacks like re-declaring the `time()`
function in other namespaces.

## 2. Why Bother?

There are currently a few libraries that provide this functionality, however
there is no interopability between these different libraries, as they ship with their own
clock interfaces. Symfony provides a package called `symfony/phpunit-bridge` that has a
`Symfony\Bridge\PhpUnit\ClockMock` class, which allows mocking PHP's built-in time & date
functions, however this does not solve mocking calls to `new \DateTimeImmutable()`. It does
not fully mock time when called from other libraries that rely on the system time.
`Cake\Chronos\Chronos` does provide mocking, however it is set via a global (static class
property), and this has its own pitfalls as it provides no isolation.

Pros:

* Consistent interface to get the current time;
* Easy to mock the wall clock time for repeatablility.

Cons:

* Extra overhead and developer effort to get the current time, not as simple as
calling `time()` or `date()`.

## 3. Scope

### 3.1 Goals

* Provide a simple and mockable way to read the current time;
* Allow interoperability between libraries when reading the clock.
Comment on lines +35 to +36
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, do we need a trailing ; or . here? If so, perhaps consistently use one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, perhaps @ashnazg can weight in on this?


### 3.2 Non-Goals

* This PSR does not provide a recommendation on how and when to use the concepts
described in this document, so it is not a coding standard;
* This PSR does not provide a recommendation on how to handle timezones when
retrieving the current time. This is left up to the implementation.

## 4. Approaches

### 4.1 Chosen Approach

We have decided to formalize the existing practices, used by several other packages
out in the wild. Some of the popular packages providing this functionality are:
`lcobucci/clock`, `kreait/clock`, `ergebnis/clock`, and `mangoweb/clock`. Some providing
interfaces, and some relying on overloading (extending) the Clock class to mock the
current time.
cseufert marked this conversation as resolved.
Show resolved Hide resolved


### 4.2 Example Implementations

```php
final class SystemClock implements \Psr\Clock\ClockInterface
{
public function now(): \DateTimeImmutable
{
return new \DateTimeImmutable();
}
}

//

final class UTCClock implements \Psr\Clock\ClockInterface
{
private \DateTimeZone $utcTimeZone;
cseufert marked this conversation as resolved.
Show resolved Hide resolved

public function __construct()
{
$this->utcTimeZone = new \DateTimeZone('UTC');
}

public function now(): \DateTimeImmutable
{
return new \DateTimeImmutable('now', $this->utcTimeZone);
}
}

//

final class FrozenClock implements \Psr\Clock\ClockInterface
{
private \DateTimeImmutable $now;

public function __construct(\DateTimeImmutable $now)
{
$this->now = $now;
}

public function now(): \DateTimeImmutable
{
return clone $this->now;
}

public function advance(DateInterval $interval): void
{
$this->now = $this->now->add($interval);
}
}

```

## 5. People

### 5.1 Editor

* Chris Seufert

### 5.2 Sponsor

* Chuck Burgess

### 5.3 Working group members

* Luís Cobucci
* Pol Dellaiera
* Ben Edmunds
* Jérôme Gamez
* Andreas Heigl
* Andreas Möller

## 6. Votes

* [Entrance Vote](https://groups.google.com/g/php-fig/c/hIKqd0an-GI)

## 7. Relevant Links

* https://github.com/ergebnis/clock/blob/main/src/Clock.php
* https://github.com/icecave/chrono/blob/master/src/Clock/ClockInterface.php
* https://github.com/Kdyby/DateTimeProvider/blob/master/src/DateTimeProviderInterface.php
* https://github.com/kreait/clock-php/blob/main/src/Clock.php
* https://github.com/lcobucci/clock/blob/2.1.x/src/Clock.php
* https://github.com/mangoweb-backend/clock/blob/master/src/Clock.php
* https://martinfowler.com/bliki/ClockWrapper.html

## 8. Past contributors

This document stems from the work of many people in previous years, we recognize their effort:

*
_**Note:** Order descending chronologically._
64 changes: 64 additions & 0 deletions proposed/clock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
Common Interface for Accessing the Clock
========================================

This document describes a simple interface for reading the system clock.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
interpreted as described in [RFC 2119][].

The final implementations MAY decorate the objects with more
functionality than the one proposed but they MUST implement the indicated
interfaces/functionality first.

[RFC 2119]: http://tools.ietf.org/html/rfc2119

# 1. Specification

## 1.1 Introduction

Creating a standard way of accessing the clock, would allow interopability
during testing, when testing behavior that has timing based side affects.
Common ways to get the current time include calling `\time()` or
`new DateTimeImmutable('now')`. However, this makes mocking the current time
impossible in some situations.

## 1.2 Definitions

* **Clock** - The clock is able to read the current time and date.

* **Timestamp** - The current time as an integer number of seconds since
Jan 1, 1970 00:00:00 UTC.

### 1.3 Usage

There are some common usage patterns, which are outlined below:

**Get the current timestamp**

This should be done by using the `getTimestamp()` method on the returned `\DateTimeImmutable` like so:
```php
$timestamp = $clock->now()->getTimestamp();
```

# 2. Interfaces

## 2.1 ClockInterface

The clock interface defines the most basic operations to read the current time and date from the clock.
It MUST return the time as a `DateTimeImmutable`.

~~~php
<?php

namespace Psr\Clock;

interface ClockInterface
cseufert marked this conversation as resolved.
Show resolved Hide resolved
{
/**
* Returns the current time as a DateTimeImmutable Object
*/
public function now(): \DateTimeImmutable;
cseufert marked this conversation as resolved.
Show resolved Hide resolved

}
~~~