From 1d17436aaf42518eaf77a84069584916fffaf092 Mon Sep 17 00:00:00 2001 From: Dorian Villet Date: Fri, 29 Sep 2023 14:10:33 +0200 Subject: [PATCH] Improve performances for LocalDate, LocalTime and Duration __toString(). --- src/Duration.php | 4 ++-- src/LocalDate.php | 14 ++++++++++---- src/LocalTime.php | 20 +++++++++----------- tests/LocalDateTest.php | 16 +++++++++++++++- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/Duration.php b/src/Duration.php index 9a2d03a..3dfaec3 100644 --- a/src/Duration.php +++ b/src/Duration.php @@ -13,9 +13,9 @@ use function is_int; use function preg_match; use function rtrim; -use function sprintf; use function str_pad; +use const STR_PAD_LEFT; use const STR_PAD_RIGHT; /** @@ -808,7 +808,7 @@ public function __toString(): string $string .= (($seconds === 0 && $negative) ? '-0' : $seconds); if ($nanos !== 0) { - $string .= '.' . rtrim(sprintf('%09d', $nanos), '0'); + $string .= '.' . rtrim(str_pad((string) $nanos, 9, '0', STR_PAD_LEFT), '0'); } return $string . 'S'; diff --git a/src/LocalDate.php b/src/LocalDate.php index f0939c1..414ad68 100644 --- a/src/LocalDate.php +++ b/src/LocalDate.php @@ -14,9 +14,12 @@ use DateTimeInterface; use JsonSerializable; +use function abs; use function intdiv; use function min; -use function sprintf; +use function str_pad; + +use const STR_PAD_LEFT; /** * A date without a time-zone in the ISO-8601 calendar system, such as `2007-12-03`. @@ -759,9 +762,12 @@ public function jsonSerialize(): string */ public function __toString(): string { - $pattern = ($this->year < 0 ? '%05d' : '%04d') . '-%02d-%02d'; - - return sprintf($pattern, $this->year, $this->month, $this->day); + // This code is optimized for high performance + return ($this->year < 1000 ? ($this->year < 0 ? '-' : '') . str_pad((string) abs($this->year), 4, '0', STR_PAD_LEFT) : $this->year) + . '-' + . ($this->month < 10 ? '0' . $this->month : $this->month) + . '-' + . ($this->day < 10 ? '0' . $this->day : $this->day); } /** diff --git a/src/LocalTime.php b/src/LocalTime.php index d1376d4..6544ee1 100644 --- a/src/LocalTime.php +++ b/src/LocalTime.php @@ -19,9 +19,10 @@ use function intdiv; use function rtrim; -use function sprintf; use function str_pad; +use const STR_PAD_LEFT; + /** * A time without a time-zone in the ISO-8601 calendar system, such as 10:15:30. * @@ -662,16 +663,13 @@ public function jsonSerialize(): string */ public function __toString(): string { - if ($this->nano === 0) { - if ($this->second === 0) { - return sprintf('%02u:%02u', $this->hour, $this->minute); - } else { - return sprintf('%02u:%02u:%02u', $this->hour, $this->minute, $this->second); - } - } - - $nanos = rtrim(sprintf('%09u', $this->nano), '0'); + $hasNanos = $this->nano !== 0; - return sprintf('%02u:%02u:%02u.%s', $this->hour, $this->minute, $this->second, $nanos); + // This code is optimized for high performance + return ($this->hour < 10 ? '0' . $this->hour : $this->hour) + . ':' + . ($this->minute < 10 ? '0' . $this->minute : $this->minute) + . ($hasNanos || $this->second !== 0 ? ':' . str_pad((string) $this->second, 2, '0', STR_PAD_LEFT) : '') + . ($hasNanos ? '.' . rtrim(str_pad((string) $this->nano, 9, '0', STR_PAD_LEFT), '0') : ''); } } diff --git a/tests/LocalDateTest.php b/tests/LocalDateTest.php index f46db60..9794386 100644 --- a/tests/LocalDateTest.php +++ b/tests/LocalDateTest.php @@ -1389,8 +1389,22 @@ public function testToString(int $year, int $month, int $day, string $expected): public function providerToString(): array { return [ - [999, 1, 2, '0999-01-02'], + [-999999, 12, 31, '-999999-12-31'], + [-185321, 11, 2, '-185321-11-02'], + [-18532, 11, 2, '-18532-11-02'], + [-2023, 11, 28, '-2023-11-28'], + [-2023, 11, 2, '-2023-11-02'], + [-2023, 1, 2, '-2023-01-02'], + [-999, 1, 2, '-0999-01-02'], [-2, 1, 1, '-0002-01-01'], + [2, 1, 1, '0002-01-01'], + [999, 1, 2, '0999-01-02'], + [2023, 1, 2, '2023-01-02'], + [2023, 11, 2, '2023-11-02'], + [2023, 11, 28, '2023-11-28'], + [18532, 11, 2, '18532-11-02'], + [185321, 11, 2, '185321-11-02'], + [999999, 12, 31, '999999-12-31'], ]; }