Completed
Push — master ( cc516e...32adf9 )
by Philip
20:39
created

FlexDate::fromString()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.2728
c 0
b 0
f 0
cc 5
nc 9
nop 1
1
<?php
2
3
namespace Dontdrinkandroot\Date;
4
5
use DateTime;
6
use Exception;
7
8
/**
9
 * @author Philip Washington Sorst <[email protected]>
10
 */
11
class FlexDate
12
{
13
    const PRECISION_YEAR = 'year';
14
    const PRECISION_MONTH = 'month';
15
    const PRECISION_DAY = 'day';
16
    const PRECISION_NONE = 'none';
17
18
    protected ?int $year;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected '?', expecting T_FUNCTION or T_CONST
Loading history...
19
20
    protected ?int $month;
21
22
    protected ?int $day;
23
24
    public function __construct(?int $year = null, ?int $month = null, ?int $day = null)
25
    {
26
        $this->year = $year;
27
        $this->month = $month;
28
        $this->day = $day;
29
    }
30
31
    public function getYear(): ?int
32
    {
33
        return $this->year;
34
    }
35
36
    public function setYear(?int $year): void
37
    {
38
        $this->year = $year;
39
    }
40
41
    public function getMonth(): ?int
42
    {
43
        return $this->month;
44
    }
45
46
    public function setMonth(?int $month): void
47
    {
48
        $this->month = $month;
49
    }
50
51
    public function getDay(): ?int
52
    {
53
        return $this->day;
54
    }
55
56
    public function setDay(?int $day): void
57
    {
58
        $this->day = $day;
59
    }
60
61
    public function hasValue(): bool
62
    {
63
        return null !== $this->year || null !== $this->month || null !== $this->day;
64
    }
65
66
    public function isCompleteDate(): bool
67
    {
68
        return null !== $this->year && null !== $this->month && null !== $this->day;
69
    }
70
71
    public function isValid(): bool
72
    {
73
        try {
74
            $this->assertValid();
75
76
            return true;
77
        } catch (Exception $e) {
78
            return false;
79
        }
80
    }
81
82
    public function assertValid(): bool
83
    {
84
        if (null !== $this->day && null === $this->month) {
85
            throw new Exception('Day set, but no month');
86
        }
87
88
        if (null !== $this->month && null === $this->year) {
89
            throw new Exception('Month, but no year');
90
        }
91
92
        return true;
93
    }
94
95
    public function isValidDate(): bool
96
    {
97
        return checkdate($this->month, $this->day, $this->year);
98
    }
99
100
    public function toDateTime(): DateTime
101
    {
102
        $dateTime = new DateTime();
103
        $inferredYear = $this->year !== null ? $this->year : 0;
104
        $inferredMonth = $this->month !== null ? $this->month : 1;
105
        $inferredDay = $this->day !== null ? $this->day : 1;
106
        $dateTime->setDate($inferredYear, $inferredMonth, $inferredDay);
107
108
        return $dateTime;
109
    }
110
111
    public function __toString(): string
112
    {
113
        $string = '';
114
        if (null !== $this->year) {
115
            $string .= $this->year;
116
        }
117
        if (null !== $this->month) {
118
            $string .= '-';
119
            $string .= str_pad($this->month, 2, '0', STR_PAD_LEFT);
120
        }
121
        if (null !== $this->day) {
122
            $string .= '-';
123
            $string .= str_pad($this->day, 2, '0', STR_PAD_LEFT);
124
        }
125
126
        return $string;
127
    }
128
129
    public static function fromString(string $dateString): FlexDate
130
    {
131
        $flexDate = new FlexDate();
132
        if (empty($dateString)) {
133
            return $flexDate;
134
        }
135
136
        $parts = explode('-', $dateString);
137
        $numParts = count($parts);
138
        if ($numParts > 0) {
139
            $flexDate->setYear((int)$parts[0]);
140
        }
141
        if ($numParts > 1) {
142
            $flexDate->setMonth((int)$parts[1]);
143
        }
144
        if ($numParts > 2) {
145
            $flexDate->setDay((int)$parts[2]);
146
        }
147
148
        return $flexDate;
149
    }
150
151
    public function getPrecision(): string
152
    {
153
        if (null !== $this->day) {
154
            return self::PRECISION_DAY;
155
        }
156
157
        if (null !== $this->month) {
158
            return self::PRECISION_MONTH;
159
        }
160
161
        if (null !== $this->year) {
162
            return self::PRECISION_YEAR;
163
        }
164
165
        return self::PRECISION_NONE;
166
    }
167
}
168