| 148 |
lars |
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 |
*/
|
|
|
11 |
|
|
|
12 |
namespace Carbon\Traits;
|
|
|
13 |
|
|
|
14 |
use Carbon\CarbonInterface;
|
|
|
15 |
use DateTimeInterface;
|
|
|
16 |
use Throwable;
|
|
|
17 |
|
|
|
18 |
/**
|
|
|
19 |
* Trait Options.
|
|
|
20 |
*
|
|
|
21 |
* Embed base methods to change settings of Carbon classes.
|
|
|
22 |
*
|
|
|
23 |
* Depends on the following methods:
|
|
|
24 |
*
|
|
|
25 |
* @method \Carbon\Carbon|\Carbon\CarbonImmutable shiftTimezone($timezone) Set the timezone
|
|
|
26 |
*/
|
|
|
27 |
trait Options
|
|
|
28 |
{
|
|
|
29 |
use Localization;
|
|
|
30 |
|
|
|
31 |
/**
|
|
|
32 |
* Customizable PHP_INT_SIZE override.
|
|
|
33 |
*
|
|
|
34 |
* @var int
|
|
|
35 |
*/
|
|
|
36 |
public static $PHPIntSize = PHP_INT_SIZE;
|
|
|
37 |
|
|
|
38 |
/**
|
|
|
39 |
* First day of week.
|
|
|
40 |
*
|
|
|
41 |
* @var int|string
|
|
|
42 |
*/
|
|
|
43 |
protected static $weekStartsAt = CarbonInterface::MONDAY;
|
|
|
44 |
|
|
|
45 |
/**
|
|
|
46 |
* Last day of week.
|
|
|
47 |
*
|
|
|
48 |
* @var int|string
|
|
|
49 |
*/
|
|
|
50 |
protected static $weekEndsAt = CarbonInterface::SUNDAY;
|
|
|
51 |
|
|
|
52 |
/**
|
|
|
53 |
* Days of weekend.
|
|
|
54 |
*
|
|
|
55 |
* @var array
|
|
|
56 |
*/
|
|
|
57 |
protected static $weekendDays = [
|
|
|
58 |
CarbonInterface::SATURDAY,
|
|
|
59 |
CarbonInterface::SUNDAY,
|
|
|
60 |
];
|
|
|
61 |
|
|
|
62 |
/**
|
|
|
63 |
* Format regex patterns.
|
|
|
64 |
*
|
|
|
65 |
* @var array<string, string>
|
|
|
66 |
*/
|
|
|
67 |
protected static $regexFormats = [
|
|
|
68 |
'd' => '(3[01]|[12][0-9]|0[1-9])',
|
|
|
69 |
'D' => '(Sun|Mon|Tue|Wed|Thu|Fri|Sat)',
|
|
|
70 |
'j' => '([123][0-9]|[1-9])',
|
|
|
71 |
'l' => '([a-zA-Z]{2,})',
|
|
|
72 |
'N' => '([1-7])',
|
|
|
73 |
'S' => '(st|nd|rd|th)',
|
|
|
74 |
'w' => '([0-6])',
|
|
|
75 |
'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])',
|
|
|
76 |
'W' => '(5[012]|[1-4][0-9]|0?[1-9])',
|
|
|
77 |
'F' => '([a-zA-Z]{2,})',
|
|
|
78 |
'm' => '(1[012]|0[1-9])',
|
|
|
79 |
'M' => '([a-zA-Z]{3})',
|
|
|
80 |
'n' => '(1[012]|[1-9])',
|
|
|
81 |
't' => '(2[89]|3[01])',
|
|
|
82 |
'L' => '(0|1)',
|
|
|
83 |
'o' => '([1-9][0-9]{0,4})',
|
|
|
84 |
'Y' => '([1-9]?[0-9]{4})',
|
|
|
85 |
'y' => '([0-9]{2})',
|
|
|
86 |
'a' => '(am|pm)',
|
|
|
87 |
'A' => '(AM|PM)',
|
|
|
88 |
'B' => '([0-9]{3})',
|
|
|
89 |
'g' => '(1[012]|[1-9])',
|
|
|
90 |
'G' => '(2[0-3]|1?[0-9])',
|
|
|
91 |
'h' => '(1[012]|0[1-9])',
|
|
|
92 |
'H' => '(2[0-3]|[01][0-9])',
|
|
|
93 |
'i' => '([0-5][0-9])',
|
|
|
94 |
's' => '([0-5][0-9])',
|
|
|
95 |
'u' => '([0-9]{1,6})',
|
|
|
96 |
'v' => '([0-9]{1,3})',
|
|
|
97 |
'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\\/[a-zA-Z]*)',
|
|
|
98 |
'I' => '(0|1)',
|
|
|
99 |
'O' => '([+-](1[012]|0[0-9])[0134][05])',
|
|
|
100 |
'P' => '([+-](1[012]|0[0-9]):[0134][05])',
|
|
|
101 |
'p' => '(Z|[+-](1[012]|0[0-9]):[0134][05])',
|
|
|
102 |
'T' => '([a-zA-Z]{1,5})',
|
|
|
103 |
'Z' => '(-?[1-5]?[0-9]{1,4})',
|
|
|
104 |
'U' => '([0-9]*)',
|
|
|
105 |
|
|
|
106 |
// The formats below are combinations of the above formats.
|
|
|
107 |
'c' => '(([1-9]?[0-9]{4})-(1[012]|0[1-9])-(3[01]|[12][0-9]|0[1-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])[+-](1[012]|0[0-9]):([0134][05]))', // Y-m-dTH:i:sP
|
|
|
108 |
'r' => '(([a-zA-Z]{3}), ([123][0-9]|0[1-9]) ([a-zA-Z]{3}) ([1-9]?[0-9]{4}) (2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9]) [+-](1[012]|0[0-9])([0134][05]))', // D, d M Y H:i:s O
|
|
|
109 |
];
|
|
|
110 |
|
|
|
111 |
/**
|
|
|
112 |
* Format modifiers (such as available in createFromFormat) regex patterns.
|
|
|
113 |
*
|
|
|
114 |
* @var array
|
|
|
115 |
*/
|
|
|
116 |
protected static $regexFormatModifiers = [
|
|
|
117 |
'*' => '.+',
|
|
|
118 |
' ' => '[ ]',
|
|
|
119 |
'#' => '[;:\\/.,()-]',
|
|
|
120 |
'?' => '([^a]|[a])',
|
|
|
121 |
'!' => '',
|
|
|
122 |
'|' => '',
|
|
|
123 |
'+' => '',
|
|
|
124 |
];
|
|
|
125 |
|
|
|
126 |
/**
|
|
|
127 |
* Indicates if months should be calculated with overflow.
|
|
|
128 |
* Global setting.
|
|
|
129 |
*
|
|
|
130 |
* @var bool
|
|
|
131 |
*/
|
|
|
132 |
protected static $monthsOverflow = true;
|
|
|
133 |
|
|
|
134 |
/**
|
|
|
135 |
* Indicates if years should be calculated with overflow.
|
|
|
136 |
* Global setting.
|
|
|
137 |
*
|
|
|
138 |
* @var bool
|
|
|
139 |
*/
|
|
|
140 |
protected static $yearsOverflow = true;
|
|
|
141 |
|
|
|
142 |
/**
|
|
|
143 |
* Indicates if the strict mode is in use.
|
|
|
144 |
* Global setting.
|
|
|
145 |
*
|
|
|
146 |
* @var bool
|
|
|
147 |
*/
|
|
|
148 |
protected static $strictModeEnabled = true;
|
|
|
149 |
|
|
|
150 |
/**
|
|
|
151 |
* Function to call instead of format.
|
|
|
152 |
*
|
|
|
153 |
* @var string|callable|null
|
|
|
154 |
*/
|
|
|
155 |
protected static $formatFunction;
|
|
|
156 |
|
|
|
157 |
/**
|
|
|
158 |
* Function to call instead of createFromFormat.
|
|
|
159 |
*
|
|
|
160 |
* @var string|callable|null
|
|
|
161 |
*/
|
|
|
162 |
protected static $createFromFormatFunction;
|
|
|
163 |
|
|
|
164 |
/**
|
|
|
165 |
* Function to call instead of parse.
|
|
|
166 |
*
|
|
|
167 |
* @var string|callable|null
|
|
|
168 |
*/
|
|
|
169 |
protected static $parseFunction;
|
|
|
170 |
|
|
|
171 |
/**
|
|
|
172 |
* Indicates if months should be calculated with overflow.
|
|
|
173 |
* Specific setting.
|
|
|
174 |
*
|
|
|
175 |
* @var bool|null
|
|
|
176 |
*/
|
|
|
177 |
protected $localMonthsOverflow;
|
|
|
178 |
|
|
|
179 |
/**
|
|
|
180 |
* Indicates if years should be calculated with overflow.
|
|
|
181 |
* Specific setting.
|
|
|
182 |
*
|
|
|
183 |
* @var bool|null
|
|
|
184 |
*/
|
|
|
185 |
protected $localYearsOverflow;
|
|
|
186 |
|
|
|
187 |
/**
|
|
|
188 |
* Indicates if the strict mode is in use.
|
|
|
189 |
* Specific setting.
|
|
|
190 |
*
|
|
|
191 |
* @var bool|null
|
|
|
192 |
*/
|
|
|
193 |
protected $localStrictModeEnabled;
|
|
|
194 |
|
|
|
195 |
/**
|
|
|
196 |
* Options for diffForHumans and forHumans methods.
|
|
|
197 |
*
|
|
|
198 |
* @var bool|null
|
|
|
199 |
*/
|
|
|
200 |
protected $localHumanDiffOptions;
|
|
|
201 |
|
|
|
202 |
/**
|
|
|
203 |
* Format to use on string cast.
|
|
|
204 |
*
|
|
|
205 |
* @var string|null
|
|
|
206 |
*/
|
|
|
207 |
protected $localToStringFormat;
|
|
|
208 |
|
|
|
209 |
/**
|
|
|
210 |
* Format to use on JSON serialization.
|
|
|
211 |
*
|
|
|
212 |
* @var string|null
|
|
|
213 |
*/
|
|
|
214 |
protected $localSerializer;
|
|
|
215 |
|
|
|
216 |
/**
|
|
|
217 |
* Instance-specific macros.
|
|
|
218 |
*
|
|
|
219 |
* @var array|null
|
|
|
220 |
*/
|
|
|
221 |
protected $localMacros;
|
|
|
222 |
|
|
|
223 |
/**
|
|
|
224 |
* Instance-specific generic macros.
|
|
|
225 |
*
|
|
|
226 |
* @var array|null
|
|
|
227 |
*/
|
|
|
228 |
protected $localGenericMacros;
|
|
|
229 |
|
|
|
230 |
/**
|
|
|
231 |
* Function to call instead of format.
|
|
|
232 |
*
|
|
|
233 |
* @var string|callable|null
|
|
|
234 |
*/
|
|
|
235 |
protected $localFormatFunction;
|
|
|
236 |
|
|
|
237 |
/**
|
|
|
238 |
* @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
|
|
|
239 |
* You should rather use the ->settings() method.
|
|
|
240 |
* @see settings
|
|
|
241 |
*
|
|
|
242 |
* Enable the strict mode (or disable with passing false).
|
|
|
243 |
*
|
|
|
244 |
* @param bool $strictModeEnabled
|
|
|
245 |
*/
|
|
|
246 |
public static function useStrictMode($strictModeEnabled = true)
|
|
|
247 |
{
|
|
|
248 |
static::$strictModeEnabled = $strictModeEnabled;
|
|
|
249 |
}
|
|
|
250 |
|
|
|
251 |
/**
|
|
|
252 |
* Returns true if the strict mode is globally in use, false else.
|
|
|
253 |
* (It can be overridden in specific instances.)
|
|
|
254 |
*
|
|
|
255 |
* @return bool
|
|
|
256 |
*/
|
|
|
257 |
public static function isStrictModeEnabled()
|
|
|
258 |
{
|
|
|
259 |
return static::$strictModeEnabled;
|
|
|
260 |
}
|
|
|
261 |
|
|
|
262 |
/**
|
|
|
263 |
* @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
|
|
|
264 |
* You should rather use the ->settings() method.
|
|
|
265 |
* Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
|
|
|
266 |
* are available for quarters, years, decade, centuries, millennia (singular and plural forms).
|
|
|
267 |
* @see settings
|
|
|
268 |
*
|
|
|
269 |
* Indicates if months should be calculated with overflow.
|
|
|
270 |
*
|
|
|
271 |
* @param bool $monthsOverflow
|
|
|
272 |
*
|
|
|
273 |
* @return void
|
|
|
274 |
*/
|
|
|
275 |
public static function useMonthsOverflow($monthsOverflow = true)
|
|
|
276 |
{
|
|
|
277 |
static::$monthsOverflow = $monthsOverflow;
|
|
|
278 |
}
|
|
|
279 |
|
|
|
280 |
/**
|
|
|
281 |
* @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
|
|
|
282 |
* You should rather use the ->settings() method.
|
|
|
283 |
* Or you can use method variants: addMonthsWithOverflow/addMonthsNoOverflow, same variants
|
|
|
284 |
* are available for quarters, years, decade, centuries, millennia (singular and plural forms).
|
|
|
285 |
* @see settings
|
|
|
286 |
*
|
|
|
287 |
* Reset the month overflow behavior.
|
|
|
288 |
*
|
|
|
289 |
* @return void
|
|
|
290 |
*/
|
|
|
291 |
public static function resetMonthsOverflow()
|
|
|
292 |
{
|
|
|
293 |
static::$monthsOverflow = true;
|
|
|
294 |
}
|
|
|
295 |
|
|
|
296 |
/**
|
|
|
297 |
* Get the month overflow global behavior (can be overridden in specific instances).
|
|
|
298 |
*
|
|
|
299 |
* @return bool
|
|
|
300 |
*/
|
|
|
301 |
public static function shouldOverflowMonths()
|
|
|
302 |
{
|
|
|
303 |
return static::$monthsOverflow;
|
|
|
304 |
}
|
|
|
305 |
|
|
|
306 |
/**
|
|
|
307 |
* @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
|
|
|
308 |
* You should rather use the ->settings() method.
|
|
|
309 |
* Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
|
|
|
310 |
* are available for quarters, years, decade, centuries, millennia (singular and plural forms).
|
|
|
311 |
* @see settings
|
|
|
312 |
*
|
|
|
313 |
* Indicates if years should be calculated with overflow.
|
|
|
314 |
*
|
|
|
315 |
* @param bool $yearsOverflow
|
|
|
316 |
*
|
|
|
317 |
* @return void
|
|
|
318 |
*/
|
|
|
319 |
public static function useYearsOverflow($yearsOverflow = true)
|
|
|
320 |
{
|
|
|
321 |
static::$yearsOverflow = $yearsOverflow;
|
|
|
322 |
}
|
|
|
323 |
|
|
|
324 |
/**
|
|
|
325 |
* @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
|
|
|
326 |
* You should rather use the ->settings() method.
|
|
|
327 |
* Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
|
|
|
328 |
* are available for quarters, years, decade, centuries, millennia (singular and plural forms).
|
|
|
329 |
* @see settings
|
|
|
330 |
*
|
|
|
331 |
* Reset the month overflow behavior.
|
|
|
332 |
*
|
|
|
333 |
* @return void
|
|
|
334 |
*/
|
|
|
335 |
public static function resetYearsOverflow()
|
|
|
336 |
{
|
|
|
337 |
static::$yearsOverflow = true;
|
|
|
338 |
}
|
|
|
339 |
|
|
|
340 |
/**
|
|
|
341 |
* Get the month overflow global behavior (can be overridden in specific instances).
|
|
|
342 |
*
|
|
|
343 |
* @return bool
|
|
|
344 |
*/
|
|
|
345 |
public static function shouldOverflowYears()
|
|
|
346 |
{
|
|
|
347 |
return static::$yearsOverflow;
|
|
|
348 |
}
|
|
|
349 |
|
|
|
350 |
/**
|
|
|
351 |
* Set specific options.
|
|
|
352 |
* - strictMode: true|false|null
|
|
|
353 |
* - monthOverflow: true|false|null
|
|
|
354 |
* - yearOverflow: true|false|null
|
|
|
355 |
* - humanDiffOptions: int|null
|
|
|
356 |
* - toStringFormat: string|Closure|null
|
|
|
357 |
* - toJsonFormat: string|Closure|null
|
|
|
358 |
* - locale: string|null
|
|
|
359 |
* - timezone: \DateTimeZone|string|int|null
|
|
|
360 |
* - macros: array|null
|
|
|
361 |
* - genericMacros: array|null
|
|
|
362 |
*
|
|
|
363 |
* @param array $settings
|
|
|
364 |
*
|
|
|
365 |
* @return $this|static
|
|
|
366 |
*/
|
|
|
367 |
public function settings(array $settings)
|
|
|
368 |
{
|
|
|
369 |
$this->localStrictModeEnabled = $settings['strictMode'] ?? null;
|
|
|
370 |
$this->localMonthsOverflow = $settings['monthOverflow'] ?? null;
|
|
|
371 |
$this->localYearsOverflow = $settings['yearOverflow'] ?? null;
|
|
|
372 |
$this->localHumanDiffOptions = $settings['humanDiffOptions'] ?? null;
|
|
|
373 |
$this->localToStringFormat = $settings['toStringFormat'] ?? null;
|
|
|
374 |
$this->localSerializer = $settings['toJsonFormat'] ?? null;
|
|
|
375 |
$this->localMacros = $settings['macros'] ?? null;
|
|
|
376 |
$this->localGenericMacros = $settings['genericMacros'] ?? null;
|
|
|
377 |
$this->localFormatFunction = $settings['formatFunction'] ?? null;
|
|
|
378 |
|
|
|
379 |
if (isset($settings['locale'])) {
|
|
|
380 |
$locales = $settings['locale'];
|
|
|
381 |
|
|
|
382 |
if (!\is_array($locales)) {
|
|
|
383 |
$locales = [$locales];
|
|
|
384 |
}
|
|
|
385 |
|
|
|
386 |
$this->locale(...$locales);
|
|
|
387 |
}
|
|
|
388 |
|
|
|
389 |
if (isset($settings['innerTimezone'])) {
|
|
|
390 |
return $this->setTimezone($settings['innerTimezone']);
|
|
|
391 |
}
|
|
|
392 |
|
|
|
393 |
if (isset($settings['timezone'])) {
|
|
|
394 |
return $this->shiftTimezone($settings['timezone']);
|
|
|
395 |
}
|
|
|
396 |
|
|
|
397 |
return $this;
|
|
|
398 |
}
|
|
|
399 |
|
|
|
400 |
/**
|
|
|
401 |
* Returns current local settings.
|
|
|
402 |
*
|
|
|
403 |
* @return array
|
|
|
404 |
*/
|
|
|
405 |
public function getSettings()
|
|
|
406 |
{
|
|
|
407 |
$settings = [];
|
|
|
408 |
$map = [
|
|
|
409 |
'localStrictModeEnabled' => 'strictMode',
|
|
|
410 |
'localMonthsOverflow' => 'monthOverflow',
|
|
|
411 |
'localYearsOverflow' => 'yearOverflow',
|
|
|
412 |
'localHumanDiffOptions' => 'humanDiffOptions',
|
|
|
413 |
'localToStringFormat' => 'toStringFormat',
|
|
|
414 |
'localSerializer' => 'toJsonFormat',
|
|
|
415 |
'localMacros' => 'macros',
|
|
|
416 |
'localGenericMacros' => 'genericMacros',
|
|
|
417 |
'locale' => 'locale',
|
|
|
418 |
'tzName' => 'timezone',
|
|
|
419 |
'localFormatFunction' => 'formatFunction',
|
|
|
420 |
];
|
|
|
421 |
|
|
|
422 |
foreach ($map as $property => $key) {
|
|
|
423 |
$value = $this->$property ?? null;
|
|
|
424 |
|
|
|
425 |
if ($value !== null) {
|
|
|
426 |
$settings[$key] = $value;
|
|
|
427 |
}
|
|
|
428 |
}
|
|
|
429 |
|
|
|
430 |
return $settings;
|
|
|
431 |
}
|
|
|
432 |
|
|
|
433 |
/**
|
|
|
434 |
* Show truthy properties on var_dump().
|
|
|
435 |
*
|
|
|
436 |
* @return array
|
|
|
437 |
*/
|
|
|
438 |
public function __debugInfo()
|
|
|
439 |
{
|
|
|
440 |
$infos = array_filter(get_object_vars($this), function ($var) {
|
|
|
441 |
return $var;
|
|
|
442 |
});
|
|
|
443 |
|
|
|
444 |
foreach (['dumpProperties', 'constructedObjectId'] as $property) {
|
|
|
445 |
if (isset($infos[$property])) {
|
|
|
446 |
unset($infos[$property]);
|
|
|
447 |
}
|
|
|
448 |
}
|
|
|
449 |
|
|
|
450 |
$this->addExtraDebugInfos($infos);
|
|
|
451 |
|
|
|
452 |
return $infos;
|
|
|
453 |
}
|
|
|
454 |
|
|
|
455 |
protected function addExtraDebugInfos(&$infos): void
|
|
|
456 |
{
|
|
|
457 |
if ($this instanceof DateTimeInterface) {
|
|
|
458 |
try {
|
|
|
459 |
if (!isset($infos['date'])) {
|
|
|
460 |
$infos['date'] = $this->format(CarbonInterface::MOCK_DATETIME_FORMAT);
|
|
|
461 |
}
|
|
|
462 |
|
|
|
463 |
if (!isset($infos['timezone'])) {
|
|
|
464 |
$infos['timezone'] = $this->tzName;
|
|
|
465 |
}
|
|
|
466 |
} catch (Throwable $exception) {
|
|
|
467 |
// noop
|
|
|
468 |
}
|
|
|
469 |
}
|
|
|
470 |
}
|
|
|
471 |
}
|