fix: carry the sign on the interval instead of on each unit
This commit is contained in:
1 parent
23696d9b4c
commit
a449056f05
2 files changed
+21
-14
No files matched your search
+6
-7
@@ -188,14 +188,13 @@ final class Duration
|
|||||||
{
|
{
|
||||||
$units += ['hour' => '0', 'minute' => '0', 'second' => '0', 'fraction' => '0', 'sign' => '+'];
|
$units += ['hour' => '0', 'minute' => '0', 'second' => '0', 'fraction' => '0', 'sign' => '+'];
|
||||||
$units['fraction'] = str_pad($units['fraction'] ?? '000000', 6, '0');
|
$units['fraction'] = str_pad($units['fraction'] ?? '000000', 6, '0');
|
||||||
$sign = '-' === $units['sign'] ? '-' : '';
|
|
||||||
|
|
||||||
return self::fromDateString(
|
$instance = self::fromDateString($units['hour'].' hours '.$units['minute'].' minutes '.$units['second'].' seconds '.$units['fraction'].' microseconds');
|
||||||
$sign.$units['hour'].' hours '
|
if ('-' === $units['sign']) {
|
||||||
.$sign.$units['minute'].' minutes '
|
$instance->dateInterval->invert = 1;
|
||||||
.$sign.$units['second'].' seconds '
|
}
|
||||||
.$sign.$units['fraction'].' microseconds'
|
|
||||||
);
|
return $instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+15
-7
@@ -24,6 +24,7 @@ namespace League\Period;
|
|||||||
|
|
||||||
use DateInterval;
|
use DateInterval;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
use DateTimeImmutable;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
@@ -49,7 +50,8 @@ final class DurationTest extends TestCase
|
|||||||
{
|
{
|
||||||
$interval = $duration->dateInterval;
|
$interval = $duration->dateInterval;
|
||||||
|
|
||||||
$date = ['P'];
|
// the sign belongs to the whole duration: -PT12M28S, not PT-12M-28S
|
||||||
|
$date = [1 === $interval->invert ? '-P' : 'P'];
|
||||||
if (0 !== $interval->y) {
|
if (0 !== $interval->y) {
|
||||||
$date[] = '%yY';
|
$date[] = '%yY';
|
||||||
}
|
}
|
||||||
@@ -242,7 +244,7 @@ final class DurationTest extends TestCase
|
|||||||
],
|
],
|
||||||
'negative chrono' => [
|
'negative chrono' => [
|
||||||
'chronometer' => '-12:28',
|
'chronometer' => '-12:28',
|
||||||
'expected' => 'PT-12M-28S',
|
'expected' => '-PT12M28S',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -282,11 +284,11 @@ final class DurationTest extends TestCase
|
|||||||
],
|
],
|
||||||
'negative chrono' => [
|
'negative chrono' => [
|
||||||
'chronometer' => '-12:28',
|
'chronometer' => '-12:28',
|
||||||
'expected' => 'PT-12H-28M',
|
'expected' => '-PT12H28M',
|
||||||
],
|
],
|
||||||
'negative chrono with seconds' => [
|
'negative chrono with seconds' => [
|
||||||
'chronometer' => '-01:02:28',
|
'chronometer' => '-01:02:28',
|
||||||
'expected' => 'PT-1H-2M-28S',
|
'expected' => '-PT1H2M28S',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -295,11 +297,17 @@ final class DurationTest extends TestCase
|
|||||||
* A sign applies to the whole duration, not just the hour. It used to be
|
* A sign applies to the whole duration, not just the hour. It used to be
|
||||||
* lost when the hour was zero, and to negate only the hour otherwise.
|
* lost when the hour was zero, and to negate only the hour otherwise.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* @param 'fromChronoString'|'fromTimeString' $method
|
||||||
|
*/
|
||||||
#[DataProvider('signedDurationProvider')]
|
#[DataProvider('signedDurationProvider')]
|
||||||
public function testSignedStringsApplySignToWholeDuration(string $method, string $input, string $reference, string $expected): void
|
public function testSignedStringsApplySignToWholeDuration(string $method, string $input, string $reference, string $expected): void
|
||||||
{
|
{
|
||||||
$duration = Duration::$method($input);
|
$duration = match ($method) {
|
||||||
$date = new \DateTimeImmutable($reference);
|
'fromChronoString' => Duration::fromChronoString($input),
|
||||||
|
'fromTimeString' => Duration::fromTimeString($input),
|
||||||
|
};
|
||||||
|
$date = new DateTimeImmutable($reference);
|
||||||
|
|
||||||
self::assertSame(
|
self::assertSame(
|
||||||
$expected,
|
$expected,
|
||||||
@@ -308,7 +316,7 @@ final class DurationTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return iterable<string, array{method:string, input:string, reference:string, expected:string}>
|
* @return iterable<string, array{method:'fromChronoString'|'fromTimeString', input:string, reference:string, expected:string}>
|
||||||
*/
|
*/
|
||||||
public static function signedDurationProvider(): iterable
|
public static function signedDurationProvider(): iterable
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user