PHP

PHP 8.6: Třída Duration

// obsah 3
  1. 01 Jak se Duration vytváří?
  2. 02 Jak se s tím počítá?
  3. 03 A porovnávání?

PHP konečně dostává vlastní typ pro dobu trvání, třídu Time\Duration.

Ten problém zná asi každý. sleep() bere sekundy, usleep() mikrosekundy, stream_set_timeout() sekundy plus mikrosekundy zvlášť a v konfiguraci knihoven se potkáte s obojím. Samotné číslo přitom neřekne nic:

<?php

$timeout = 500; // sekund? milisekund? mikrosekund?

V novince u verze PHP 8.6 je to vidět na první pohled:

<?php

use Time\Duration;

$timeout = Duration::fromMilliseconds(500);

Jak se Duration vytváří?

Třída je final readonly a nemá veřejný konstruktor. Místo něj má pojmenované tovární metody:

<?php

use Time\Duration;

Duration::fromNanoseconds(1500);
Duration::fromMicroseconds(250);
Duration::fromMilliseconds(500);
Duration::fromSeconds(30);
Duration::fromMinutes(15);
Duration::fromHours(2);
Duration::fromIso8601DurationString('PT1H30M');

Uvnitř drží tři veřejné vlastnosti: $seconds, $nanoseconds (0 až 999 999 999) a $negative.

Jak se s tím počítá?

<?php

use Time\Duration;

$sekunda = Duration::fromSeconds(1);
$pulSekundy = $sekunda->divideBy(2);
$pulDruhySekundy = $sekunda->add($pulSekundy);

var_dump($pulDruhySekundy->seconds);     // int(1)
var_dump($pulDruhySekundy->nanoseconds); // int(500000000)

K dispozici jsou add(), sub(), multiplyBy(), divideBy(), negate() a absolute(). Všechny vrací novou instanci, objekt samotný je neměnný (immutable):

<?php

use Time\Duration;

$zpetne = Duration::fromHours(1)->negate();

var_dump($zpetne->negative);            // bool(true)
var_dump($zpetne->absolute()->seconds); // int(3600)

A porovnávání?

Třída má vlastní obsluhu porovnání, takže operátory fungují přímo:

<?php

use Time\Duration;

$timeout = Duration::fromSeconds(30);
$limit = Duration::fromMinutes(1);

var_dump($timeout < $limit); // bool(true)

Pro řazení je tu statická compare(), kterou jde rovnou předat jako first-class callable:

<?php

use Time\Duration;

$doby = [
    Duration::fromMinutes(5),
    Duration::fromMilliseconds(200),
    Duration::fromHours(1),
];

usort($doby, Duration::compare(...));

RFC prošlo v poměru 35 : 1 (a 2 se zdrželi). V samostatném hlasování se ještě rozhodovalo o pojmenování metod a vyhrály plné názvy multiplyBy a divideBy nad zkratkami.

Mně to přijde jako jedna z nejužitečnějších věcí v 8.6. Napsat si takovou třídu umí každý, jenže si ji dneska každá knihovna píše po svém a předávat mezi nimi dobu trvání je otrava.

Zdroj: https://wiki.php.net/rfc/duration_class

Michal Katuščák
Michal Katuščák

Navrhuji a vyvíjím aplikace nad Symfony a Reactem, zajímám se architekturu softwaru. Žiju v Českých Budějovicích.