Skip to content

Commit

Permalink
Merge pull request #85 from gnutix/improve-performances-tostring-methods
Browse files Browse the repository at this point in the history
Improve performances for __toString() methods.
  • Loading branch information
BenMorel authored Oct 16, 2023
2 parents 7d9ced3 + 8424509 commit 00b2e4f
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 32 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 toISOString(): 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
20 changes: 16 additions & 4 deletions src/LocalDate.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

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 +761,19 @@ public function jsonSerialize(): string
*/
public function toISOString(): 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 > -1000
? (
$this->year < 0
? '-' . str_pad((string) -$this->year, 4, '0', STR_PAD_LEFT)
: str_pad((string) $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: 8 additions & 12 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,17 +663,12 @@ public function jsonSerialize(): string
*/
public function toISOString(): 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');

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)
. ($this->second !== 0 || $this->nano !== 0 ? ':' . ($this->second < 10 ? '0' . $this->second : $this->second) : '')
. ($this->nano !== 0 ? '.' . rtrim(str_pad((string) $this->nano, 9, '0', STR_PAD_LEFT), '0') : '');
}

/**
Expand Down
8 changes: 5 additions & 3 deletions src/MonthDay.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
use Brick\DateTime\Parser\IsoParsers;
use JsonSerializable;

use function sprintf;

/**
* A month-day in the ISO-8601 calendar system, such as `--12-03`.
*/
Expand Down Expand Up @@ -238,7 +236,11 @@ public function jsonSerialize(): string
*/
public function toISOString(): string
{
return sprintf('--%02d-%02d', $this->month, $this->day);
// This code is optimized for high performance
return '--'
. ($this->month < 10 ? '0' . $this->month : $this->month)
. '-'
. ($this->day < 10 ? '0' . $this->day : $this->day);
}

/**
Expand Down
18 changes: 14 additions & 4 deletions src/YearMonth.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
use Brick\DateTime\Utility\Math;
use JsonSerializable;

use function sprintf;
use function str_pad;

use const STR_PAD_LEFT;

/**
* Represents the combination of a year and a month.
Expand Down Expand Up @@ -300,9 +302,17 @@ public function jsonSerialize(): string
*/
public function toISOString(): string
{
$pattern = ($this->year < 0 ? '%05d' : '%04d') . '-%02d';

return sprintf($pattern, $this->year, $this->month);
// This code is optimized for high performance
return ($this->year < 1000 && $this->year > -1000
? (
$this->year < 0
? '-' . str_pad((string) -$this->year, 4, '0', STR_PAD_LEFT)
: str_pad((string) $this->year, 4, '0', STR_PAD_LEFT)
)
: $this->year
)
. '-'
. ($this->month < 10 ? '0' . $this->month : $this->month);
}

/**
Expand Down
18 changes: 14 additions & 4 deletions src/YearWeek.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
use Brick\DateTime\Parser\IsoParsers;
use JsonSerializable;

use function sprintf;
use function str_pad;

use const STR_PAD_LEFT;

/**
* Represents the combination of a year and a week.
Expand Down Expand Up @@ -308,9 +310,17 @@ public function jsonSerialize(): string
*/
public function toISOString(): string
{
$pattern = ($this->year < 0 ? '%05d' : '%04d') . '-W%02d';

return sprintf($pattern, $this->year, $this->week);
// This code is optimized for high performance
return ($this->year < 1000 && $this->year > -1000
? (
$this->year < 0
? '-' . str_pad((string) -$this->year, 4, '0', STR_PAD_LEFT)
: str_pad((string) $this->year, 4, '0', STR_PAD_LEFT)
)
: $this->year
)
. '-W'
. ($this->week < 10 ? '0' . $this->week : $this->week);
}

/**
Expand Down
16 changes: 15 additions & 1 deletion tests/LocalDateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1402,8 +1402,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
4 changes: 4 additions & 0 deletions tests/LocalTimeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,10 @@ public function testToString(int $h, int $m, int $s, int $n, string $r): void
public function providerToString(): array
{
return [
[0, 0, 0, 0, '00:00'],
[0, 1, 0, 0, '00:01'],
[0, 0, 1, 0, '00:00:01'],
[0, 0, 0, 1, '00:00:00.000000001'],
[1, 2, 0, 0, '01:02'],
[1, 2, 3, 0, '01:02:03'],
[1, 2, 3, 4, '01:02:03.000000004'],
Expand Down
4 changes: 2 additions & 2 deletions tests/YearMonthTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -462,9 +462,9 @@ public function providerToLocalDateRange(): array
/**
* @dataProvider providerToString
*/
public function testJsonSerialize(int $year, int $week, string $expectedString): void
public function testJsonSerialize(int $year, int $month, string $expectedString): void
{
self::assertSame(json_encode($expectedString), json_encode(YearMonth::of($year, $week)));
self::assertSame(json_encode($expectedString), json_encode(YearMonth::of($year, $month)));
}

/**
Expand Down

0 comments on commit 00b2e4f

Please sign in to comment.