Skip to content

Commit

Permalink
Improve milliseconds/microseconds support (#1486)
Browse files Browse the repository at this point in the history
Fix #1481 total milliseconds/microseconds in intervals
Fix #1482 microseconds in intervals add, instance and create
  • Loading branch information
kylekatarnls authored Oct 26, 2018
1 parent b9c255b commit 790f2bc
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 14 deletions.
30 changes: 21 additions & 9 deletions src/Carbon/CarbonInterval.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ public function __construct($years = 1, $months = null, $weeks = null, $days = n
parent::__construct($spec);

if (!is_null($microseconds)) {
$this->f = $microseconds;
$this->f = $microseconds / 1000000;
}
}

Expand Down Expand Up @@ -339,12 +339,13 @@ public static function getMicrosecondsPerMillisecond()
* @param int $hours
* @param int $minutes
* @param int $seconds
* @param int $microseconds
*
* @return static
*/
public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null)
public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
{
return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds);
return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
}

/**
Expand Down Expand Up @@ -571,7 +572,11 @@ public static function fromString($intervalDefinition)
*/
public static function instance(DateInterval $di)
{
$microseconds = $di->f;
$instance = new static(static::getDateIntervalSpec($di));
if ($microseconds) {
$instance->f = $microseconds;
}
$instance->invert = $di->invert;
foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
if ($di->$unit < 0) {
Expand Down Expand Up @@ -677,11 +682,11 @@ public function __get($name)

case 'milli':
case 'milliseconds':
return (int) floor($this->f / 1000);
return (int) floor(round($this->f * 1000000) / 1000);

case 'micro':
case 'microseconds':
return (int) $this->f;
return (int) round($this->f * 1000000);

case 'weeks':
return (int) floor($this->d / static::getDaysPerWeek());
Expand Down Expand Up @@ -739,12 +744,12 @@ public function __set($name, $value)

case 'milli':
case 'millisecond':
$this->f = $value * 1000 + $this->f % 1000;
$this->microseconds = $value * 1000 + $this->microseconds % 1000;
break;

case 'micro':
case 'microsecond':
$this->f = $value;
$this->f = $value / 1000000;
break;

default:
Expand Down Expand Up @@ -1128,6 +1133,7 @@ public function add($unit, $value = 1)
$this->hours += $interval->h * $sign;
$this->minutes += $interval->i * $sign;
$this->seconds += $interval->s * $sign;
$this->microseconds += $interval->microseconds * $sign;

return $this;
}
Expand Down Expand Up @@ -1310,7 +1316,7 @@ public function total($unit)

if (in_array($unit, ['days', 'weeks'])) {
$realUnit = 'dayz';
} elseif (!in_array($unit, ['seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
} elseif (!in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
throw new InvalidArgumentException("Unknown unit '$unit'.");
}

Expand All @@ -1323,7 +1329,13 @@ public function total($unit)

if ($source === $realUnit) {
$unitFound = true;
$result += $this->$source;
$value = $this->$source;
if ($source === 'microseconds') {
$value %= 1000;
}
if ($source !== 'milliseconds') {
$result += $value;
}
$cumulativeFactor = 1;
}

Expand Down
7 changes: 6 additions & 1 deletion tests/AbstractTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public function assertInstanceOfCarbon($d)
$this->assertInstanceOf(CarbonInterface::class, $d);
}

public function assertCarbonInterval(CarbonInterval $ci, $years, $months = null, $days = null, $hours = null, $minutes = null, $seconds = null)
public function assertCarbonInterval(CarbonInterval $ci, $years, $months = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
{
$actual = ['years' => $ci->years];

Expand Down Expand Up @@ -171,6 +171,11 @@ public function assertCarbonInterval(CarbonInterval $ci, $years, $months = null,
$expected['seconds'] = $seconds;
}

if ($microseconds !== null) {
$actual['microseconds'] = $ci->microseconds;
$expected['microseconds'] = $microseconds;
}

$this->assertSame($expected, $actual);
}

Expand Down
17 changes: 13 additions & 4 deletions tests/CarbonInterval/AddTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ public function testAddWithNegativeDiffDateInterval()
$this->assertCarbonInterval($ci, 4, 3, 28, 8, 10, 11);
}

public function testAddMicroseconds()
{
$diff = Carbon::now()->diff(Carbon::now()->addDays(3)->addMicroseconds(111222));
$ci = CarbonInterval::create(1, 0, 0, 2, 0, 0, 0, 222333)->add($diff);
$this->assertCarbonInterval($ci, 1, 0, 5, 0, 0, 0, 333555);
$diff = Carbon::now()->diff(Carbon::now()->addDays(3));
$ci = CarbonInterval::create(1, 0, 0, 2, 0, 0, 0, 222333)->add($diff);
$this->assertCarbonInterval($ci, 1, 0, 5, 0, 0, 0, 222333);
$diff = Carbon::now()->diff(Carbon::now()->addDays(3)->addMicroseconds(111222));
$ci = CarbonInterval::create(1, 0, 0, 2, 0, 0, 0)->add($diff);
$this->assertCarbonInterval($ci, 1, 0, 5, 0, 0, 0, 111222);
}

public function testAddWithRawDiffDateInterval()
{
$diff = (new \DateTime())->diff(new \DateTime('3 weeks'));
Expand All @@ -52,9 +65,6 @@ public function testAddWithRawNegativeDiffDateInterval()
$this->assertCarbonInterval($ci, 4, 3, 28, 8, 10, 11);
}

/**
* @group i
*/
public function testAddAndSubMultipleFormats()
{
$this->assertCarbonInterval(CarbonInterval::day()->add('hours', 3), 0, 0, 1, 3, 0, 0);
Expand All @@ -74,7 +84,6 @@ public function testAddAndSubMultipleFormats()
}

/**
* @group i
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage This type of data cannot be added/subtracted.
*/
Expand Down
7 changes: 7 additions & 0 deletions tests/CarbonInterval/TotalTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,20 @@ public function testGetTotalsViaGetters()
{
$interval = CarbonInterval::create(0, 0, 0, 0, 150, 0, 0);

$this->assertSame(150 * 60 * 60 * 1000 * 1000, $interval->totalMicroseconds);
$this->assertSame(150 * 60 * 60 * 1000, $interval->totalMilliseconds);
$this->assertSame(150 * 60 * 60, $interval->totalSeconds);
$this->assertSame(150 * 60, $interval->totalMinutes);
$this->assertSame(150, $interval->totalHours);
$this->assertSame(150 / 24, $interval->totalDays);
$this->assertSame(150 / 24 / 7, $interval->totalWeeks);
$this->assertSame(150 / 24 / 7 / 4, $interval->totalMonths);
$this->assertSame(150 / 24 / 7 / 4 / 12, $interval->totalYears);

$interval = CarbonInterval::milliseconds(12312);

$this->assertSame(12312000, $interval->totalMicroseconds);
$this->assertSame(12312, $interval->totalMilliseconds);
}

public function testGetTotalsViaGettersWithCustomFactors()
Expand Down

0 comments on commit 790f2bc

Please sign in to comment.