Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
20.00% |
1 / 5 |
CRAP | |
90.62% |
58 / 64 |
Time | |
0.00% |
0 / 1 |
|
20.00% |
1 / 5 |
17.24 | |
90.62% |
58 / 64 |
__construct | |
0.00% |
0 / 1 |
3.14 | |
75.00% |
6 / 8 |
|||
fromUnixTime | |
0.00% |
0 / 1 |
2.00 | |
94.12% |
16 / 17 |
|||
toUnixTime | |
0.00% |
0 / 1 |
2.01 | |
88.89% |
8 / 9 |
|||
convertMicrosecondsToTime | |
100.00% |
1 / 1 |
3 | |
100.00% |
14 / 14 |
|||
convertTimeToMicroseconds | |
0.00% |
0 / 1 |
7.10 | |
87.50% |
14 / 16 |
<?php | |
namespace Popy\Calendar\Converter\UnixTimeConverter; | |
use Popy\Calendar\ValueObject\Time as TimeObject; | |
use Popy\Calendar\Converter\Conversion; | |
use Popy\Calendar\Converter\UnixTimeConverterInterface; | |
use Popy\Calendar\ValueObject\DateTimeRepresentationInterface; | |
/** | |
* Time of the day representation. | |
* | |
* Fragment units are, usually, named as, and used as : | |
* 0 => hours (format symbols ghGH) | |
* 1 => minutes (format symbol i) | |
* 2 => seconds (format symbol s) | |
* 3 => milliseconds (format symbol v) | |
* 4 => microseconds (format symbol ยต) | |
* | |
* Transversal units are, usually, named as and used as : | |
* 0 => Internet swatch time (format symbol B). | |
*/ | |
class Time implements UnixTimeConverterInterface | |
{ | |
/** | |
* Day length in seconds. | |
* | |
* @var integer | |
*/ | |
protected $dayLengthInSeconds = 24 * 3600; | |
/** | |
* Time format ranges. | |
* | |
* @var array<int> | |
*/ | |
protected $ranges = [24, 60, 60, 1000, 1000]; | |
/** | |
* Day length in microseconds. | |
* | |
* @var integer | |
*/ | |
protected $dayLengthInMicroSeconds; | |
/** | |
* Class constructor. | |
* | |
* @param array|null $ranges Time segments ranges/sizes. | |
* @param integer|null $dayLengthInSeconds Day length. | |
*/ | |
public function __construct(array $ranges = null, $dayLengthInSeconds = null) | |
{ | |
if (null !== $ranges) { | |
$this->ranges = $ranges; | |
} | |
if (null !== $dayLengthInSeconds) { | |
$this->dayLengthInSeconds = $dayLengthInSeconds; | |
} | |
$this->dayLengthInMicroSeconds = $this->dayLengthInSeconds * 1000000; | |
} | |
/** | |
* @inheritDoc | |
*/ | |
public function fromUnixTime(Conversion $conversion) | |
{ | |
$input = $conversion->getTo(); | |
if (!$input instanceof DateTimeRepresentationInterface) { | |
return; | |
} | |
$unixTime = $conversion->getUnixTime(); | |
$microSec = $conversion->getUnixMicroTime() | |
+ ($unixTime % $this->dayLengthInSeconds) * 1000000 | |
; | |
$time = $this->convertMicrosecondsToTime($microSec); | |
// Swatch time calculation. It's a fixed earth-day ratio, starting at a | |
// fixed +01:00 time offset. | |
$time = $time->withTransversal( | |
0, | |
intval(1000 * ($input->getUnixTime() + 3600) / 86400) % 1000 | |
); | |
// Removing the consumed seconds | |
$unixTime -= $unixTime % $this->dayLengthInSeconds; | |
$conversion | |
->setUnixTime($unixTime) | |
->setUnixMicroTime(0) | |
->setTo($input->withTime($time)) | |
; | |
} | |
/** | |
* @inheritDoc | |
*/ | |
public function toUnixTime(Conversion $conversion) | |
{ | |
$input = $conversion->getTo(); | |
if (!$input instanceof DateTimeRepresentationInterface) { | |
return; | |
} | |
$time = $input->getTime()->withSizes($this->ranges); | |
$microsec = $this->convertTimeToMicroseconds($time); | |
$conversion | |
->setTo($input->withTime($time)) | |
->setUnixTime($conversion->getUnixTime() + intval($microsec / 1000000)) | |
// Swatch time can return negative time. Shield against that. | |
->setUnixMicroTime(max(0, $microsec % 1000000)) | |
; | |
} | |
/** | |
* Convert a time expressed in microseconds, into a Time object. | |
* | |
* @param integer $time | |
* | |
* @return TimeObject | |
*/ | |
public function convertMicrosecondsToTime($time) | |
{ | |
// Calculating day-ratio; | |
// Dividing microseconds per seconds results in the intended value | |
$ratio = intval($time / $this->dayLengthInSeconds); | |
// If using a different time format, apply ratio | |
$timeScale = array_product($this->ranges); | |
if ($this->dayLengthInMicroSeconds !== $timeScale) { | |
$time = intval( | |
($time * $timeScale) / $this->dayLengthInMicroSeconds | |
); | |
} | |
$len = count($this->ranges); | |
$res = array_fill(0, $len, 0); | |
for ($i=$len - 1; $i > -1; $i--) { | |
$res[$i] = $time % $this->ranges[$i]; | |
$time = intval($time / $this->ranges[$i]); | |
} | |
return new TimeObject($res, $this->ranges, $ratio); | |
} | |
/** | |
* Converts a "Time" into its value in its lower unit. | |
* | |
* @param TimeObject $time | |
* | |
* @return integer | |
*/ | |
public function convertTimeToMicroseconds(TimeObject $time) | |
{ | |
$meaningfull = $time->countMeaningfull() > 0; | |
// IF time had no meaningfull informations, fallback to a day ratio. | |
if (!$meaningfull && null !== $ratio = $time->getRatio()) { | |
return $ratio * $this->dayLengthInSeconds; | |
} | |
// IF time had no meaningfull informations, use internel swatch time. | |
// May not work properly on non-earth systems. Whatever, who uses this | |
// anyway ? ANd who will use this on other planets ? | |
if (!$meaningfull && null !== $swatch = $time->getTransversal(0)) { | |
return $swatch * 1000 * 86400 | |
- 3600 * 1000000 // minus fixed time offset | |
; | |
} | |
$len = count($this->ranges); | |
$res = 0; | |
for ($i=0; $i < $len; $i++) { | |
$res = $res * $this->ranges[$i] + (int)$time->get($i); | |
} | |
// If using a different time format, apply ratio | |
$timeScale = array_product($this->ranges); | |
if ($this->dayLengthInMicroSeconds !== $timeScale) { | |
return intval(($res * $this->dayLengthInMicroSeconds) / $timeScale); | |
} | |
return $res; | |
} | |
} |