Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/TimestampValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ public function getMilliseconds()
return (int) ($this->value * 1000);
}

/**
* @param TimestampValueMilliSeconds $timestampValue
* @return TimestampValue
* @throws InvalidTimestampValueException
* @throws MissingTimestampValueException
*/
public static function fromTimestampValueMillis(TimestampValueMilliSeconds $timestampValue)
{
return new self($timestampValue->getValue() / 1000);
}

/**
* @param $timestamp
* @return bool
Expand Down
108 changes: 108 additions & 0 deletions src/TimestampValueMilliSeconds.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

namespace G4\ValueObject;

use G4\ValueObject\Exception\MissingTimestampValueException;
use G4\ValueObject\Exception\InvalidTimestampValueException;

class TimestampValueMilliSeconds implements StringInterface, NumberInterface
{
const MILLISECONDS_MIN_LENGTH = 10;
const MILLISECONDS_MAX_LENGTH = 13;

/**
* @var int
*/
private $value;

/**
* @param $value
* @throws MissingTimestampValueException
* @throws InvalidTimestampValueException
*/
public function __construct($value)
{
if (empty($value)) {
throw new MissingTimestampValueException();
}

if (!self::isValid($value)) {
throw new InvalidTimestampValueException($value);
}

$this->value = (int) $value;
}

public function __toString()
{
return (string) $this->value;
}

/**
* @return int
*/
public function getValue()
{
return $this->value;
}

/**
* @return int
*/
public function getSeconds()
{
return (int) ($this->value / 1000);
}

/**
* @return string
*/
public function getFormatted()
{
$seconds = (int) ($this->value / 1000);
$milliseconds = $this->value % 1000;
$millisecondsPadded = str_pad($milliseconds, 3, '0', STR_PAD_LEFT);
return date('Y-m-d H:i:s', $seconds) . '.' . $millisecondsPadded;
}

/**
* @param TimestampValue $timestampValue
* @return self
* @throws InvalidTimestampValueException
* @throws MissingTimestampValueException
*/
public static function fromTimestampValue(TimestampValue $timestampValue)
{
return new self($timestampValue->getValue() * 1000);
}

/**
* @return self
* @throws InvalidTimestampValueException
* @throws MissingTimestampValueException
*/
public static function now()
{
return new self((int) (microtime(true) * 1000));
}

/**
* @param $timestamp
* @return bool
*/
public static function isValid($timestamp)
{

if (strlen((string) $timestamp) < self::MILLISECONDS_MIN_LENGTH
|| strlen((string) $timestamp) > self::MILLISECONDS_MAX_LENGTH
) {
return false;
}

$check = (is_int($timestamp) || is_float($timestamp))
? $timestamp
: (string) (int) $timestamp;

return $check === $timestamp;
}
}
77 changes: 77 additions & 0 deletions tests/unit/src/TimestampValueMillisecondsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

namespace unit\src;

use G4\ValueObject\Exception\MissingTimestampValueException;
use G4\ValueObject\Exception\InvalidTimestampValueException;
use G4\ValueObject\TimestampValue;
use G4\ValueObject\TimestampValueMilliSeconds;
use PHPUnit\Framework\TestCase;

class TimestampValueMillisecondsTest extends TestCase
{
public function testMissingValueException()
{
$this->expectException(MissingTimestampValueException::class);
new TimestampValueMilliSeconds('');
}

public function testInvalidValueFloatException()
{
$this->expectException(InvalidTimestampValueException::class);
new TimestampValueMilliSeconds('1.0');
}

public function testInvalidValueHexaNumberException()
{
$this->expectException(InvalidTimestampValueException::class);
new TimestampValueMilliSeconds('0xFF');
}

public function testValidValues()
{
$now = (int) (microtime(true) * 1000);
$timestampInt = new TimestampValueMilliSeconds($now);
$this->assertEquals($now, $timestampInt->getValue());

$timestampString = new TimestampValueMilliSeconds('1748436857881');
$this->assertEquals('1748436857881', (string) $timestampString);
}

public function testGetFormatted()
{
$timestamp = new TimestampValueMilliSeconds('1748436857881');
$this->assertEquals('2025-05-28 14:54:17.881', $timestamp->getFormatted());
}

public function testGetSeconds()
{
$timestamp = new TimestampValueMilliSeconds(1748436857881);
$this->assertEquals(1748436857, $timestamp->getSeconds());
}

public function testNow()
{
$time = time();
$timestamp = TimestampValueMilliSeconds::now();
$this->assertEquals($time, $timestamp->getSeconds());
}

public function testInvalidValueLengthLower()
{
$this->expectException(InvalidTimestampValueException::class);
new TimestampValueMilliSeconds(123456789);
}

public function testInvalidValueLengthHigher()
{
$this->expectException(InvalidTimestampValueException::class);
new TimestampValueMilliSeconds(12345678912345);
}

public function testFromTimestampValue()
{
$timestamp = TimestampValueMilliSeconds::fromTimestampValue(new TimestampValue(1748436857));
$this->assertEquals(1748436857000, $timestamp->getValue());
}
}
7 changes: 7 additions & 0 deletions tests/unit/src/TimestampValueTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use G4\ValueObject\TimestampValue;
use G4\ValueObject\Exception\MissingTimestampValueException;
use G4\ValueObject\Exception\InvalidTimestampValueException;
use G4\ValueObject\TimestampValueMilliSeconds;

class TimestampValueTest extends \PHPUnit_Framework_TestCase
{
Expand Down Expand Up @@ -47,4 +48,10 @@ public function testGetMilliseconds()
$timestampString = new TimestampValue('1523441442');
$this->assertEquals('1523441442000', $timestampString->getMilliseconds());
}

public function testFromTimestampValueMillis()
{
$timestamp = TimestampValue::fromTimestampValueMillis(new TimestampValueMilliSeconds(1748436857000));
$this->assertEquals(1748436857, $timestamp->getValue());
}
}