Skip to content

Commit

Permalink
Merge pull request #345 from thekid/feature/float-datetime
Browse files Browse the repository at this point in the history
Support passing floating point numbers to constructor, setting microseconds
  • Loading branch information
thekid authored Aug 24, 2024
2 parents 044654d + a01a576 commit e77d5b2
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 22 deletions.
21 changes: 15 additions & 6 deletions src/main/php/util/Date.class.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php namespace util;

use DateTime;
use lang\{IllegalArgumentException, IllegalStateException, Value};

/**
Expand Down Expand Up @@ -36,19 +37,27 @@ static function __static() {
* - If no timezone has been given as second parameter, the system's default
* timezone is used.
*
* @param ?int|string|php.DateTime $in
* @param ?int|float|string|DateTime $in
* @param ?util.TimeZone $timezone default NULL string of timezone
* @throws lang.IllegalArgumentException in case the date is unparseable
*/
public function __construct($in= null, ?TimeZone $timezone= null) {
if ($in instanceof \DateTime) {
if (null === $in) {
$this->handle= date_create('now', $timezone ? $timezone->getHandle() : null);
} else if ($in instanceof DateTime) {
$this->handle= $in;
} else if ((string)(int)$in === (string)$in) {
} else if (is_int($in) || (string)(int)$in === $in) {

// Specially mark timestamps for parsing (we assume here that strings
// containing only digits are timestamps)
$this->handle= date_create('@'.$in);
date_timezone_set($this->handle, $timezone ? $timezone->getHandle() : timezone_open(date_default_timezone_get()));
$timezone && date_timezone_set($this->handle, $timezone->getHandle());
} else if (is_float($in)) {

// Timestamps with microseconds are defined as `"@" "-"? [0-9]+ "." [0-9]{0,6}`,
// see https://www.php.net/manual/en/datetime.formats.php#datetime.formats.relative
$this->handle= date_create('@'.sprintf('%.6f', $in));
$timezone && date_timezone_set($this->handle, $timezone->getHandle());
} else {
if (false === ($this->handle= date_create($in ?? 'now', $timezone ? $timezone->getHandle() : null))) {
throw new IllegalArgumentException('Given argument is neither a timestamp nor a well-formed timestring: '.Objects::stringOf($in));
Expand All @@ -62,7 +71,7 @@ public function hashCode(): string {
}

/** Retrieve handle of underlying DateTime object. */
public function getHandle(): \DateTime {
public function getHandle(): DateTime {
return clone $this->handle;
}

Expand Down
25 changes: 9 additions & 16 deletions src/test/php/util/unittest/DateTest.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -343,22 +343,10 @@ public function createDateFromTime() {
Assert::equals(strtotime('19.19'), $date->getTime());
}

#[Test]
public function testValidUnixTimestamp() {
$this->assertDateEquals('1970-01-01T00:00:00+00:00', new Date(0));
$this->assertDateEquals('1970-01-01T00:00:00+00:00', new Date('0'));

$this->assertDateEquals('1970-01-01T00:00:01+00:00', new Date(1));
$this->assertDateEquals('1970-01-01T00:00:01+00:00', new Date('1'));

$this->assertDateEquals('1969-12-31T23:59:59+00:00', new Date(-1));
$this->assertDateEquals('1969-12-31T23:59:59+00:00', new Date('-1'));

$this->assertDateEquals('1969-12-20T10:13:20+00:00', new Date(-1000000));
$this->assertDateEquals('1969-12-20T10:13:20+00:00', new Date('-1000000'));

$this->assertDateEquals('1970-01-12T13:46:40+00:00', new Date(1000000));
$this->assertDateEquals('1970-01-12T13:46:40+00:00', new Date('1000000'));
#[Test, Values([[0, '1970-01-01T00:00:00+00:00'], [1, '1970-01-01T00:00:01+00:00'], [-1, '1969-12-31T23:59:59+00:00'], [-1000000, '1969-12-20T10:13:20+00:00'], [1000000, '1970-01-12T13:46:40+00:00']])]
public function testValidUnixTimestamp($timestamp, $expected) {
$this->assertDateEquals($expected, new Date($timestamp));
$this->assertDateEquals($expected, new Date((string)$timestamp));
}

#[Test, Expect(IllegalArgumentException::class)]
Expand All @@ -370,4 +358,9 @@ public function testInvalidUnixTimestamp() {
public function microseconds() {
Assert::equals(393313, (new Date('2019-07-03 15:18:10.393313'))->getMicroSeconds());
}

#[Test]
public function float_timestamp() {
Assert::equals(393000, (new Date(1723896922.393))->getMicroSeconds());
}
}

0 comments on commit e77d5b2

Please sign in to comment.