Skip to content

Commit

Permalink
Improve performances for LocalDate, LocalTime and Duration __toString().
Browse files Browse the repository at this point in the history
  • Loading branch information
gnutix committed Oct 2, 2023
1 parent 9bafac4 commit b79d7e1
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 18 deletions.
4 changes: 2 additions & 2 deletions src/Duration.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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';
Expand Down
14 changes: 10 additions & 4 deletions src/LocalDate.php
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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);
}

/**
Expand Down
20 changes: 9 additions & 11 deletions src/LocalTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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') : '');
}
}
16 changes: 15 additions & 1 deletion tests/LocalDateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'],
];
}

Expand Down

0 comments on commit b79d7e1

Please sign in to comment.