Completed
Push — main ( ec0f68...b41cf0 )
by Andreas
14s queued 12s
created

CalendarDay::getCalendar()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
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 getCalendar(): IntlCalendar
95
	{
96
		return clone $this->calendar;
97
	}
98
99
	public function hasYearSet(): bool
100
	{
101
		return null !== $this->year;
102
	}
103
104
    public function isFollowUpDay(DateTimeInterface $dateTime, string $followUpDay): bool
105
    {
106
	    return $this->isModifiedDate($dateTime, $followUpDay, 'next');
107
    }
108
109
	private function isModifiedDate(DateTimeInterface $dateTime, string $modifiedDay, string $direction): bool
110
	{
111
		$cal = clone $this->calendar;
112
		$cal = self::setGregorianYearForDate((int) $dateTime->format('Y'), $cal);
113
		$day = $cal->toDateTime();
114
		$day->modify($direction . ' ' . $modifiedDay);
115
		$cal->setTime($day->getTimestamp() * 1000);
116
		$cal2         = clone $this->calendar;
117
		$cal2->setTime($dateTime->getTimestamp() * 1000);
118
119
		if (null !== $this->year && $cal->get(IntlCalendar::FIELD_YEAR) !== $cal2->get(IntlCalendar::FIELD_YEAR)) {
120
			return false;
121
		}
122
123
		if ($cal->get(IntlCalendar::FIELD_MONTH) !== $cal2->get(IntlCalendar::FIELD_MONTH)) {
124
			return false;
125
		}
126
127
		return $cal->get(IntlCalendar::FIELD_DAY_OF_MONTH) === $cal2->get(IntlCalendar::FIELD_DAY_OF_MONTH);
128
	}
129
130
    public function getWeekdayForGregorianYear(int $year): int
131
    {
132
        $cal = $this->getDayForGregorianYear($year);
133
134
        return $cal->get(IntlCalendar::FIELD_DAY_OF_WEEK);
135
    }
136
137
    private function getDayForGregorianYear(int $gregorianYear): IntlCalendar
138
    {
139
        $cal = clone $this->calendar;
140
        $cal->set(IntlCalendar::FIELD_MONTH, $this->month - 1);
141
        $cal->set(IntlCalendar::FIELD_DAY_OF_MONTH, $this->day);
142
143
        return self::setGregorianYearForDate($gregorianYear, $cal);
144
    }
145
}
146