blob: 7ba622567c04dadc8f97bf5981ed34780074e79b [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?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 */
11namespace Carbon\Traits;
12
13use Carbon\Carbon;
14use Carbon\CarbonImmutable;
15use Carbon\CarbonInterface;
16use Carbon\CarbonInterval;
17use Carbon\CarbonPeriod;
18use Carbon\Exceptions\UnitException;
19use Closure;
20use DateTime;
21use DateTimeImmutable;
22use ReturnTypeWillChange;
23
24/**
25 * Trait Converter.
26 *
27 * Change date into different string formats and types and
28 * handle the string cast.
29 *
30 * Depends on the following methods:
31 *
32 * @method static copy()
33 */
34trait Converter
35{
36 /**
37 * Format to use for __toString method when type juggling occurs.
38 *
39 * @var string|Closure|null
40 */
41 protected static $toStringFormat;
42
43 /**
44 * Reset the format used to the default when type juggling a Carbon instance to a string
45 *
46 * @return void
47 */
48 public static function resetToStringFormat()
49 {
50 static::setToStringFormat(null);
51 }
52
53 /**
54 * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
55 * You should rather let Carbon object being casted to string with DEFAULT_TO_STRING_FORMAT, and
56 * use other method or custom format passed to format() method if you need to dump an other string
57 * format.
58 *
59 * Set the default format used when type juggling a Carbon instance to a string
60 *
61 * @param string|Closure|null $format
62 *
63 * @return void
64 */
65 public static function setToStringFormat($format)
66 {
67 static::$toStringFormat = $format;
68 }
69
70 /**
71 * Returns the formatted date string on success or FALSE on failure.
72 *
73 * @see https://php.net/manual/en/datetime.format.php
74 *
75 * @param string $format
76 *
77 * @return string
78 */
79 #[ReturnTypeWillChange]
80 public function format($format)
81 {
82 $function = $this->localFormatFunction ?: static::$formatFunction;
83
84 if (!$function) {
85 return $this->rawFormat($format);
86 }
87
88 if (\is_string($function) && method_exists($this, $function)) {
89 $function = [$this, $function];
90 }
91
92 return $function(...\func_get_args());
93 }
94
95 /**
96 * @see https://php.net/manual/en/datetime.format.php
97 *
98 * @param string $format
99 *
100 * @return string
101 */
102 public function rawFormat($format)
103 {
104 return parent::format($format);
105 }
106
107 /**
108 * Format the instance as a string using the set format
109 *
110 * @example
111 * ```
112 * echo Carbon::now(); // Carbon instances can be casted to string
113 * ```
114 *
115 * @return string
116 */
117 public function __toString()
118 {
119 $format = $this->localToStringFormat ?? static::$toStringFormat;
120
121 return $format instanceof Closure
122 ? $format($this)
123 : $this->rawFormat($format ?: (
124 \defined('static::DEFAULT_TO_STRING_FORMAT')
125 ? static::DEFAULT_TO_STRING_FORMAT
126 : CarbonInterface::DEFAULT_TO_STRING_FORMAT
127 ));
128 }
129
130 /**
131 * Format the instance as date
132 *
133 * @example
134 * ```
135 * echo Carbon::now()->toDateString();
136 * ```
137 *
138 * @return string
139 */
140 public function toDateString()
141 {
142 return $this->rawFormat('Y-m-d');
143 }
144
145 /**
146 * Format the instance as a readable date
147 *
148 * @example
149 * ```
150 * echo Carbon::now()->toFormattedDateString();
151 * ```
152 *
153 * @return string
154 */
155 public function toFormattedDateString()
156 {
157 return $this->rawFormat('M j, Y');
158 }
159
160 /**
161 * Format the instance as time
162 *
163 * @example
164 * ```
165 * echo Carbon::now()->toTimeString();
166 * ```
167 *
168 * @param string $unitPrecision
169 *
170 * @return string
171 */
172 public function toTimeString($unitPrecision = 'second')
173 {
174 return $this->rawFormat(static::getTimeFormatByPrecision($unitPrecision));
175 }
176
177 /**
178 * Format the instance as date and time
179 *
180 * @example
181 * ```
182 * echo Carbon::now()->toDateTimeString();
183 * ```
184 *
185 * @param string $unitPrecision
186 *
187 * @return string
188 */
189 public function toDateTimeString($unitPrecision = 'second')
190 {
191 return $this->rawFormat('Y-m-d '.static::getTimeFormatByPrecision($unitPrecision));
192 }
193
194 /**
195 * Return a format from H:i to H:i:s.u according to given unit precision.
196 *
197 * @param string $unitPrecision "minute", "second", "millisecond" or "microsecond"
198 *
199 * @return string
200 */
201 public static function getTimeFormatByPrecision($unitPrecision)
202 {
203 switch (static::singularUnit($unitPrecision)) {
204 case 'minute':
205 return 'H:i';
206 case 'second':
207 return 'H:i:s';
208 case 'm':
209 case 'millisecond':
210 return 'H:i:s.v';
211 case 'µ':
212 case 'microsecond':
213 return 'H:i:s.u';
214 }
215
216 throw new UnitException('Precision unit expected among: minute, second, millisecond and microsecond.');
217 }
218
219 /**
220 * Format the instance as date and time T-separated with no timezone
221 *
222 * @example
223 * ```
224 * echo Carbon::now()->toDateTimeLocalString();
225 * echo "\n";
226 * echo Carbon::now()->toDateTimeLocalString('minute'); // You can specify precision among: minute, second, millisecond and microsecond
227 * ```
228 *
229 * @param string $unitPrecision
230 *
231 * @return string
232 */
233 public function toDateTimeLocalString($unitPrecision = 'second')
234 {
235 return $this->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision));
236 }
237
238 /**
239 * Format the instance with day, date and time
240 *
241 * @example
242 * ```
243 * echo Carbon::now()->toDayDateTimeString();
244 * ```
245 *
246 * @return string
247 */
248 public function toDayDateTimeString()
249 {
250 return $this->rawFormat('D, M j, Y g:i A');
251 }
252
253 /**
254 * Format the instance as ATOM
255 *
256 * @example
257 * ```
258 * echo Carbon::now()->toAtomString();
259 * ```
260 *
261 * @return string
262 */
263 public function toAtomString()
264 {
265 return $this->rawFormat(DateTime::ATOM);
266 }
267
268 /**
269 * Format the instance as COOKIE
270 *
271 * @example
272 * ```
273 * echo Carbon::now()->toCookieString();
274 * ```
275 *
276 * @return string
277 */
278 public function toCookieString()
279 {
280 return $this->rawFormat(DateTime::COOKIE);
281 }
282
283 /**
284 * Format the instance as ISO8601
285 *
286 * @example
287 * ```
288 * echo Carbon::now()->toIso8601String();
289 * ```
290 *
291 * @return string
292 */
293 public function toIso8601String()
294 {
295 return $this->toAtomString();
296 }
297
298 /**
299 * Format the instance as RFC822
300 *
301 * @example
302 * ```
303 * echo Carbon::now()->toRfc822String();
304 * ```
305 *
306 * @return string
307 */
308 public function toRfc822String()
309 {
310 return $this->rawFormat(DateTime::RFC822);
311 }
312
313 /**
314 * Convert the instance to UTC and return as Zulu ISO8601
315 *
316 * @example
317 * ```
318 * echo Carbon::now()->toIso8601ZuluString();
319 * ```
320 *
321 * @param string $unitPrecision
322 *
323 * @return string
324 */
325 public function toIso8601ZuluString($unitPrecision = 'second')
326 {
327 return $this->avoidMutation()
328 ->utc()
329 ->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision).'\Z');
330 }
331
332 /**
333 * Format the instance as RFC850
334 *
335 * @example
336 * ```
337 * echo Carbon::now()->toRfc850String();
338 * ```
339 *
340 * @return string
341 */
342 public function toRfc850String()
343 {
344 return $this->rawFormat(DateTime::RFC850);
345 }
346
347 /**
348 * Format the instance as RFC1036
349 *
350 * @example
351 * ```
352 * echo Carbon::now()->toRfc1036String();
353 * ```
354 *
355 * @return string
356 */
357 public function toRfc1036String()
358 {
359 return $this->rawFormat(DateTime::RFC1036);
360 }
361
362 /**
363 * Format the instance as RFC1123
364 *
365 * @example
366 * ```
367 * echo Carbon::now()->toRfc1123String();
368 * ```
369 *
370 * @return string
371 */
372 public function toRfc1123String()
373 {
374 return $this->rawFormat(DateTime::RFC1123);
375 }
376
377 /**
378 * Format the instance as RFC2822
379 *
380 * @example
381 * ```
382 * echo Carbon::now()->toRfc2822String();
383 * ```
384 *
385 * @return string
386 */
387 public function toRfc2822String()
388 {
389 return $this->rawFormat(DateTime::RFC2822);
390 }
391
392 /**
393 * Format the instance as RFC3339
394 *
395 * @param bool $extended
396 *
397 * @example
398 * ```
399 * echo Carbon::now()->toRfc3339String() . "\n";
400 * echo Carbon::now()->toRfc3339String(true) . "\n";
401 * ```
402 *
403 * @return string
404 */
405 public function toRfc3339String($extended = false)
406 {
407 $format = DateTime::RFC3339;
408 if ($extended) {
409 $format = DateTime::RFC3339_EXTENDED;
410 }
411
412 return $this->rawFormat($format);
413 }
414
415 /**
416 * Format the instance as RSS
417 *
418 * @example
419 * ```
420 * echo Carbon::now()->toRssString();
421 * ```
422 *
423 * @return string
424 */
425 public function toRssString()
426 {
427 return $this->rawFormat(DateTime::RSS);
428 }
429
430 /**
431 * Format the instance as W3C
432 *
433 * @example
434 * ```
435 * echo Carbon::now()->toW3cString();
436 * ```
437 *
438 * @return string
439 */
440 public function toW3cString()
441 {
442 return $this->rawFormat(DateTime::W3C);
443 }
444
445 /**
446 * Format the instance as RFC7231
447 *
448 * @example
449 * ```
450 * echo Carbon::now()->toRfc7231String();
451 * ```
452 *
453 * @return string
454 */
455 public function toRfc7231String()
456 {
457 return $this->avoidMutation()
458 ->setTimezone('GMT')
459 ->rawFormat(\defined('static::RFC7231_FORMAT') ? static::RFC7231_FORMAT : CarbonInterface::RFC7231_FORMAT);
460 }
461
462 /**
463 * Get default array representation.
464 *
465 * @example
466 * ```
467 * var_dump(Carbon::now()->toArray());
468 * ```
469 *
470 * @return array
471 */
472 public function toArray()
473 {
474 return [
475 'year' => $this->year,
476 'month' => $this->month,
477 'day' => $this->day,
478 'dayOfWeek' => $this->dayOfWeek,
479 'dayOfYear' => $this->dayOfYear,
480 'hour' => $this->hour,
481 'minute' => $this->minute,
482 'second' => $this->second,
483 'micro' => $this->micro,
484 'timestamp' => $this->timestamp,
485 'formatted' => $this->rawFormat(\defined('static::DEFAULT_TO_STRING_FORMAT') ? static::DEFAULT_TO_STRING_FORMAT : CarbonInterface::DEFAULT_TO_STRING_FORMAT),
486 'timezone' => $this->timezone,
487 ];
488 }
489
490 /**
491 * Get default object representation.
492 *
493 * @example
494 * ```
495 * var_dump(Carbon::now()->toObject());
496 * ```
497 *
498 * @return object
499 */
500 public function toObject()
501 {
502 return (object) $this->toArray();
503 }
504
505 /**
506 * Returns english human readable complete date string.
507 *
508 * @example
509 * ```
510 * echo Carbon::now()->toString();
511 * ```
512 *
513 * @return string
514 */
515 public function toString()
516 {
517 return $this->avoidMutation()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
518 }
519
520 /**
521 * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z, if $keepOffset truthy, offset will be kept:
522 * 1977-04-22T01:00:00-05:00).
523 *
524 * @example
525 * ```
526 * echo Carbon::now('America/Toronto')->toISOString() . "\n";
527 * echo Carbon::now('America/Toronto')->toISOString(true) . "\n";
528 * ```
529 *
530 * @param bool $keepOffset Pass true to keep the date offset. Else forced to UTC.
531 *
532 * @return null|string
533 */
534 public function toISOString($keepOffset = false)
535 {
536 if (!$this->isValid()) {
537 return null;
538 }
539
540 $yearFormat = $this->year < 0 || $this->year > 9999 ? 'YYYYYY' : 'YYYY';
541 $tzFormat = $keepOffset ? 'Z' : '[Z]';
542 $date = $keepOffset ? $this : $this->avoidMutation()->utc();
543
544 return $date->isoFormat("$yearFormat-MM-DD[T]HH:mm:ss.SSSSSS$tzFormat");
545 }
546
547 /**
548 * Return the ISO-8601 string (ex: 1977-04-22T06:00:00Z) with UTC timezone.
549 *
550 * @example
551 * ```
552 * echo Carbon::now('America/Toronto')->toJSON();
553 * ```
554 *
555 * @return null|string
556 */
557 public function toJSON()
558 {
559 return $this->toISOString();
560 }
561
562 /**
563 * Return native DateTime PHP object matching the current instance.
564 *
565 * @example
566 * ```
567 * var_dump(Carbon::now()->toDateTime());
568 * ```
569 *
570 * @return DateTime
571 */
572 public function toDateTime()
573 {
574 return new DateTime($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone());
575 }
576
577 /**
578 * Return native toDateTimeImmutable PHP object matching the current instance.
579 *
580 * @example
581 * ```
582 * var_dump(Carbon::now()->toDateTimeImmutable());
583 * ```
584 *
585 * @return DateTimeImmutable
586 */
587 public function toDateTimeImmutable()
588 {
589 return new DateTimeImmutable($this->rawFormat('Y-m-d H:i:s.u'), $this->getTimezone());
590 }
591
592 /**
593 * @alias toDateTime
594 *
595 * Return native DateTime PHP object matching the current instance.
596 *
597 * @example
598 * ```
599 * var_dump(Carbon::now()->toDate());
600 * ```
601 *
602 * @return DateTime
603 */
604 public function toDate()
605 {
606 return $this->toDateTime();
607 }
608
609 /**
610 * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
611 *
612 * @param \DateTimeInterface|Carbon|CarbonImmutable|int|null $end period end date or recurrences count if int
613 * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit
614 * @param string|null $unit if specified, $interval must be an integer
615 *
616 * @return CarbonPeriod
617 */
618 public function toPeriod($end = null, $interval = null, $unit = null)
619 {
620 if ($unit) {
621 $interval = CarbonInterval::make("$interval ".static::pluralUnit($unit));
622 }
623
624 $period = (new CarbonPeriod())->setDateClass(static::class)->setStartDate($this);
625
626 if ($interval) {
627 $period->setDateInterval($interval);
628 }
629
630 if (\is_int($end) || \is_string($end) && ctype_digit($end)) {
631 $period->setRecurrences($end);
632 } elseif ($end) {
633 $period->setEndDate($end);
634 }
635
636 return $period;
637 }
638
639 /**
640 * Create a iterable CarbonPeriod object from current date to a given end date (and optional interval).
641 *
642 * @param \DateTimeInterface|Carbon|CarbonImmutable|null $end period end date
643 * @param int|\DateInterval|string|null $interval period default interval or number of the given $unit
644 * @param string|null $unit if specified, $interval must be an integer
645 *
646 * @return CarbonPeriod
647 */
648 public function range($end = null, $interval = null, $unit = null)
649 {
650 return $this->toPeriod($end, $interval, $unit);
651 }
652}