Week.php 7.1 KB

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