Passed
Push — refactor ( cbcbc2 )
by Andreas
01:30
created

CalendarDay::isModifiedDate()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 19
rs 9.8666
cc 4
nc 3
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Copyright (c) Andreas Heigl<[email protected]>
7
 *
8
 * Licensed under the MIT-license. For details see the included file LICENSE.md
9
 */
10
11
namespace Org_Heigl\Holidaychecker;
12
13
use DateTime;
14
use DateTimeImmutable;
15
use DateTimeInterface;
16
use IntlCalendar;
17
18
class CalendarDay
19
{
20
    /** @var int */
21
    private $day;
22
23
    /** @var int */
24
    private $month;
25
26
    /** @var int|null */
27
    private $year = null;
28
29
    /** @var IntlCalendar */
30
    private $calendar;
31
32
    public function __construct(int $day, int $month, IntlCalendar $calendar)
33
    {
34
        $this->day      = $day;
35
        $this->month    = $month;
36
        $this->calendar = $calendar;
37
        $this->calendar->set(IntlCalendar::FIELD_DAY_OF_MONTH, $day);
38
        $this->calendar->set(IntlCalendar::FIELD_MONTH, $month - 1);
39
        $this->calendar->set(IntlCalendar::FIELD_HOUR_OF_DAY, 12);
40
        $this->calendar->set(IntlCalendar::FIELD_MINUTE, 0);
41
        $this->calendar->set(IntlCalendar::FIELD_SECOND, 0);
42
        $this->calendar->set(IntlCalendar::FIELD_MILLISECOND, 0);
43
    }
44
45
    public function setYear(int $year): void
46
    {
47
        $this->year = $year;
48
        $this->calendar->set(IntlCalendar::FIELD_YEAR, $year);
49
    }
50
51
    public function setGregorianYear(int $year): void
52
    {
53
        $calendarYear = (int) $this->calendar->toDateTime()->format('Y');
54
55
        $diff = $year - $calendarYear;
56
        $realYear = $this->calendar->get(IntlCalendar::FIELD_YEAR);
57
58
        $this->year = $realYear + $diff;
59
        $this->calendar->add(IntlCalendar::FIELD_YEAR, $diff);
60
    }
61
62
    public static function setGregorianYearForDate(int $year, IntlCalendar $calendar): IntlCalendar
63
    {
64
        $datetime = $calendar->toDateTime();
65
        $yearDiff = $year - (int) $datetime->format('Y');
66
67
        $calendar->set(IntlCalendar::FIELD_YEAR, $calendar->get(IntlCalendar::FIELD_YEAR) + $yearDiff);
68
        if ($calendar->toDateTime()->format('Y') < $year) {
69
            $calendar->set(IntlCalendar::FIELD_YEAR, $calendar->get(IntlCalendar::FIELD_YEAR) + 1);
70
        }
71
        if ($calendar->toDateTime()->format('Y') > $year) {
72
            $calendar->set(IntlCalendar::FIELD_YEAR, $calendar->get(IntlCalendar::FIELD_YEAR) - 1);
73
        }
74
75
        return $calendar;
76
    }
77
78
    public function isSameDay(DateTimeInterface $dateTime): bool
79
    {
80
        $cal = clone $this->calendar;
81
        $cal->setTime($dateTime->getTimestamp() * 1000);
82
83
        if (null !== $this->year &&
84
            $cal->get(IntlCalendar::FIELD_YEAR) !== $this->calendar->get(IntlCalendar::FIELD_YEAR)
85
        ) {
86
            return false;
87
        }
88
89
        if ($cal->get(IntlCalendar::FIELD_MONTH) !== $this->calendar->get(IntlCalendar::FIELD_MONTH)) {
90
            return false;
91
        }
92
93
        return $cal->get(IntlCalendar::FIELD_DAY_OF_MONTH) === $this->calendar->get(IntlCalendar::FIELD_DAY_OF_MONTH);
94
    }
95
96
    public function isFollowUpDay(DateTimeInterface $dateTime, string $followUpDay): bool
97
    {
98
	    if ($dateTime instanceof DateTime) {
99
		    $dateTime = DateTimeImmutable::createFromMutable($dateTime);
100
	    }
101
	    return $this->isModifiedDate($dateTime, $followUpDay, 'next');
102
    }
103
104
    public function isPreviousDay(DateTimeInterface $dateTime, string $previousDay): bool
105
    {
106
		if ($dateTime instanceof DateTime) {
107
			$dateTime = DateTimeImmutable::createFromMutable($dateTime);
108
		}
109
		return $this->isModifiedDate($dateTime, $previousDay, 'previous');
110
    }
111
112
	private function isModifiedDate(DateTimeImmutable $dateTime, string $modifiedDay, string $direction): bool
113
	{
114
		$cal = clone $this->calendar;
115
		$cal = self::setGregorianYearForDate((int) $dateTime->format('Y'), $cal);
116
		$day = $cal->toDateTime();
117
		$day->modify($direction . ' ' . $modifiedDay);
118
		$cal->setTime($day->getTimestamp() * 1000);
119
		$cal2         = clone $this->calendar;
120
		$cal2->setTime($dateTime->getTimestamp() * 1000);
121
122
		if (null !== $this->year && $cal->get(IntlCalendar::FIELD_YEAR) !== $cal2->get(IntlCalendar::FIELD_YEAR)) {
123
			return false;
124
		}
125
126
		if ($cal->get(IntlCalendar::FIELD_MONTH) !== $cal2->get(IntlCalendar::FIELD_MONTH)) {
127
			return false;
128
		}
129
130
		return $cal->get(IntlCalendar::FIELD_DAY_OF_MONTH) === $cal2->get(IntlCalendar::FIELD_DAY_OF_MONTH);
131
	}
132
133
    public function getWeekdayForGregorianYear(int $year): int
134
    {
135
        $cal = $this->getDayForGregorianYear($year);
136
137
        return $cal->get(IntlCalendar::FIELD_DAY_OF_WEEK);
138
    }
139
140
    private function getDayForGregorianYear(int $gregorianYear): IntlCalendar
141
    {
142
        $cal = clone $this->calendar;
143
        $cal->set(IntlCalendar::FIELD_MONTH, $this->month - 1);
144
        $cal->set(IntlCalendar::FIELD_DAY_OF_MONTH, $this->day);
145
146
        $cal = self::setGregorianYearForDate($gregorianYear, $cal);
147
148
        return $cal;
149
    }
150
}
151