Matthias Andreas Benkard | 7b2a3a1 | 2021-08-16 10:57:25 +0200 | [diff] [blame] | 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * This file is part of the Carbon package. |
| 5 | * |
| 6 | * (c) Brian Nesbitt <brian@nesbot.com> |
| 7 | * |
| 8 | * For the full copyright and license information, please view the LICENSE |
| 9 | * file that was distributed with this source code. |
| 10 | */ |
Matthias Andreas Benkard | 1ba5381 | 2022-12-27 17:32:58 +0100 | [diff] [blame^] | 11 | |
Matthias Andreas Benkard | 7b2a3a1 | 2021-08-16 10:57:25 +0200 | [diff] [blame] | 12 | namespace Carbon\Traits; |
| 13 | |
| 14 | /** |
| 15 | * Trait Week. |
| 16 | * |
| 17 | * week and ISO week number, year and count in year. |
| 18 | * |
| 19 | * Depends on the following properties: |
| 20 | * |
| 21 | * @property int $daysInYear |
| 22 | * @property int $dayOfWeek |
| 23 | * @property int $dayOfYear |
| 24 | * @property int $year |
| 25 | * |
| 26 | * Depends on the following methods: |
| 27 | * |
| 28 | * @method static addWeeks(int $weeks = 1) |
| 29 | * @method static copy() |
| 30 | * @method static dayOfYear(int $dayOfYear) |
| 31 | * @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null) |
| 32 | * @method static next(int|string $day = null) |
| 33 | * @method static startOfWeek(int $day = 1) |
| 34 | * @method static subWeeks(int $weeks = 1) |
| 35 | * @method static year(int $year = null) |
| 36 | */ |
| 37 | trait Week |
| 38 | { |
| 39 | /** |
| 40 | * Set/get the week number of year using given first day of week and first |
| 41 | * day of year included in the first week. Or use ISO format if no settings |
| 42 | * given. |
| 43 | * |
| 44 | * @param int|null $year if null, act as a getter, if not null, set the year and return current instance. |
| 45 | * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) |
| 46 | * @param int|null $dayOfYear first day of year included in the week #1 |
| 47 | * |
| 48 | * @return int|static |
| 49 | */ |
| 50 | public function isoWeekYear($year = null, $dayOfWeek = null, $dayOfYear = null) |
| 51 | { |
| 52 | return $this->weekYear( |
| 53 | $year, |
| 54 | $dayOfWeek ?? 1, |
| 55 | $dayOfYear ?? 4 |
| 56 | ); |
| 57 | } |
| 58 | |
| 59 | /** |
| 60 | * Set/get the week number of year using given first day of week and first |
| 61 | * day of year included in the first week. Or use US format if no settings |
| 62 | * given (Sunday / Jan 6). |
| 63 | * |
| 64 | * @param int|null $year if null, act as a getter, if not null, set the year and return current instance. |
| 65 | * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) |
| 66 | * @param int|null $dayOfYear first day of year included in the week #1 |
| 67 | * |
| 68 | * @return int|static |
| 69 | */ |
| 70 | public function weekYear($year = null, $dayOfWeek = null, $dayOfYear = null) |
| 71 | { |
| 72 | $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0; |
| 73 | $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1; |
| 74 | |
| 75 | if ($year !== null) { |
| 76 | $year = (int) round($year); |
| 77 | |
| 78 | if ($this->weekYear(null, $dayOfWeek, $dayOfYear) === $year) { |
| 79 | return $this->avoidMutation(); |
| 80 | } |
| 81 | |
| 82 | $week = $this->week(null, $dayOfWeek, $dayOfYear); |
| 83 | $day = $this->dayOfWeek; |
| 84 | $date = $this->year($year); |
| 85 | switch ($date->weekYear(null, $dayOfWeek, $dayOfYear) - $year) { |
| 86 | case 1: |
| 87 | $date = $date->subWeeks(26); |
| 88 | |
| 89 | break; |
| 90 | case -1: |
| 91 | $date = $date->addWeeks(26); |
| 92 | |
| 93 | break; |
| 94 | } |
| 95 | |
| 96 | $date = $date->addWeeks($week - $date->week(null, $dayOfWeek, $dayOfYear))->startOfWeek($dayOfWeek); |
| 97 | |
| 98 | if ($date->dayOfWeek === $day) { |
| 99 | return $date; |
| 100 | } |
| 101 | |
| 102 | return $date->next($day); |
| 103 | } |
| 104 | |
| 105 | $year = $this->year; |
| 106 | $day = $this->dayOfYear; |
| 107 | $date = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); |
| 108 | |
| 109 | if ($date->year === $year && $day < $date->dayOfYear) { |
| 110 | return $year - 1; |
| 111 | } |
| 112 | |
| 113 | $date = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); |
| 114 | |
| 115 | if ($date->year === $year && $day >= $date->dayOfYear) { |
| 116 | return $year + 1; |
| 117 | } |
| 118 | |
| 119 | return $year; |
| 120 | } |
| 121 | |
| 122 | /** |
| 123 | * Get the number of weeks of the current week-year using given first day of week and first |
| 124 | * day of year included in the first week. Or use ISO format if no settings |
| 125 | * given. |
| 126 | * |
| 127 | * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) |
| 128 | * @param int|null $dayOfYear first day of year included in the week #1 |
| 129 | * |
| 130 | * @return int |
| 131 | */ |
| 132 | public function isoWeeksInYear($dayOfWeek = null, $dayOfYear = null) |
| 133 | { |
| 134 | return $this->weeksInYear( |
| 135 | $dayOfWeek ?? 1, |
| 136 | $dayOfYear ?? 4 |
| 137 | ); |
| 138 | } |
| 139 | |
| 140 | /** |
| 141 | * Get the number of weeks of the current week-year using given first day of week and first |
| 142 | * day of year included in the first week. Or use US format if no settings |
| 143 | * given (Sunday / Jan 6). |
| 144 | * |
| 145 | * @param int|null $dayOfWeek first date of week from 0 (Sunday) to 6 (Saturday) |
| 146 | * @param int|null $dayOfYear first day of year included in the week #1 |
| 147 | * |
| 148 | * @return int |
| 149 | */ |
| 150 | public function weeksInYear($dayOfWeek = null, $dayOfYear = null) |
| 151 | { |
| 152 | $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0; |
| 153 | $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1; |
| 154 | $year = $this->year; |
| 155 | $start = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); |
| 156 | $startDay = $start->dayOfYear; |
| 157 | if ($start->year !== $year) { |
| 158 | $startDay -= $start->daysInYear; |
| 159 | } |
| 160 | $end = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); |
| 161 | $endDay = $end->dayOfYear; |
| 162 | if ($end->year !== $year) { |
| 163 | $endDay += $this->daysInYear; |
| 164 | } |
| 165 | |
| 166 | return (int) round(($endDay - $startDay) / 7); |
| 167 | } |
| 168 | |
| 169 | /** |
| 170 | * Get/set the week number using given first day of week and first |
| 171 | * day of year included in the first week. Or use US format if no settings |
| 172 | * given (Sunday / Jan 6). |
| 173 | * |
| 174 | * @param int|null $week |
| 175 | * @param int|null $dayOfWeek |
| 176 | * @param int|null $dayOfYear |
| 177 | * |
| 178 | * @return int|static |
| 179 | */ |
| 180 | public function week($week = null, $dayOfWeek = null, $dayOfYear = null) |
| 181 | { |
| 182 | $date = $this; |
| 183 | $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0; |
| 184 | $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1; |
| 185 | |
| 186 | if ($week !== null) { |
| 187 | return $date->addWeeks(round($week) - $this->week(null, $dayOfWeek, $dayOfYear)); |
| 188 | } |
| 189 | |
| 190 | $start = $date->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); |
| 191 | $end = $date->avoidMutation()->startOfWeek($dayOfWeek); |
| 192 | if ($start > $end) { |
| 193 | $start = $start->subWeeks(26)->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek); |
| 194 | } |
| 195 | $week = (int) ($start->diffInDays($end) / 7 + 1); |
| 196 | |
| 197 | return $week > $end->weeksInYear($dayOfWeek, $dayOfYear) ? 1 : $week; |
| 198 | } |
| 199 | |
| 200 | /** |
| 201 | * Get/set the week number using given first day of week and first |
| 202 | * day of year included in the first week. Or use ISO format if no settings |
| 203 | * given. |
| 204 | * |
| 205 | * @param int|null $week |
| 206 | * @param int|null $dayOfWeek |
| 207 | * @param int|null $dayOfYear |
| 208 | * |
| 209 | * @return int|static |
| 210 | */ |
| 211 | public function isoWeek($week = null, $dayOfWeek = null, $dayOfYear = null) |
| 212 | { |
| 213 | return $this->week( |
| 214 | $week, |
| 215 | $dayOfWeek ?? 1, |
| 216 | $dayOfYear ?? 4 |
| 217 | ); |
| 218 | } |
| 219 | } |