AbstractDatePartsSolarSplitter::fromUnixTime()   B
last analyzed

Complexity

Conditions 6
Paths 5

Size

Total Lines 40
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 21
nc 5
nop 1
dl 0
loc 40
rs 8.439
c 0
b 0
f 0
1
<?php
2
3
namespace Popy\Calendar\Converter\UnixTimeConverter;
4
5
use OutOfBoundsException;
6
use Popy\Calendar\Converter\Conversion;
7
use Popy\Calendar\Converter\UnixTimeConverterInterface;
8
use Popy\Calendar\ValueObject\DateSolarRepresentationInterface;
9
use Popy\Calendar\ValueObject\DateFragmentedRepresentationInterface;
10
11
abstract class AbstractDatePartsSolarSplitter implements UnixTimeConverterInterface
12
{
13
    /**
14
     * @inheritDoc
15
     */
16
    public function fromUnixTime(Conversion $conversion)
17
    {
18
        $input = $conversion->getTo();
19
20
        if (
21
            !$input instanceof DateFragmentedRepresentationInterface
22
            || !$input instanceof DateSolarRepresentationInterface
23
        ) {
24
            return;
25
        }
26
27
        $dayIndex = $input->getDayIndex();
28
29
        $fragments = $resultSizes = [];
30
31
        foreach ($this->getAllFragmentSizes($input) as $sizes) {
32
            foreach ($sizes as $k => $size) {
33
                if ($dayIndex < $size) {
34
                    $fragments[] = $k;
35
                    $resultSizes[] = $size;
36
                    continue 2;
37
                }
38
39
                $dayIndex -= $size;
40
            }
41
42
            throw new OutOfBoundsException(
43
                'Input dayIndex too big for given fragment sizes'
44
            );
45
        }
46
47
        $fragments[] = $dayIndex;
48
49
50
        $dateParts = $input->getDateParts()
51
            ->withFragments($fragments)
52
            ->withSizes($resultSizes)
53
        ;
54
55
        $conversion->setTo($input->withDateParts($dateParts));
56
    }
57
58
    /**
59
     * @inheritDoc
60
     */
61
    public function toUnixTime(Conversion $conversion)
62
    {
63
        $input = $conversion->getTo();
64
65
        if (
66
            !$input instanceof DateFragmentedRepresentationInterface
67
            || !$input instanceof DateSolarRepresentationInterface
68
        ) {
69
            return;
70
        }
71
72
        if (null !== $input->getDayIndex()) {
73
            return ;
74
        }
75
76
        $dayIndex = 0;
77
        $dateParts = $input->getDateParts();
78
        $fragmentSizes = $this->getAllFragmentSizes($input);
79
80
        foreach ($dateParts->all() as $index => $value) {
81
            $value = (int)$value;
82
            if (!isset($fragmentSizes[$index])) {
83
                // No available size means we reached the final fragment
84
                $dayIndex += $value;
85
                break;
86
            }
87
88
            if ($value && !isset($fragmentSizes[$index][$value - 1])) {
89
                throw new OutOfBoundsException(sprintf(
90
                    '%s is an index too big for fragment #%s',
91
                    $value,
92
                    $index
93
                ));
94
            }
95
96
            for ($i=0; $i < $value; $i++) {
97
                $dayIndex += $fragmentSizes[$index][$i];
98
            }
99
        }
100
101
        $conversion->setTo($input->withDayIndex(
102
            $dayIndex,
103
            $input->getEraDayIndex()
104
        ));
105
    }
106
107
    /**
108
     * Returns an array containing, for each fragment, all its possible sizes in
109
     * days.
110
     *
111
     * For instance, for the standard gregorian calendar, should return
112
     * [ [31,28,31, ...] ]
113
     *
114
     * @param DateFragmentedRepresentationInterface $input
115
     *
116
     * @return array<array<integer>>
117
     */
118
    abstract protected function getAllFragmentSizes(DateFragmentedRepresentationInterface $input);
119
}
120