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; | |
| } | |
| } |