Completed
Push — main ( 3b4b71...eb05bd )
by Andreas
14s queued 12s
created

CalendarDay::isModifiedDate()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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