Carbon.php 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898
  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;
  11. use DateTime;
  12. use DateTimeZone;
  13. use InvalidArgumentException;
  14. /**
  15. * A simple API extension for DateTime
  16. *
  17. * @property integer $year
  18. * @property integer $month
  19. * @property integer $day
  20. * @property integer $hour
  21. * @property integer $minute
  22. * @property integer $second
  23. * @property integer $timestamp seconds since the Unix Epoch
  24. * @property-read integer $dayOfWeek 0 (for Sunday) through 6 (for Saturday)
  25. * @property-read integer $dayOfYear 0 through 365
  26. * @property-read integer $weekOfYear ISO-8601 week number of year, weeks starting on Monday
  27. * @property-read integer $daysInMonth number of days in the given month
  28. * @property-read integer $age does a diffInYears() with default parameters
  29. * @property-read integer $quarter the quarter of this instance, 1 - 4
  30. * @property-read integer $offset the timezone offset in seconds from UTC
  31. * @property-read integer $offsetHours the timezone offset in hours from UTC
  32. * @property-read integer $dst daylight savings time indicator, 1 if DST, 0 otherwise
  33. * @property-read string $timezoneName
  34. * @property-read string $tzName
  35. *
  36. * @property-read DateTimeZone $timezone the current timezone
  37. * @property-read DateTimeZone $tz alias of timezone
  38. * @property-write DateTimeZone|string $timezone the current timezone
  39. * @property-write DateTimeZone|string $tz alias of timezone
  40. *
  41. */
  42. class Carbon extends DateTime
  43. {
  44. /**
  45. * The day constants
  46. */
  47. const SUNDAY = 0;
  48. const MONDAY = 1;
  49. const TUESDAY = 2;
  50. const WEDNESDAY = 3;
  51. const THURSDAY = 4;
  52. const FRIDAY = 5;
  53. const SATURDAY = 6;
  54. /**
  55. * Names of days of the week.
  56. *
  57. * @var array
  58. */
  59. private static $days = array(
  60. self::SUNDAY => 'Sunday',
  61. self::MONDAY => 'Monday',
  62. self::TUESDAY => 'Tuesday',
  63. self::WEDNESDAY => 'Wednesday',
  64. self::THURSDAY => 'Thursday',
  65. self::FRIDAY => 'Friday',
  66. self::SATURDAY => 'Saturday'
  67. );
  68. /**
  69. * Number of X in Y
  70. */
  71. const MONTHS_PER_YEAR = 12;
  72. const HOURS_PER_DAY = 24;
  73. const MINUTES_PER_HOUR = 60;
  74. const SECONDS_PER_MINUTE = 60;
  75. /**
  76. * A test Carbon instance to be returned when now instances are created
  77. *
  78. * @var Carbon
  79. */
  80. protected static $testNow;
  81. /**
  82. * Creates a DateTimeZone from a string or a DateTimeZone
  83. *
  84. * @param DateTimeZone|string $object
  85. *
  86. * @return DateTimeZone
  87. */
  88. protected static function safeCreateDateTimeZone($object)
  89. {
  90. if ($object instanceof DateTimeZone) {
  91. return $object;
  92. }
  93. $tz = @timezone_open((string) $object);
  94. if ($tz === false) {
  95. throw new InvalidArgumentException('Unknown or bad timezone ('.$object.')');
  96. }
  97. return $tz;
  98. }
  99. ///////////////////////////////////////////////////////////////////
  100. //////////////////////////// CONSTRUCTORS /////////////////////////
  101. ///////////////////////////////////////////////////////////////////
  102. /**
  103. * Create a new Carbon instance.
  104. *
  105. * Please see the testing aids section (specifically static::setTestNow())
  106. * for more on the possibility of this constructor returning a test instance.
  107. *
  108. * @param string $time
  109. * @param DateTimeZone|string $tz
  110. */
  111. public function __construct($time = null, $tz = null)
  112. {
  113. // If the class has a test now set and we are trying to create a now()
  114. // instance then override as required
  115. if (static::hasTestNow() && (empty($time) || $time === 'now')) {
  116. $time = static::getTestNow()->toDateTimeString();
  117. $tz = static::getTestNow()->tz;
  118. }
  119. if ($tz !== null) {
  120. parent::__construct($time, self::safeCreateDateTimeZone($tz));
  121. } else {
  122. parent::__construct($time);
  123. }
  124. }
  125. /**
  126. * Create a Carbon instance from a DateTime one
  127. *
  128. * @param DateTime $dt
  129. *
  130. * @return Carbon
  131. */
  132. public static function instance(DateTime $dt)
  133. {
  134. return new static($dt->format('Y-m-d H:i:s'), $dt->getTimeZone());
  135. }
  136. /**
  137. * Create a carbon instance from a string. This is an alias for the
  138. * constructor that allows better fluent syntax as it allows you to do
  139. * Carbon::parse('Monday next week')->fn() rather than
  140. * (new Carbon('Monday next week'))->fn()
  141. *
  142. * @param string $time
  143. * @param DateTimeZone|string $tz
  144. */
  145. public static function parse($time = null, $tz = null)
  146. {
  147. return new static($time, $tz);
  148. }
  149. /**
  150. * Get a Carbon instance for the current date and time
  151. *
  152. * @param DateTimeZone|string $tz
  153. *
  154. * @return Carbon
  155. */
  156. public static function now($tz = null)
  157. {
  158. return new static(null, $tz);
  159. }
  160. /**
  161. * Create a Carbon instance for today
  162. *
  163. * @param DateTimeZone|string $tz
  164. *
  165. * @return Carbon
  166. */
  167. public static function today($tz = null)
  168. {
  169. return static::now($tz)->startOfDay();
  170. }
  171. /**
  172. * Create a Carbon instance for tomorrow
  173. *
  174. * @param DateTimeZone|string $tz
  175. *
  176. * @return Carbon
  177. */
  178. public static function tomorrow($tz = null)
  179. {
  180. return static::today($tz)->addDay();
  181. }
  182. /**
  183. * Create a Carbon instance for yesterday
  184. *
  185. * @param DateTimeZone|string $tz
  186. *
  187. * @return Carbon
  188. */
  189. public static function yesterday($tz = null)
  190. {
  191. return static::today($tz)->subDay();
  192. }
  193. /**
  194. * Create a new Carbon instance from a specific date and time.
  195. *
  196. * If any of $year, $month or $day are set to null their now() values
  197. * will be used.
  198. *
  199. * If $hour is null it will be set to its now() value and the default values
  200. * for $minute and $second will be their now() values.
  201. * If $hour is not null then the default values for $minute and $second
  202. * will be 0.
  203. *
  204. * @param integer $year
  205. * @param integer $month
  206. * @param integer $day
  207. * @param integer $hour
  208. * @param integer $minute
  209. * @param integer $second
  210. * @param DateTimeZone|string $tz
  211. *
  212. * @return Carbon
  213. */
  214. public static function create($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $tz = null)
  215. {
  216. $year = ($year === null) ? date('Y') : $year;
  217. $month = ($month === null) ? date('n') : $month;
  218. $day = ($day === null) ? date('j') : $day;
  219. if ($hour === null) {
  220. $hour = date('G');
  221. $minute = ($minute === null) ? date('i') : $minute;
  222. $second = ($second === null) ? date('s') : $second;
  223. } else {
  224. $minute = ($minute === null) ? 0 : $minute;
  225. $second = ($second === null) ? 0 : $second;
  226. }
  227. return self::createFromFormat('Y-n-j G:i:s', sprintf('%s-%s-%s %s:%02s:%02s', $year, $month, $day, $hour, $minute, $second), $tz);
  228. }
  229. /**
  230. * Create a Carbon instance from just a date. The time portion is set to now.
  231. *
  232. * @param integer $year
  233. * @param integer $month
  234. * @param integer $day
  235. * @param DateTimeZone|string $tz
  236. *
  237. * @return Carbon
  238. */
  239. public static function createFromDate($year = null, $month = null, $day = null, $tz = null)
  240. {
  241. return self::create($year, $month, $day, null, null, null, $tz);
  242. }
  243. /**
  244. * Create a Carbon instance from just a time. The date portion is set to today.
  245. *
  246. * @param integer $hour
  247. * @param integer $minute
  248. * @param integer $second
  249. * @param DateTimeZone|string $tz
  250. *
  251. * @return Carbon
  252. */
  253. public static function createFromTime($hour = null, $minute = null, $second = null, $tz = null)
  254. {
  255. return self::create(null, null, null, $hour, $minute, $second, $tz);
  256. }
  257. /**
  258. * Create a Carbon instance from a specific format
  259. *
  260. * @param string $format
  261. * @param string $time
  262. * @param DateTimeZone|string $tz
  263. *
  264. * @return Carbon
  265. */
  266. public static function createFromFormat($format, $time, $tz = null)
  267. {
  268. if ($tz !== null) {
  269. $dt = parent::createFromFormat($format, $time, self::safeCreateDateTimeZone($tz));
  270. } else {
  271. $dt = parent::createFromFormat($format, $time);
  272. }
  273. if ($dt instanceof DateTime) {
  274. return self::instance($dt);
  275. }
  276. $errors = DateTime::getLastErrors();
  277. throw new InvalidArgumentException(implode(PHP_EOL, $errors['errors']));
  278. }
  279. /**
  280. * Create a Carbon instance from a timestamp
  281. *
  282. * @param integer $timestamp
  283. * @param DateTimeZone|string $tz
  284. *
  285. * @return Carbon
  286. */
  287. public static function createFromTimestamp($timestamp, $tz = null)
  288. {
  289. return self::now($tz)->setTimestamp($timestamp);
  290. }
  291. /**
  292. * Create a Carbon instance from an UTC timestamp
  293. *
  294. * @param integer $timestamp
  295. *
  296. * @return Carbon
  297. */
  298. public static function createFromTimestampUTC($timestamp)
  299. {
  300. return new static('@'.$timestamp);
  301. }
  302. /**
  303. * Get a copy of the instance
  304. *
  305. * @return Carbon
  306. */
  307. public function copy()
  308. {
  309. return self::instance($this);
  310. }
  311. ///////////////////////////////////////////////////////////////////
  312. ///////////////////////// GETTERS AND SETTERS /////////////////////
  313. ///////////////////////////////////////////////////////////////////
  314. /**
  315. * Get a part of the Carbon object
  316. *
  317. * @param string $name
  318. *
  319. * @return string|integer|DateTimeZone
  320. */
  321. public function __get($name)
  322. {
  323. switch ($name) {
  324. case 'year':
  325. return intval($this->format('Y'));
  326. case 'month':
  327. return intval($this->format('n'));
  328. case 'day':
  329. return intval($this->format('j'));
  330. case 'hour':
  331. return intval($this->format('G'));
  332. case 'minute':
  333. return intval($this->format('i'));
  334. case 'second':
  335. return intval($this->format('s'));
  336. case 'dayOfWeek':
  337. return intval($this->format('w'));
  338. case 'dayOfYear':
  339. return intval($this->format('z'));
  340. case 'weekOfYear':
  341. return intval($this->format('W'));
  342. case 'daysInMonth':
  343. return intval($this->format('t'));
  344. case 'timestamp':
  345. return intval($this->format('U'));
  346. case 'age':
  347. return intval($this->diffInYears());
  348. case 'quarter':
  349. return intval(($this->month - 1) / 3) + 1;
  350. case 'offset':
  351. return $this->getOffset();
  352. case 'offsetHours':
  353. return $this->getOffset() / self::SECONDS_PER_MINUTE / self::MINUTES_PER_HOUR;
  354. case 'dst':
  355. return $this->format('I') == '1';
  356. case 'timezone':
  357. return $this->getTimezone();
  358. case 'timezoneName':
  359. return $this->getTimezone()->getName();
  360. case 'tz':
  361. return $this->timezone;
  362. case 'tzName':
  363. return $this->timezoneName;
  364. default:
  365. throw new InvalidArgumentException(sprintf("Unknown getter '%s'", $name));
  366. }
  367. }
  368. /**
  369. * Check if an attribute exists on the object
  370. *
  371. * @param string $name
  372. *
  373. * @return boolean
  374. */
  375. public function __isset($name)
  376. {
  377. try {
  378. $this->__get($name);
  379. } catch (InvalidArgumentException $e) {
  380. return false;
  381. }
  382. return true;
  383. }
  384. /**
  385. * Set a part of the Carbon object
  386. *
  387. * @param string $name
  388. * @param string|integer|DateTimeZone $value
  389. */
  390. public function __set($name, $value)
  391. {
  392. switch ($name) {
  393. case 'year':
  394. parent::setDate($value, $this->month, $this->day);
  395. break;
  396. case 'month':
  397. parent::setDate($this->year, $value, $this->day);
  398. break;
  399. case 'day':
  400. parent::setDate($this->year, $this->month, $value);
  401. break;
  402. case 'hour':
  403. parent::setTime($value, $this->minute, $this->second);
  404. break;
  405. case 'minute':
  406. parent::setTime($this->hour, $value, $this->second);
  407. break;
  408. case 'second':
  409. parent::setTime($this->hour, $this->minute, $value);
  410. break;
  411. case 'timestamp':
  412. parent::setTimestamp($value);
  413. break;
  414. case 'timezone':
  415. $this->setTimezone($value);
  416. break;
  417. case 'tz':
  418. $this->setTimezone($value);
  419. break;
  420. default:
  421. throw new InvalidArgumentException(sprintf("Unknown setter '%s'", $name));
  422. }
  423. }
  424. /**
  425. * Set the instance's year
  426. *
  427. * @param integer $value
  428. *
  429. * @return self
  430. */
  431. public function year($value)
  432. {
  433. $this->year = $value;
  434. return $this;
  435. }
  436. /**
  437. * Set the instance's month
  438. *
  439. * @param integer $value
  440. *
  441. * @return self
  442. */
  443. public function month($value)
  444. {
  445. $this->month = $value;
  446. return $this;
  447. }
  448. /**
  449. * Set the instance's day
  450. *
  451. * @param integer $value
  452. *
  453. * @return self
  454. */
  455. public function day($value)
  456. {
  457. $this->day = $value;
  458. return $this;
  459. }
  460. /**
  461. * Set the date all together
  462. *
  463. * @param integer $year
  464. * @param integer $month
  465. * @param integer $day
  466. *
  467. * @return self
  468. */
  469. public function setDate($year, $month, $day)
  470. {
  471. return $this->year($year)->month($month)->day($day);
  472. }
  473. /**
  474. * Set the instance's hour
  475. *
  476. * @param integer $value
  477. *
  478. * @return self
  479. */
  480. public function hour($value)
  481. {
  482. $this->hour = $value;
  483. return $this;
  484. }
  485. /**
  486. * Set the instance's minute
  487. *
  488. * @param integer $value
  489. *
  490. * @return self
  491. */
  492. public function minute($value)
  493. {
  494. $this->minute = $value;
  495. return $this;
  496. }
  497. /**
  498. * Set the instance's second
  499. *
  500. * @param integer $value
  501. *
  502. * @return self
  503. */
  504. public function second($value)
  505. {
  506. $this->second = $value;
  507. return $this;
  508. }
  509. /**
  510. * Set the time all together
  511. *
  512. * @param integer $hour
  513. * @param integer $minute
  514. * @param integer $second
  515. *
  516. * @return self
  517. */
  518. public function setTime($hour, $minute, $second = NULL, $microseconds = NULL)
  519. {
  520. if(is_null($second)) $second = 0;
  521. return $this->hour($hour)->minute($minute)->second($second);
  522. }
  523. /**
  524. * Set the date and time all together
  525. *
  526. * @param integer $year
  527. * @param integer $month
  528. * @param integer $day
  529. * @param integer $hour
  530. * @param integer $minute
  531. * @param integer $second
  532. *
  533. * @return self
  534. */
  535. public function setDateTime($year, $month, $day, $hour, $minute, $second)
  536. {
  537. return $this->setDate($year, $month, $day)->setTime($hour, $minute, $second);
  538. }
  539. /**
  540. * Set the instance's timestamp
  541. *
  542. * @param integer $value
  543. *
  544. * @return self
  545. */
  546. public function timestamp($value)
  547. {
  548. $this->timestamp = $value;
  549. return $this;
  550. }
  551. /**
  552. * Alias for setTimezone()
  553. *
  554. * @param DateTimeZone|string $value
  555. *
  556. * @return self
  557. */
  558. public function timezone($value)
  559. {
  560. return $this->setTimezone($value);
  561. }
  562. /**
  563. * Alias for setTimezone()
  564. *
  565. * @param DateTimeZone|string $value
  566. *
  567. * @return self
  568. */
  569. public function tz($value)
  570. {
  571. return $this->setTimezone($value);
  572. }
  573. /**
  574. * Set the instance's timezone from a string or object
  575. *
  576. * @param DateTimeZone|string $value
  577. */
  578. public function setTimezone($value)
  579. {
  580. parent::setTimezone(self::safeCreateDateTimeZone($value));
  581. return $this;
  582. }
  583. ///////////////////////////////////////////////////////////////////
  584. ///////////////////////// TESTING AIDS ////////////////////////////
  585. ///////////////////////////////////////////////////////////////////
  586. /**
  587. * Set a Carbon instance (real or mock) to be returned when a "now"
  588. * instance is created. The provided instance will be returned
  589. * specifically under the following conditions:
  590. * - A call to the static now() method, ex. Carbon::now()
  591. * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null)
  592. * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now')
  593. *
  594. * Note the timezone parameter was left out of the examples above and
  595. * has no affect as the mock value will be returned regardless of its value.
  596. *
  597. * To clear the test instance call this method using the default
  598. * parameter of null.
  599. *
  600. * @param Carbon $testNow
  601. */
  602. public static function setTestNow(Carbon $testNow = null)
  603. {
  604. static::$testNow = $testNow;
  605. }
  606. /**
  607. * Get the Carbon instance (real or mock) to be returned when a "now"
  608. * instance is created.
  609. *
  610. * @return Carbon the current instance used for testing
  611. */
  612. public static function getTestNow()
  613. {
  614. return static::$testNow;
  615. }
  616. /**
  617. * Determine if there is a valid test instance set. A valid test instance
  618. * is anything that is not null.
  619. *
  620. * @return boolean true if there is a test instance, otherwise false
  621. */
  622. public static function hasTestNow()
  623. {
  624. return static::getTestNow() !== null;
  625. }
  626. ///////////////////////////////////////////////////////////////////
  627. /////////////////////// STRING FORMATTING /////////////////////////
  628. ///////////////////////////////////////////////////////////////////
  629. /**
  630. * Format the instance with the current locale. You can set the current
  631. * locale using setlocale() http://php.net/setlocale.
  632. *
  633. * @param string $format
  634. *
  635. * @return string
  636. */
  637. public function formatLocalized($format)
  638. {
  639. return strftime($format, $this->timestamp);
  640. }
  641. /**
  642. * Format the instance with date and time
  643. *
  644. * @return string
  645. */
  646. public function __toString()
  647. {
  648. return $this->toDateTimeString();
  649. }
  650. /**
  651. * Format the instance as date
  652. *
  653. * @return string
  654. */
  655. public function toDateString()
  656. {
  657. return $this->format('Y-m-d');
  658. }
  659. /**
  660. * Format the instance as a readable date
  661. *
  662. * @return string
  663. */
  664. public function toFormattedDateString()
  665. {
  666. return $this->format('M j, Y');
  667. }
  668. /**
  669. * Format the instance as time
  670. *
  671. * @return string
  672. */
  673. public function toTimeString()
  674. {
  675. return $this->format('H:i:s');
  676. }
  677. /**
  678. * Format the instance as date and time
  679. *
  680. * @return string
  681. */
  682. public function toDateTimeString()
  683. {
  684. return $this->format('Y-m-d H:i:s');
  685. }
  686. /**
  687. * Format the instance with day, date and time
  688. *
  689. * @return string
  690. */
  691. public function toDayDateTimeString()
  692. {
  693. return $this->format('D, M j, Y g:i A');
  694. }
  695. /**
  696. * Format the instance as ATOM
  697. *
  698. * @return string
  699. */
  700. public function toATOMString()
  701. {
  702. return $this->format(DateTime::ATOM);
  703. }
  704. /**
  705. * Format the instance as COOKIE
  706. *
  707. * @return string
  708. */
  709. public function toCOOKIEString()
  710. {
  711. return $this->format(DateTime::COOKIE);
  712. }
  713. /**
  714. * Format the instance as ISO8601
  715. *
  716. * @return string
  717. */
  718. public function toISO8601String()
  719. {
  720. return $this->format(DateTime::ISO8601);
  721. }
  722. /**
  723. * Format the instance as RFC822
  724. *
  725. * @return string
  726. */
  727. public function toRFC822String()
  728. {
  729. return $this->format(DateTime::RFC822);
  730. }
  731. /**
  732. * Format the instance as RFC850
  733. *
  734. * @return string
  735. */
  736. public function toRFC850String()
  737. {
  738. return $this->format(DateTime::RFC850);
  739. }
  740. /**
  741. * Format the instance as RFC1036
  742. *
  743. * @return string
  744. */
  745. public function toRFC1036String()
  746. {
  747. return $this->format(DateTime::RFC1036);
  748. }
  749. /**
  750. * Format the instance as RFC1123
  751. *
  752. * @return string
  753. */
  754. public function toRFC1123String()
  755. {
  756. return $this->format(DateTime::RFC1123);
  757. }
  758. /**
  759. * Format the instance as RFC2822
  760. *
  761. * @return string
  762. */
  763. public function toRFC2822String()
  764. {
  765. return $this->format(DateTime::RFC2822);
  766. }
  767. /**
  768. * Format the instance as RFC3339
  769. *
  770. * @return string
  771. */
  772. public function toRFC3339String()
  773. {
  774. return $this->format(DateTime::RFC3339);
  775. }
  776. /**
  777. * Format the instance as RSS
  778. *
  779. * @return string
  780. */
  781. public function toRSSString()
  782. {
  783. return $this->format(DateTime::RSS);
  784. }
  785. /**
  786. * Format the instance as W3C
  787. *
  788. * @return string
  789. */
  790. public function toW3CString()
  791. {
  792. return $this->format(DateTime::W3C);
  793. }
  794. ///////////////////////////////////////////////////////////////////
  795. ////////////////////////// COMPARISONS ////////////////////////////
  796. ///////////////////////////////////////////////////////////////////
  797. /**
  798. * Determines if the instance is equal to another
  799. *
  800. * @param Carbon $dt
  801. *
  802. * @return boolean
  803. */
  804. public function eq(Carbon $dt)
  805. {
  806. return $this == $dt;
  807. }
  808. /**
  809. * Determines if the instance is not equal to another
  810. *
  811. * @param Carbon $dt
  812. *
  813. * @return boolean
  814. */
  815. public function ne(Carbon $dt)
  816. {
  817. return !$this->eq($dt);
  818. }
  819. /**
  820. * Determines if the instance is greater (after) than another
  821. *
  822. * @param Carbon $dt
  823. *
  824. * @return boolean
  825. */
  826. public function gt(Carbon $dt)
  827. {
  828. return $this > $dt;
  829. }
  830. /**
  831. * Determines if the instance is greater (after) than or equal to another
  832. *
  833. * @param Carbon $dt
  834. *
  835. * @return boolean
  836. */
  837. public function gte(Carbon $dt)
  838. {
  839. return $this >= $dt;
  840. }
  841. /**
  842. * Determines if the instance is less (before) than another
  843. *
  844. * @param Carbon $dt
  845. *
  846. * @return boolean
  847. */
  848. public function lt(Carbon $dt)
  849. {
  850. return $this < $dt;
  851. }
  852. /**
  853. * Determines if the instance is less (before) or equal to another
  854. *
  855. * @param Carbon $dt
  856. *
  857. * @return boolean
  858. */
  859. public function lte(Carbon $dt)
  860. {
  861. return $this <= $dt;
  862. }
  863. /**
  864. * Determines if the instance is between two others
  865. *
  866. * @param Carbon $dt1
  867. * @param Carbon $dt2
  868. * @param boolean $equal Indicates if a > and < comparison should be used or <= or >=
  869. *
  870. * @return boolean
  871. */
  872. public function between(Carbon $dt1, Carbon $dt2, $equal = true)
  873. {
  874. if ($dt1->gt($dt2)) {
  875. $temp = $dt1;
  876. $dt1 = $dt2;
  877. $dt2 = $temp;
  878. }
  879. if ($equal) {
  880. return $this->gte($dt1) && $this->lte($dt2);
  881. } else {
  882. return $this->gt($dt1) && $this->lt($dt2);
  883. }
  884. }
  885. /**
  886. * Determines if the instance is a weekday
  887. *
  888. * @return boolean
  889. */
  890. public function isWeekday()
  891. {
  892. return ($this->dayOfWeek != self::SUNDAY && $this->dayOfWeek != self::SATURDAY);
  893. }
  894. /**
  895. * Determines if the instance is a weekend day
  896. *
  897. * @return boolean
  898. */
  899. public function isWeekend()
  900. {
  901. return !$this->isWeekDay();
  902. }
  903. /**
  904. * Determines if the instance is yesterday
  905. *
  906. * @return boolean
  907. */
  908. public function isYesterday()
  909. {
  910. return $this->toDateString() === self::now($this->tz)->subDay()->toDateString();
  911. }
  912. /**
  913. * Determines if the instance is today
  914. *
  915. * @return boolean
  916. */
  917. public function isToday()
  918. {
  919. return $this->toDateString() === self::now($this->tz)->toDateString();
  920. }
  921. /**
  922. * Determines if the instance is tomorrow
  923. *
  924. * @return boolean
  925. */
  926. public function isTomorrow()
  927. {
  928. return $this->toDateString() === self::now($this->tz)->addDay()->toDateString();
  929. }
  930. /**
  931. * Determines if the instance is in the future, ie. greater (after) than now
  932. *
  933. * @return boolean
  934. */
  935. public function isFuture()
  936. {
  937. return $this->gt(self::now($this->tz));
  938. }
  939. /**
  940. * Determines if the instance is in the past, ie. less (before) than now
  941. *
  942. * @return boolean
  943. */
  944. public function isPast()
  945. {
  946. return !$this->isFuture();
  947. }
  948. /**
  949. * Determines if the instance is a leap year
  950. *
  951. * @return boolean
  952. */
  953. public function isLeapYear()
  954. {
  955. return $this->format('L') == '1';
  956. }
  957. ///////////////////////////////////////////////////////////////////
  958. /////////////////// ADDITIONS AND SUBSTRACTIONS ///////////////////
  959. ///////////////////////////////////////////////////////////////////
  960. /**
  961. * Add years to the instance. Positive $value travel forward while
  962. * negative $value travel into the past.
  963. *
  964. * @param integer $value
  965. *
  966. * @return self
  967. */
  968. public function addYears($value)
  969. {
  970. return $this->modify(intval($value) . ' year');
  971. }
  972. /**
  973. * Add a year to the instance
  974. *
  975. * @return self
  976. */
  977. public function addYear()
  978. {
  979. return $this->addYears(1);
  980. }
  981. /**
  982. * Remove a year from the instance
  983. *
  984. * @return self
  985. */
  986. public function subYear()
  987. {
  988. return $this->addYears(-1);
  989. }
  990. /**
  991. * Remove years from the instance.
  992. *
  993. * @param integer $value
  994. *
  995. * @return self
  996. */
  997. public function subYears($value)
  998. {
  999. return $this->addYears(-1 * $value);
  1000. }
  1001. /**
  1002. * Add months to the instance. Positive $value travels forward while
  1003. * negative $value travels into the past.
  1004. *
  1005. * @param integer $value
  1006. *
  1007. * @return self
  1008. */
  1009. public function addMonths($value)
  1010. {
  1011. return $this->modify(intval($value) . ' month');
  1012. }
  1013. /**
  1014. * Add a month to the instance
  1015. *
  1016. * @return self
  1017. */
  1018. public function addMonth()
  1019. {
  1020. return $this->addMonths(1);
  1021. }
  1022. /**
  1023. * Remove a month from the instance
  1024. *
  1025. * @return self
  1026. */
  1027. public function subMonth()
  1028. {
  1029. return $this->addMonths(-1);
  1030. }
  1031. /**
  1032. * Remove months from the instance
  1033. *
  1034. * @param integer $value
  1035. *
  1036. * @return self
  1037. */
  1038. public function subMonths($value)
  1039. {
  1040. return $this->addMonths(-1 * $value);
  1041. }
  1042. /**
  1043. * Add days to the instance. Positive $value travels forward while
  1044. * negative $value travels into the past.
  1045. *
  1046. * @param integer $value
  1047. *
  1048. * @return self
  1049. */
  1050. public function addDays($value)
  1051. {
  1052. return $this->modify(intval($value) . ' day');
  1053. }
  1054. /**
  1055. * Add a day to the instance
  1056. *
  1057. * @return self
  1058. */
  1059. public function addDay()
  1060. {
  1061. return $this->addDays(1);
  1062. }
  1063. /**
  1064. * Remove a day from the instance
  1065. *
  1066. * @return self
  1067. */
  1068. public function subDay()
  1069. {
  1070. return $this->addDays(-1);
  1071. }
  1072. /**
  1073. * Remove days from the instance
  1074. *
  1075. * @param integer $value
  1076. *
  1077. * @return self
  1078. */
  1079. public function subDays($value)
  1080. {
  1081. return $this->addDays(-1 * $value);
  1082. }
  1083. /**
  1084. * Add weekdays to the instance. Positive $value travels forward while
  1085. * negative $value travels into the past.
  1086. *
  1087. * @param integer $value
  1088. *
  1089. * @return self
  1090. */
  1091. public function addWeekdays($value)
  1092. {
  1093. return $this->modify(intval($value) . ' weekday');
  1094. }
  1095. /**
  1096. * Add a weekday to the instance
  1097. *
  1098. * @return self
  1099. */
  1100. public function addWeekday()
  1101. {
  1102. return $this->addWeekdays(1);
  1103. }
  1104. /**
  1105. * Remove a weekday from the instance
  1106. *
  1107. * @return self
  1108. */
  1109. public function subWeekday()
  1110. {
  1111. return $this->addWeekdays(-1);
  1112. }
  1113. /**
  1114. * Remove weekdays from the instance
  1115. *
  1116. * @param integer $value
  1117. *
  1118. * @return self
  1119. */
  1120. public function subWeekdays($value)
  1121. {
  1122. return $this->addWeekdays(-1 * $value);
  1123. }
  1124. /**
  1125. * Add weeks to the instance. Positive $value travels forward while
  1126. * negative $value travels into the past.
  1127. *
  1128. * @param integer $value
  1129. *
  1130. * @return self
  1131. */
  1132. public function addWeeks($value)
  1133. {
  1134. return $this->modify(intval($value) . ' week');
  1135. }
  1136. /**
  1137. * Add a week to the instance
  1138. *
  1139. * @return self
  1140. */
  1141. public function addWeek()
  1142. {
  1143. return $this->addWeeks(1);
  1144. }
  1145. /**
  1146. * Remove a week from the instance
  1147. *
  1148. * @return self
  1149. */
  1150. public function subWeek()
  1151. {
  1152. return $this->addWeeks(-1);
  1153. }
  1154. /**
  1155. * Remove weeks to the instance
  1156. *
  1157. * @param integer $value
  1158. *
  1159. * @return self
  1160. */
  1161. public function subWeeks($value)
  1162. {
  1163. return $this->addWeeks(-1 * $value);
  1164. }
  1165. /**
  1166. * Add hours to the instance. Positive $value travels forward while
  1167. * negative $value travels into the past.
  1168. *
  1169. * @param integer $value
  1170. *
  1171. * @return self
  1172. */
  1173. public function addHours($value)
  1174. {
  1175. return $this->modify(intval($value) . ' hour');
  1176. }
  1177. /**
  1178. * Add an hour to the instance
  1179. *
  1180. * @return self
  1181. */
  1182. public function addHour()
  1183. {
  1184. return $this->addHours(1);
  1185. }
  1186. /**
  1187. * Remove an hour from the instance
  1188. *
  1189. * @return self
  1190. */
  1191. public function subHour()
  1192. {
  1193. return $this->addHours(-1);
  1194. }
  1195. /**
  1196. * Remove hours from the instance
  1197. *
  1198. * @param integer $value
  1199. *
  1200. * @return self
  1201. */
  1202. public function subHours($value)
  1203. {
  1204. return $this->addHours(-1 * $value);
  1205. }
  1206. /**
  1207. * Add minutes to the instance. Positive $value travels forward while
  1208. * negative $value travels into the past.
  1209. *
  1210. * @param integer $value
  1211. *
  1212. * @return self
  1213. */
  1214. public function addMinutes($value)
  1215. {
  1216. return $this->modify(intval($value) . ' minute');
  1217. }
  1218. /**
  1219. * Add a minute to the instance
  1220. *
  1221. * @return self
  1222. */
  1223. public function addMinute()
  1224. {
  1225. return $this->addMinutes(1);
  1226. }
  1227. /**
  1228. * Remove a minute from the instance
  1229. *
  1230. * @return self
  1231. */
  1232. public function subMinute()
  1233. {
  1234. return $this->addMinutes(-1);
  1235. }
  1236. /**
  1237. * Remove minutes from the instance
  1238. *
  1239. * @param integer $value
  1240. *
  1241. * @return self
  1242. */
  1243. public function subMinutes($value)
  1244. {
  1245. return $this->addMinutes(-1 * $value);
  1246. }
  1247. /**
  1248. * Add seconds to the instance. Positive $value travels forward while
  1249. * negative $value travels into the past.
  1250. *
  1251. * @param integer $value
  1252. *
  1253. * @return self
  1254. */
  1255. public function addSeconds($value)
  1256. {
  1257. return $this->modify(intval($value) . ' second');
  1258. }
  1259. /**
  1260. * Add a second to the instance
  1261. *
  1262. * @return self
  1263. */
  1264. public function addSecond()
  1265. {
  1266. return $this->addSeconds(1);
  1267. }
  1268. /**
  1269. * Remove a second from the instance
  1270. *
  1271. * @return self
  1272. */
  1273. public function subSecond()
  1274. {
  1275. return $this->addSeconds(-1);
  1276. }
  1277. /**
  1278. * Remove seconds from the instance
  1279. *
  1280. * @param integer $value
  1281. *
  1282. * @return self
  1283. */
  1284. public function subSeconds($value)
  1285. {
  1286. return $this->addSeconds(-1 * $value);
  1287. }
  1288. ///////////////////////////////////////////////////////////////////
  1289. /////////////////////////// DIFFERENCES ///////////////////////////
  1290. ///////////////////////////////////////////////////////////////////
  1291. /**
  1292. * Get the difference in years
  1293. *
  1294. * @param Carbon $dt
  1295. * @param boolean $abs Get the absolute of the difference
  1296. *
  1297. * @return integer
  1298. */
  1299. public function diffInYears(Carbon $dt = null, $abs = true)
  1300. {
  1301. $dt = ($dt === null) ? static::now($this->tz) : $dt;
  1302. $sign = ($abs) ? '' : '%r';
  1303. return intval($this->diff($dt)->format($sign.'%y'));
  1304. }
  1305. /**
  1306. * Get the difference in months
  1307. *
  1308. * @param Carbon $dt
  1309. * @param boolean $abs Get the absolute of the difference
  1310. *
  1311. * @return integer
  1312. */
  1313. public function diffInMonths(Carbon $dt = null, $abs = true)
  1314. {
  1315. $dt = ($dt === null) ? static::now($this->tz) : $dt;
  1316. list($sign, $years, $months) = explode(':', $this->diff($dt)->format('%r:%y:%m'));
  1317. $value = ($years * self::MONTHS_PER_YEAR) + $months;
  1318. if ($sign === '-' && !$abs) {
  1319. $value = $value * -1;
  1320. }
  1321. return $value;
  1322. }
  1323. /**
  1324. * Get the difference in days
  1325. *
  1326. * @param Carbon $dt
  1327. * @param boolean $abs Get the absolute of the difference
  1328. *
  1329. * @return integer
  1330. */
  1331. public function diffInDays(Carbon $dt = null, $abs = true)
  1332. {
  1333. $dt = ($dt === null) ? static::now($this->tz) : $dt;
  1334. $sign = ($abs) ? '' : '%r';
  1335. return intval($this->diff($dt)->format($sign.'%a'));
  1336. }
  1337. /**
  1338. * Get the difference in hours
  1339. *
  1340. * @param Carbon $dt
  1341. * @param boolean $abs Get the absolute of the difference
  1342. *
  1343. * @return integer
  1344. */
  1345. public function diffInHours(Carbon $dt = null, $abs = true)
  1346. {
  1347. $dt = ($dt === null) ? static::now($this->tz) : $dt;
  1348. return intval($this->diffInMinutes($dt, $abs) / self::MINUTES_PER_HOUR);
  1349. }
  1350. /**
  1351. * Get the difference in minutes
  1352. *
  1353. * @param Carbon $dt
  1354. * @param boolean $abs Get the absolute of the difference
  1355. *
  1356. * @return integer
  1357. */
  1358. public function diffInMinutes(Carbon $dt = null, $abs = true)
  1359. {
  1360. $dt = ($dt === null) ? static::now($this->tz) : $dt;
  1361. return intval($this->diffInSeconds($dt, $abs) / self::SECONDS_PER_MINUTE);
  1362. }
  1363. /**
  1364. * Get the difference in seconds
  1365. *
  1366. * @param Carbon $dt
  1367. * @param boolean $abs Get the absolute of the difference
  1368. *
  1369. * @return integer
  1370. */
  1371. public function diffInSeconds(Carbon $dt = null, $abs = true)
  1372. {
  1373. $dt = ($dt === null) ? static::now($this->tz) : $dt;
  1374. $value = $dt->getTimestamp() - $this->getTimestamp();
  1375. return $abs ? abs($value) : $value;
  1376. }
  1377. /**
  1378. * Get the difference in a human readable format.
  1379. *
  1380. * When comparing a value in the past to default now:
  1381. * 1 hour ago
  1382. * 5 months ago
  1383. *
  1384. * When comparing a value in the future to default now:
  1385. * 1 hour from now
  1386. * 5 months from now
  1387. *
  1388. * When comparing a value in the past to another value:
  1389. * 1 hour before
  1390. * 5 months before
  1391. *
  1392. * When comparing a value in the future to another value:
  1393. * 1 hour after
  1394. * 5 months after
  1395. *
  1396. * @param Carbon $other
  1397. *
  1398. * @return string
  1399. */
  1400. public function diffForHumans(Carbon $other = null)
  1401. {
  1402. $txt = '';
  1403. $isNow = $other === null;
  1404. if ($isNow) {
  1405. $other = self::now();
  1406. }
  1407. $isFuture = $this->gt($other);
  1408. $delta = $other->diffInSeconds($this);
  1409. // 30 days per month, 365 days per year... good enough!!
  1410. $divs = array(
  1411. 'second' => self::SECONDS_PER_MINUTE,
  1412. 'minute' => self::MINUTES_PER_HOUR,
  1413. 'hour' => self::HOURS_PER_DAY,
  1414. 'day' => 30,
  1415. 'month' => self::MONTHS_PER_YEAR
  1416. );
  1417. $unit = 'year';
  1418. foreach ($divs as $divUnit => $divValue) {
  1419. if ($delta < $divValue) {
  1420. $unit = $divUnit;
  1421. break;
  1422. }
  1423. $delta = floor($delta / $divValue);
  1424. }
  1425. if ($delta == 0) {
  1426. $delta = 1;
  1427. }
  1428. $txt = $delta . ' ' . $unit;
  1429. $txt .= $delta == 1 ? '' : 's';
  1430. if ($isNow) {
  1431. if ($isFuture) {
  1432. return $txt . ' from now';
  1433. }
  1434. return $txt . ' ago';
  1435. }
  1436. if ($isFuture) {
  1437. return $txt . ' after';
  1438. }
  1439. return $txt . ' before';
  1440. }
  1441. ///////////////////////////////////////////////////////////////////
  1442. //////////////////////////// MODIFIERS ////////////////////////////
  1443. ///////////////////////////////////////////////////////////////////
  1444. /**
  1445. * Resets the time to 00:00:00
  1446. *
  1447. * @return self
  1448. */
  1449. public function startOfDay()
  1450. {
  1451. return $this->hour(0)->minute(0)->second(0);
  1452. }
  1453. /**
  1454. * Resets the time to 23:59:59
  1455. *
  1456. * @return self
  1457. */
  1458. public function endOfDay()
  1459. {
  1460. return $this->hour(23)->minute(59)->second(59);
  1461. }
  1462. /**
  1463. * Resets the date to the first day of the month and the time to 00:00:00
  1464. *
  1465. * @return self
  1466. */
  1467. public function startOfMonth()
  1468. {
  1469. return $this->startOfDay()->day(1);
  1470. }
  1471. /**
  1472. * Resets the date to end of the month and time to 23:59:59
  1473. *
  1474. * @return self
  1475. */
  1476. public function endOfMonth()
  1477. {
  1478. return $this->day($this->daysInMonth)->endOfDay();
  1479. }
  1480. /**
  1481. * Resets the date to the first day of the ISO-8601 week (Monday) and the time to 00:00:00
  1482. *
  1483. * @return self
  1484. */
  1485. public function startOfWeek()
  1486. {
  1487. return $this->setISODate($this->year, $this->weekOfYear, 1)->startOfDay();
  1488. }
  1489. /**
  1490. * Resets the date to end of the ISO-8601 week (Sunday) and time to 23:59:59
  1491. *
  1492. * @return self
  1493. */
  1494. public function endOfWeek()
  1495. {
  1496. return $this->setISODate($this->year, $this->weekOfYear, 7)->endOfDay();
  1497. }
  1498. /**
  1499. * Modify to the next occurance of a given day of the week.
  1500. * If no dayOfWeek is provided, modify to the next occurance
  1501. * of the current day of the week. Use the supplied consts
  1502. * to indicate the desired dayOfWeek, ex. static::MONDAY.
  1503. *
  1504. * @param int $dayOfWeek
  1505. *
  1506. * @return mixed
  1507. */
  1508. public function next($dayOfWeek = null)
  1509. {
  1510. $this->startOfDay();
  1511. if ($dayOfWeek === null) {
  1512. $dayOfWeek = $this->dayOfWeek;
  1513. }
  1514. return $this->modify('next ' . self::$days[$dayOfWeek]);
  1515. }
  1516. /**
  1517. * Modify to the previous occurance of a given day of the week.
  1518. * If no dayOfWeek is provided, modify to the previous occurance
  1519. * of the current day of the week. Use the supplied consts
  1520. * to indicate the desired dayOfWeek, ex. static::MONDAY.
  1521. *
  1522. * @param int $dayOfWeek
  1523. *
  1524. * @return mixed
  1525. */
  1526. public function previous($dayOfWeek = null)
  1527. {
  1528. $this->startOfDay();
  1529. if ($dayOfWeek === null) {
  1530. $dayOfWeek = $this->dayOfWeek;
  1531. }
  1532. return $this->modify('last ' . self::$days[$dayOfWeek]);
  1533. }
  1534. /**
  1535. * Modify to the first occurance of a given day of the week
  1536. * in the current month. If no dayOfWeek is provided, modify to the
  1537. * first day of the current month. Use the supplied consts
  1538. * to indicate the desired dayOfWeek, ex. static::MONDAY.
  1539. *
  1540. * @param int $dayOfWeek
  1541. *
  1542. * @return mixed
  1543. */
  1544. public function firstOfMonth($dayOfWeek = null)
  1545. {
  1546. $this->startOfDay();
  1547. if ($dayOfWeek === null) {
  1548. return $this->day(1);
  1549. }
  1550. return $this->modify('first ' . self::$days[$dayOfWeek] . ' of ' . $this->format('F') . ' ' . $this->year);
  1551. }
  1552. /**
  1553. * Modify to the last occurance of a given day of the week
  1554. * in the current month. If no dayOfWeek is provided, modify to the
  1555. * last day of the current month. Use the supplied consts
  1556. * to indicate the desired dayOfWeek, ex. static::MONDAY.
  1557. *
  1558. * @param int $dayOfWeek
  1559. *
  1560. * @return mixed
  1561. */
  1562. public function lastOfMonth($dayOfWeek = null)
  1563. {
  1564. $this->startOfDay();
  1565. if ($dayOfWeek === null) {
  1566. return $this->day($this->daysInMonth);
  1567. }
  1568. return $this->modify('last ' . self::$days[$dayOfWeek] . ' of ' . $this->format('F') . ' ' . $this->year);
  1569. }
  1570. /**
  1571. * Modify to the given occurance of a given day of the week
  1572. * in the current month. If the calculated occurance is outside the scope
  1573. * of the current month, then return false and no modifications are made.
  1574. * Use the supplied consts to indicate the desired dayOfWeek, ex. static::MONDAY.
  1575. *
  1576. * @param int $nth
  1577. * @param int $dayOfWeek
  1578. *
  1579. * @return mixed
  1580. */
  1581. public function nthOfMonth($nth, $dayOfWeek)
  1582. {
  1583. $dt = $this->copy();
  1584. $dt->firstOfMonth();
  1585. $month = $dt->month;
  1586. $year = $dt->year;
  1587. $dt->modify('+' . $nth . ' ' . self::$days[$dayOfWeek]);
  1588. if ($month !== $dt->month || $year !== $dt->year) return false;
  1589. return $this->modify($dt);
  1590. }
  1591. /**
  1592. * Modify to the first occurance of a given day of the week
  1593. * in the current quarter. If no dayOfWeek is provided, modify to the
  1594. * first day of the current quarter. Use the supplied consts
  1595. * to indicate the desired dayOfWeek, ex. static::MONDAY.
  1596. *
  1597. * @param int $dayOfWeek
  1598. *
  1599. * @return mixed
  1600. */
  1601. public function firstOfQuarter($dayOfWeek = null)
  1602. {
  1603. $this->month(($this->quarter * 3) - 2);
  1604. return $this->firstOfMonth($dayOfWeek);
  1605. }
  1606. /**
  1607. * Modify to the last occurance of a given day of the week
  1608. * in the current quarter. If no dayOfWeek is provided, modify to the
  1609. * last day of the current quarter. Use the supplied consts
  1610. * to indicate the desired dayOfWeek, ex. static::MONDAY.
  1611. *
  1612. * @param int $dayOfWeek
  1613. *
  1614. * @return mixed
  1615. */
  1616. public function lastOfQuarter($dayOfWeek = null)
  1617. {
  1618. $this->month(($this->quarter * 3));
  1619. return $this->lastOfMonth($dayOfWeek);
  1620. }
  1621. /**
  1622. * Modify to the given occurance of a given day of the week
  1623. * in the current quarter. If the calculated occurance is outside the scope
  1624. * of the current quarter, then return false and no modifications are made.
  1625. * Use the supplied consts to indicate the desired dayOfWeek, ex. static::MONDAY.
  1626. *
  1627. * @param int $nth
  1628. * @param int $dayOfWeek
  1629. *
  1630. * @return mixed
  1631. */
  1632. public function nthOfQuarter($nth, $dayOfWeek)
  1633. {
  1634. $dt = $this->copy();
  1635. $dt->month(($this->quarter * 3));
  1636. $last_month = $dt->month;
  1637. $year = $dt->year;
  1638. $dt->firstOfQuarter();
  1639. $dt->modify('+' . $nth . ' ' . self::$days[$dayOfWeek]);
  1640. if ($last_month < $dt->month || $year !== $dt->year) return false;
  1641. return $this->modify($dt);
  1642. }
  1643. /**
  1644. * Modify to the first occurance of a given day of the week
  1645. * in the current year. If no dayOfWeek is provided, modify to the
  1646. * first day of the current year. Use the supplied consts
  1647. * to indicate the desired dayOfWeek, ex. static::MONDAY.
  1648. *
  1649. * @param int $dayOfWeek
  1650. *
  1651. * @return mixed
  1652. */
  1653. public function firstOfYear($dayOfWeek = null)
  1654. {
  1655. $this->month(1);
  1656. return $this->firstOfMonth($dayOfWeek);
  1657. }
  1658. /**
  1659. * Modify to the last occurance of a given day of the week
  1660. * in the current year. If no dayOfWeek is provided, modify to the
  1661. * last day of the current year. Use the supplied consts
  1662. * to indicate the desired dayOfWeek, ex. static::MONDAY.
  1663. *
  1664. * @param int $dayOfWeek
  1665. *
  1666. * @return mixed
  1667. */
  1668. public function lastOfYear($dayOfWeek = null)
  1669. {
  1670. $this->month(12);
  1671. return $this->lastOfMonth($dayOfWeek);
  1672. }
  1673. /**
  1674. * Modify to the given occurance of a given day of the week
  1675. * in the current year. If the calculated occurance is outside the scope
  1676. * of the current year, then return false and no modifications are made.
  1677. * Use the supplied consts to indicate the desired dayOfWeek, ex. static::MONDAY.
  1678. *
  1679. * @param int $nth
  1680. * @param int $dayOfWeek
  1681. *
  1682. * @return mixed
  1683. */
  1684. public function nthOfYear($nth, $dayOfWeek)
  1685. {
  1686. $dt = $this->copy();
  1687. $year = $dt->year;
  1688. $dt->firstOfYear();
  1689. $dt->modify('+' . $nth . ' ' . self::$days[$dayOfWeek]);
  1690. if ($year !== $dt->year) return false;
  1691. return $this->modify($dt);
  1692. }
  1693. }