DateSolar   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 126
rs 10
c 0
b 0
f 0
wmc 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 2
A toUnixTime() 0 17 2
B fromUnixTime() 0 61 4
1
<?php
2
3
namespace Popy\Calendar\Converter\UnixTimeConverter;
4
5
use Popy\Calendar\Converter\Conversion;
6
use Popy\Calendar\Converter\UnixTimeConverterInterface;
7
use Popy\Calendar\Converter\CompleteLeapYearCalculatorInterface;
8
use Popy\Calendar\ValueObject\DateSolarRepresentationInterface;
9
10
/**
11
 * Handles DateSolarRepresentationInterface.
12
 *
13
 * The eraDayIndex is calculated using an "eraStart" reference date. Year, year
14
 * length and leap days calculations are delegated to a LeapYearCalculator.
15
 */
16
class DateSolar implements UnixTimeConverterInterface
17
{
18
    /**
19
     * Era start unix time.
20
     *
21
     * @var integer
22
     */
23
    protected $eraStart;
24
25
    /**
26
     * Day length in seconds.
27
     *
28
     * @var integer|float|string
29
     */
30
    protected $dayLengthInSeconds = 24 * 3600;
31
32
    /**
33
     * Leap year calculator.
34
     *
35
     * @var CompleteLeapYearCalculatorInterface
36
     */
37
    protected $calculator;
38
39
    /**
40
     * Class constructor.
41
     *
42
     * @param CompleteLeapYearCalculatorInterface $calculator         Leap year calculator.
43
     * @param integer                     $eraStart           Era start unix time.
44
     * @param integer|float|string|null   $dayLengthInSeconds Day length in seconds.
45
     */
46
    public function __construct(CompleteLeapYearCalculatorInterface $calculator, $eraStart, $dayLengthInSeconds = null)
47
    {
48
        $this->calculator = $calculator;
49
        $this->eraStart   = $eraStart;
50
51
        if (null !== $dayLengthInSeconds) {
52
            $this->dayLengthInSeconds = $dayLengthInSeconds;
53
        }
54
    }
55
56
    /**
57
     * @inheritDoc
58
     */
59
    public function fromUnixTime(Conversion $conversion)
60
    {
61
        if (!$conversion->getTo() instanceof DateSolarRepresentationInterface) {
62
            return;
63
        }
64
65
        $res = $conversion->getTo();
66
67
        // TODO : remove code repetition by using a separate abstraction
68
        // handling basic math operations.
69
70
        if (is_integer($this->dayLengthInSeconds)) {
71
            // bc not needed/not available
72
73
            // Relative time from era start.
74
            $relativeTime = $conversion->getUnixTime() - $this->eraStart;
75
76
            // Calculating global day index. Floor is used to properly handle
77
            // negative values
78
            $eraDayIndex = (int)floor($relativeTime / $this->dayLengthInSeconds);
79
80
            $time = $relativeTime - $eraDayIndex * $this->dayLengthInSeconds;
81
82
            // TODO : handle the loss as microseconds ?
83
            if (is_float($time)) {
0 ignored issues
show
introduced by
The condition is_float($time) can never be true.
Loading history...
84
                $time = (int)ceil($time);
85
            }
86
87
            $conversion->setUnixTime($time);
88
        } else {
89
            // Using bc math if available for non int dayLengthInSeconds in
90
            // order to stay as precise as possible.
91
92
            // Relative time from era start.
93
            $relativeTime = bcsub($conversion->getUnixTime(), $this->eraStart);
94
95
            // Calculating global day index. Floor is used to properly handle
96
            // negative values
97
            $eraDayIndex = floor(
98
                bcdiv($relativeTime, $this->dayLengthInSeconds)
0 ignored issues
show
Bug introduced by
bcdiv($relativeTime, $this->dayLengthInSeconds) of type string is incompatible with the type double expected by parameter $value of floor(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
                /** @scrutinizer ignore-type */ bcdiv($relativeTime, $this->dayLengthInSeconds)
Loading history...
99
            );
100
101
            // TODO : handle the loss as microseconds ?
102
            $time = ceil(bcsub(
0 ignored issues
show
Bug introduced by
bcsub($relativeTime, bcm...s->dayLengthInSeconds)) of type string is incompatible with the type double expected by parameter $value of ceil(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

102
            $time = ceil(/** @scrutinizer ignore-type */ bcsub(
Loading history...
103
                $relativeTime,
104
                bcmul($eraDayIndex, $this->dayLengthInSeconds)
105
            ));
106
107
            $conversion->setUnixTime((int)$time);
108
        }
109
110
        list($year, $dayIndex) = $this->calculator
111
            ->getYearAndDayIndexFromErayDayIndex($eraDayIndex)
0 ignored issues
show
Bug introduced by
It seems like $eraDayIndex can also be of type double; however, parameter $eraDayIndex of Popy\Calendar\Converter\...IndexFromErayDayIndex() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

111
            ->getYearAndDayIndexFromErayDayIndex(/** @scrutinizer ignore-type */ $eraDayIndex)
Loading history...
112
        ;
113
114
        $res = $res
115
            ->withYear($year, $this->calculator->isLeapYear($year))
116
            ->withDayIndex($dayIndex, $eraDayIndex)
0 ignored issues
show
Bug introduced by
It seems like $eraDayIndex can also be of type double; however, parameter $eraDayIndex of Popy\Calendar\ValueObjec...terface::withDayIndex() does only seem to accept null|integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

116
            ->withDayIndex($dayIndex, /** @scrutinizer ignore-type */ $eraDayIndex)
Loading history...
117
        ;
118
119
        $conversion->setTo($res);
120
    }
121
122
    /**
123
     * @inheritDoc
124
     */
125
    public function toUnixTime(Conversion $conversion)
126
    {
127
        $input = $conversion->getTo();
128
129
        if (!$input instanceof DateSolarRepresentationInterface) {
130
            return;
131
        }
132
133
        $year = (int)$input->getYear();
134
        $eraDayIndex = $input->getDayIndex()
135
            + $this->calculator->getYearEraDayIndex($year)
136
        ;
137
138
        // TODO : BC Math implementation
139
        $conversion->setUnixTime(intval(
140
            $conversion->getUnixTime() + $this->eraStart
141
            + $eraDayIndex * $this->dayLengthInSeconds
142
        ));
143
    }
144
}
145