GitHub
Tests: 12 • Commercial: 2 • Pet projects: 4 • Legacy: 4
Total: 22

.NET Framework

Test
2021

Project Request

ASP.NET MVC • C# • SQL Server
Idea of the project: if someone wants to order a project development, here you can send an application.
Test
2020

ProjectC

ASP.NET MVC • C# • JSON • jQuery
JSON data processing.
Test
2020

Vehicle Maintenance

ASP.NET MVC • VB.NET • JSON
Idea of the project: if someone wants to order a project development, here you can send an application.
Test
2019

Movie Navigator

ASP.NET MVC • VB.NET
Request information about movie from IMDB.
Test
2018

Customers Exchange

ASP.NET MVC • C# • SQL Server
Automated teller machine emulation.
Test
2016

ATM

ASP.NET MVC • C#
Automated teller machine emulation.

.NET Core

Pet project
2022

Mail Daemon

.NET 9 • Console • JSON
Utility to send mails with customizable settings.

Custom

Code
2024

Buns of code

.NET Framework • C# • JavaScript
Code snippets from my projects, ready to use; tiny tests; code examples.

PHP

Test
2024

Mediabox

PHP 8 • Laravel 11 • Vue.js • Composer • SQLite
Test project for media files management.
Test
2020

Loan Castle

PHP • MariaDB
Jums jāizstrādā kāda lielāk projekta prototips. Izstrādājot prototipu, paturiet prātā, ka projektam attīstoties, šo prototipu varētu vajadzēt pilnveidot.
Test
2020

Content Management

PHP • MySQL • AJAX
Создать простой сайт, где будет страница с формой для авторизации и страница для авторизованного пользователя.
Test
2019

Laravel

PHP • Laravel • Vue.js • Composer • SQLite
Izveidot aplikāciju, kura ik pēc noteikta intervāla (60 sekundes) veic ierakstu datubāzē izmantojot Laravel freimworka iebūvēto funkcionalitāti.
Test
2019

Phone Check

PHP • JavaScript • JSON • Docker
Implement application to detect country by phone number.

Frontend

Test
2021

Forex Wall

npm • React
For this exercise, what we need is a simple live wall for tracking currencies.

Business projects

Commercial
2008

Certification Center

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • SQL Server • ADO.NET • Dapper • JavaScript • jQuery • Git
Transport registration and certification services in Latvia, Customer Relationship Management.
Commercial
2000

Amerikas Auto

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • SQL Server • ADO.NET • Entity Framework • JavaScript • jQuery • Git
Car service and spare parts for all USA and European car models, Customer Relationship Management.

Pet projects

Pet project
2023

Geolocation Assistant

.NET 8 • ASP.NET Core • C# • Web API • JSON • Git
Website for determining geolocation by IP or geotagged photo.
Pet project
2008

Web Dynamics

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • Web API • JSON • SQL Server • Dapper • JavaScript • jQuery • SVG • Git
Software development blog. Articles, books, videos, content management.
Pet project
2000

Blackball

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • Web API • JSON • XML • SQL Server • Dapper • JavaScript • jQuery • SVG • Git
My entertainment portal created from scratch.

Good old times

Legacy
2000

DOS Clock

Turbo Pascal • Assembler
Digital clock.
Legacy
2000

BrainOut

Turbo Pascal • Assembler
Tank battle game.
Legacy
1999

Airport Administrator

Turbo Pascal
Курсовая работа в институте.
Legacy
1998

Atomizer

Turbo Pascal • Assembler
Atomizer, aka «Studio2D». Graphic raster editor. AGI is my own «Atomizer Generated Image» file format.

Mediabox

2024 Test

Test project for media files management.

PHP 8 Laravel 11 Vue.js Composer SQLite
Information
Source code
  app
  Http
  .bin
  vite
  lib
  dist
  esm
  node
  lib
  core
  env
  node
  lib
  lib
  lib
  lib
  dist
  lib
  lib
  dist
  es
  lib
  vite
  dist
  node
  dist
  css
  js
  app
  data
  logs
  Unit
  math
  src
  src
  src
  docs
  en
  lib
  src
  src
  Cron
  src
  src
  Core
  ORM
  Spot
  filp
  src
  css
  js
  Util
  src
  src
  src
  src
  psr7
  src
  src
  Core
  Text
  Type
  Xml
  Core
  Text
  Type
  Xml
  src
  Auth
  make
  Bus
  View
  Auth
  Bus
  Http
  Mail
  View
  Auth
  Bus
  Http
  dist
  Http
  Json
  Log
  Mail
  html
  text
  Jobs
  lang
  en
  View
  pint
  pint
  src
  sail
  8.0
  8.1
  8.2
  8.3
  src
  src
  src
  src
  Node
  Util
  Node
  Node
  Node
  Data
  Node
  Node
  Util
  Xml
  src
  src
  src
  docs
  Pass
  src
  Curl
  Test
  src
  Date
  Spl
  lazy
  src
  Cli
  Lang
  List
  src
  src
  lib
  Node
  Expr
  Cast
  Name
  Stmt
  src
  src
  Html
  src
  xml
  src
  src
  src
  Data
  Node
  Html
  css
  js
  Xml
  Util
  src
  src
  src
  src
  src
  Test
  Test
  Math
  Type
  Api
  Rule
  Stub
  Api
  PHPT
  Cli
  Xml
  Util
  PHP
  Xml
  psr
  src
  src
  src
  src
  src
  docs
  src
  log
  src
  src
  psy
  src
  Hoa
  77
  78
  Sudo
  Util
  src
  src
  Map
  Tool
  uuid
  src
  Time
  Guid
  Lazy
  Math
  Dce
  Node
  Time
  Type
  src
  src
  src
  src
  src
  diff
  src
  src
  src
  src
  src
  src
  src
  src
  type
  src
  type
  src
  Test
  CI
  Node
  css
  js
  File
  Test
  Log
  Test
  Smtp
  Auth
  mime
  Part
  Test
  Test
  data
  data
  Test
  Util
  Test
  uid
  css
  js
  Test
  yaml
  Tag
  src
  src
  Css
  Rule
  src
  File
  Util
  voku
  src
  voku
  data
  src
  .env
Root / vendor / nesbot / carbon / src / Carbon / Factory.php
<?php declare(strict_types=1); /** * This file is part of the Carbon package. * * (c) Brian Nesbitt <brian@nesbot.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Carbon; use Closure; use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; use InvalidArgumentException; use ReflectionMethod; use RuntimeException; use Symfony\Contracts\Translation\TranslatorInterface; use Throwable; /** * A factory to generate Carbon instances with common settings. * * <autodoc generated by `composer phpdoc`> * * @method bool canBeCreatedFromFormat(?string $date, string $format) Checks if the (date)time string is in a given format and valid to create a * new instance. * @method ?Carbon create($year = 0, $month = 1, $day = 1, $hour = 0, $minute = 0, $second = 0, $timezone = null) Create a new Carbon instance from a specific date and time. * If any of $year, $month or $day are set to null their now() values will * be used. * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * If $hour is not null then the default values for $minute and $second * will be 0. * @method Carbon createFromDate($year = null, $month = null, $day = null, $timezone = null) Create a Carbon instance from just a date. The time portion is set to now. * @method ?Carbon createFromFormat($format, $time, $timezone = null) Create a Carbon instance from a specific format. * @method ?Carbon createFromIsoFormat(string $format, string $time, $timezone = null, ?string $locale = 'en', ?TranslatorInterface $translator = null) Create a Carbon instance from a specific ISO format (same replacements as ->isoFormat()). * @method ?Carbon createFromLocaleFormat(string $format, string $locale, string $time, $timezone = null) Create a Carbon instance from a specific format and a string in a given language. * @method ?Carbon createFromLocaleIsoFormat(string $format, string $locale, string $time, $timezone = null) Create a Carbon instance from a specific ISO format and a string in a given language. * @method Carbon createFromTime($hour = 0, $minute = 0, $second = 0, $timezone = null) Create a Carbon instance from just a time. The date portion is set to today. * @method Carbon createFromTimeString(string $time, DateTimeZone|string|int|null $timezone = null) Create a Carbon instance from a time string. The date portion is set to today. * @method Carbon createFromTimestamp(string|int|float $timestamp, DateTimeZone|string|int|null $timezone = null) Create a Carbon instance from a timestamp and set the timezone (UTC by default). * Timestamp input can be given as int, float or a string containing one or more numbers. * @method Carbon createFromTimestampMs(string|int|float $timestamp, DateTimeZone|string|int|null $timezone = null) Create a Carbon instance from a timestamp in milliseconds. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method Carbon createFromTimestampMsUTC($timestamp) Create a Carbon instance from a timestamp in milliseconds. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method Carbon createFromTimestampUTC(string|int|float $timestamp) Create a Carbon instance from a timestamp keeping the timezone to UTC. * Timestamp input can be given as int, float or a string containing one or more numbers. * @method Carbon createMidnightDate($year = null, $month = null, $day = null, $timezone = null) Create a Carbon instance from just a date. The time portion is set to midnight. * @method ?Carbon createSafe($year = null, $month = null, $day = null, $hour = null, $minute = null, $second = null, $timezone = null) Create a new safe Carbon instance from a specific date and time. * If any of $year, $month or $day are set to null their now() values will * be used. * If $hour is null it will be set to its now() value and the default * values for $minute and $second will be their now() values. * If $hour is not null then the default values for $minute and $second * will be 0. * If one of the set values is not valid, an InvalidDateException * will be thrown. * @method Carbon createStrict(?int $year = 0, ?int $month = 1, ?int $day = 1, ?int $hour = 0, ?int $minute = 0, ?int $second = 0, $timezone = null) Create a new Carbon instance from a specific date and time using strict validation. * @method mixed executeWithLocale(string $locale, callable $func) Set the current locale to the given, execute the passed function, reset the locale to previous one, * then return the result of the closure (or null if the closure was void). * @method Carbon fromSerialized($value) Create an instance from a serialized string. * @method array getAvailableLocales() Returns the list of internally available locales and already loaded custom locales. * (It will ignore custom translator dynamic loading.) * @method Language[] getAvailableLocalesInfo() Returns list of Language object for each available locale. This object allow you to get the ISO name, native * name, region and variant of the locale. * @method array getDays() Get the days of the week. * @method ?string getFallbackLocale() Get the fallback locale. * @method array getFormatsToIsoReplacements() List of replacements from date() format to isoFormat(). * @method array getIsoUnits() Returns list of locale units for ISO formatting. * @method array|false getLastErrors() {@inheritdoc} * @method string getLocale() Get the current translator locale. * @method int getMidDayAt() get midday/noon hour * @method string getTimeFormatByPrecision(string $unitPrecision) Return a format from H:i to H:i:s.u according to given unit precision. * @method string|Closure|null getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null) Returns raw translation message for a given key. * @method int getWeekEndsAt(?string $locale = null) Get the last day of week. * @method int getWeekStartsAt(?string $locale = null) Get the first day of week. * @method bool hasRelativeKeywords(?string $time) Determine if a time string will produce a relative date. * @method Carbon instance(DateTimeInterface $date) Create a Carbon instance from a DateTime one. * @method bool isImmutable() Returns true if the current class/instance is immutable. * @method bool isModifiableUnit($unit) Returns true if a property can be changed via setter. * @method bool isMutable() Returns true if the current class/instance is mutable. * @method bool localeHasDiffOneDayWords(string $locale) Returns true if the given locale is internally supported and has words for 1-day diff (just now, yesterday, tomorrow). * Support is considered enabled if the 3 words are translated in the given locale. * @method bool localeHasDiffSyntax(string $locale) Returns true if the given locale is internally supported and has diff syntax support (ago, from now, before, after). * Support is considered enabled if the 4 sentences are translated in the given locale. * @method bool localeHasDiffTwoDayWords(string $locale) Returns true if the given locale is internally supported and has words for 2-days diff (before yesterday, after tomorrow). * Support is considered enabled if the 2 words are translated in the given locale. * @method bool localeHasPeriodSyntax($locale) Returns true if the given locale is internally supported and has period syntax support (X times, every X, from X, to X). * Support is considered enabled if the 4 sentences are translated in the given locale. * @method bool localeHasShortUnits(string $locale) Returns true if the given locale is internally supported and has short-units support. * Support is considered enabled if either year, day or hour has a short variant translated. * @method ?Carbon make($var, DateTimeZone|string|null $timezone = null) Make a Carbon instance from given variable if possible. * Always return a new instance. Parse only strings and only these likely to be dates (skip intervals * and recurrences). Throw an exception for invalid format, but otherwise return null. * @method void mixin(object|string $mixin) Mix another object into the class. * @method Carbon now(DateTimeZone|string|int|null $timezone = null) Get a Carbon instance for the current date and time. * @method Carbon parse(DateTimeInterface|WeekDay|Month|string|int|float|null $time, DateTimeZone|string|int|null $timezone = null) Create a carbon instance from a string. * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * @method Carbon parseFromLocale(string $time, ?string $locale = null, DateTimeZone|string|int|null $timezone = null) Create a carbon instance from a localized string (in French, Japanese, Arabic, etc.). * @method string pluralUnit(string $unit) Returns standardized plural of a given singular/plural unit name (in English). * @method ?Carbon rawCreateFromFormat(string $format, string $time, $timezone = null) Create a Carbon instance from a specific format. * @method Carbon rawParse(DateTimeInterface|WeekDay|Month|string|int|float|null $time, DateTimeZone|string|int|null $timezone = null) Create a carbon instance from a string. * This is an alias for the constructor that allows better fluent syntax * as it allows you to do Carbon::parse('Monday next week')->fn() rather * than (new Carbon('Monday next week'))->fn(). * @method void setFallbackLocale(string $locale) Set the fallback locale. * @method void setLocale(string $locale) Set the current translator locale and indicate if the source locale file exists. * Pass 'auto' as locale to use the closest language to the current LC_TIME locale. * @method void setMidDayAt($hour) @deprecated To avoid conflict between different third-party libraries, static setters should not be used. * You should rather consider mid-day is always 12pm, then if you need to test if it's an other * hour, test it explicitly: * $date->format('G') == 13 * or to set explicitly to a given hour: * $date->setTime(13, 0, 0, 0) * Set midday/noon hour * @method string singularUnit(string $unit) Returns standardized singular of a given singular/plural unit name (in English). * @method void sleep(int|float $seconds) * @method Carbon today(DateTimeZone|string|int|null $timezone = null) Create a Carbon instance for today. * @method Carbon tomorrow(DateTimeZone|string|int|null $timezone = null) Create a Carbon instance for tomorrow. * @method string translateTimeString(string $timeString, ?string $from = null, ?string $to = null, int $mode = CarbonInterface::TRANSLATE_ALL) Translate a time string from a locale to an other. * @method string translateWith(TranslatorInterface $translator, string $key, array $parameters = [], $number = null) Translate using translation string or callback available. * @method Carbon yesterday(DateTimeZone|string|int|null $timezone = null) Create a Carbon instance for yesterday. * * </autodoc> */ class Factory { protected string $className = Carbon::class; protected array $settings = []; /** * A test Carbon instance to be returned when now instances are created. */ protected Closure|CarbonInterface|null $testNow = null; /** * The timezone to restore to when clearing the time mock. */ protected ?string $testDefaultTimezone = null; /** * Is true when test-now is generated by a closure and timezone should be taken on the fly from it. */ protected bool $useTimezoneFromTestNow = false; /** * Default translator. */ protected TranslatorInterface $translator; /** * Days of weekend. */ protected array $weekendDays = [ CarbonInterface::SATURDAY, CarbonInterface::SUNDAY, ]; /** * Format regex patterns. * * @var array<string, string> */ protected array $regexFormats = [ 'd' => '(3[01]|[12][0-9]|0[1-9])', 'D' => '(Sun|Mon|Tue|Wed|Thu|Fri|Sat)', 'j' => '([123][0-9]|[1-9])', 'l' => '([a-zA-Z]{2,})', 'N' => '([1-7])', 'S' => '(st|nd|rd|th)', 'w' => '([0-6])', 'z' => '(36[0-5]|3[0-5][0-9]|[12][0-9]{2}|[1-9]?[0-9])', 'W' => '(5[012]|[1-4][0-9]|0?[1-9])', 'F' => '([a-zA-Z]{2,})', 'm' => '(1[012]|0[1-9])', 'M' => '([a-zA-Z]{3})', 'n' => '(1[012]|[1-9])', 't' => '(2[89]|3[01])', 'L' => '(0|1)', 'o' => '([1-9][0-9]{0,4})', 'Y' => '([1-9]?[0-9]{4})', 'y' => '([0-9]{2})', 'a' => '(am|pm)', 'A' => '(AM|PM)', 'B' => '([0-9]{3})', 'g' => '(1[012]|[1-9])', 'G' => '(2[0-3]|1?[0-9])', 'h' => '(1[012]|0[1-9])', 'H' => '(2[0-3]|[01][0-9])', 'i' => '([0-5][0-9])', 's' => '([0-5][0-9])', 'u' => '([0-9]{1,6})', 'v' => '([0-9]{1,3})', 'e' => '([a-zA-Z]{1,5})|([a-zA-Z]*\\/[a-zA-Z]*)', 'I' => '(0|1)', 'O' => '([+-](1[0123]|0[0-9])[0134][05])', 'P' => '([+-](1[0123]|0[0-9]):[0134][05])', 'p' => '(Z|[+-](1[0123]|0[0-9]):[0134][05])', 'T' => '([a-zA-Z]{1,5})', 'Z' => '(-?[1-5]?[0-9]{1,4})', 'U' => '([0-9]*)', // The formats below are combinations of the above formats. '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 '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 ]; /** * Format modifiers (such as available in createFromFormat) regex patterns. * * @var array */ protected array $regexFormatModifiers = [ '*' => '.+', ' ' => '[ ]', '#' => '[;:\\/.,()-]', '?' => '([^a]|[a])', '!' => '', '|' => '', '+' => '', ]; public function __construct(array $settings = [], ?string $className = null) { if ($className) { $this->className = $className; } $this->settings = $settings; } public function getClassName(): string { return $this->className; } public function setClassName(string $className): self { $this->className = $className; return $this; } public function className(?string $className = null): self|string { return $className === null ? $this->getClassName() : $this->setClassName($className); } public function getSettings(): array { return $this->settings; } public function setSettings(array $settings): self { $this->settings = $settings; return $this; } public function settings(?array $settings = null): self|array { return $settings === null ? $this->getSettings() : $this->setSettings($settings); } public function mergeSettings(array $settings): self { $this->settings = array_merge($this->settings, $settings); return $this; } public function setHumanDiffOptions(int $humanDiffOptions): void { $this->mergeSettings([ 'humanDiffOptions' => $humanDiffOptions, ]); } public function enableHumanDiffOption($humanDiffOption): void { $this->setHumanDiffOptions($this->getHumanDiffOptions() | $humanDiffOption); } public function disableHumanDiffOption(int $humanDiffOption): void { $this->setHumanDiffOptions($this->getHumanDiffOptions() & ~$humanDiffOption); } public function getHumanDiffOptions(): int { return (int) ($this->getSettings()['humanDiffOptions'] ?? 0); } /** * Register a custom macro. * * Pass null macro to remove it. * * @example * ``` * $userSettings = [ * 'locale' => 'pt', * 'timezone' => 'America/Sao_Paulo', * ]; * $factory->macro('userFormat', function () use ($userSettings) { * return $this->copy()->locale($userSettings['locale'])->tz($userSettings['timezone'])->calendar(); * }); * echo $factory->yesterday()->hours(11)->userFormat(); * ``` */ public function macro(string $name, ?callable $macro): void { $macros = $this->getSettings()['macros'] ?? []; $macros[$name] = $macro; $this->mergeSettings([ 'macros' => $macros, ]); } /** * Remove all macros and generic macros. */ public function resetMacros(): void { $this->mergeSettings([ 'macros' => null, 'genericMacros' => null, ]); } /** * Register a custom macro. * * @param callable $macro * @param int $priority marco with higher priority is tried first * * @return void */ public function genericMacro(callable $macro, int $priority = 0): void { $genericMacros = $this->getSettings()['genericMacros'] ?? []; if (!isset($genericMacros[$priority])) { $genericMacros[$priority] = []; krsort($genericMacros, SORT_NUMERIC); } $genericMacros[$priority][] = $macro; $this->mergeSettings([ 'genericMacros' => $genericMacros, ]); } /** * Checks if macro is registered globally. */ public function hasMacro(string $name): bool { return isset($this->getSettings()['macros'][$name]); } /** * Get the raw callable macro registered globally for a given name. */ public function getMacro(string $name): ?callable { return $this->getSettings()['macros'][$name] ?? null; } /** * Set the default translator instance to use. */ public function setTranslator(TranslatorInterface $translator): void { $this->translator = $translator; } /** * Initialize the default translator instance if necessary. */ public function getTranslator(): TranslatorInterface { return $this->translator ??= Translator::get(); } /** * Reset the format used to the default when type juggling a Carbon instance to a string * * @return void */ public function resetToStringFormat(): void { $this->setToStringFormat(null); } /** * Set the default format used when type juggling a Carbon instance to a string. */ public function setToStringFormat(string|Closure|null $format): void { $this->mergeSettings([ 'toStringFormat' => $format, ]); } /** * JSON serialize all Carbon instances using the given callback. */ public function serializeUsing(string|callable|null $format): void { $this->mergeSettings([ 'toJsonFormat' => $format, ]); } /** * Enable the strict mode (or disable with passing false). */ public function useStrictMode(bool $strictModeEnabled = true): void { $this->mergeSettings([ 'strictMode' => $strictModeEnabled, ]); } /** * Returns true if the strict mode is globally in use, false else. * (It can be overridden in specific instances.) */ public function isStrictModeEnabled(): bool { return $this->getSettings()['strictMode'] ?? true; } /** * Indicates if months should be calculated with overflow. */ public function useMonthsOverflow(bool $monthsOverflow = true): void { $this->mergeSettings([ 'monthOverflow' => $monthsOverflow, ]); } /** * Reset the month overflow behavior. */ public function resetMonthsOverflow(): void { $this->useMonthsOverflow(); } /** * Get the month overflow global behavior (can be overridden in specific instances). */ public function shouldOverflowMonths(): bool { return $this->getSettings()['monthOverflow'] ?? true; } /** * Indicates if years should be calculated with overflow. */ public function useYearsOverflow(bool $yearsOverflow = true): void { $this->mergeSettings([ 'yearOverflow' => $yearsOverflow, ]); } /** * Reset the month overflow behavior. */ public function resetYearsOverflow(): void { $this->useYearsOverflow(); } /** * Get the month overflow global behavior (can be overridden in specific instances). */ public function shouldOverflowYears(): bool { return $this->getSettings()['yearOverflow'] ?? true; } /** * Get weekend days * * @return array */ public function getWeekendDays(): array { return $this->weekendDays; } /** * Set weekend days */ public function setWeekendDays(array $days): void { $this->weekendDays = $days; } /** * Checks if the (date)time string is in a given format. * * @example * ``` * Carbon::hasFormat('11:12:45', 'h:i:s'); // true * Carbon::hasFormat('13:12:45', 'h:i:s'); // false * ``` */ public function hasFormat(string $date, string $format): bool { // createFromFormat() is known to handle edge cases silently. // E.g. "1975-5-1" (Y-n-j) will still be parsed correctly when "Y-m-d" is supplied as the format. // To ensure we're really testing against our desired format, perform an additional regex validation. return $this->matchFormatPattern($date, preg_quote($format, '/'), $this->regexFormats); } /** * Checks if the (date)time string is in a given format. * * @example * ``` * Carbon::hasFormatWithModifiers('31/08/2015', 'd#m#Y'); // true * Carbon::hasFormatWithModifiers('31/08/2015', 'm#d#Y'); // false * ``` */ public function hasFormatWithModifiers(string $date, string $format): bool { return $this->matchFormatPattern($date, $format, array_merge($this->regexFormats, $this->regexFormatModifiers)); } /** * Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * * Note the timezone parameter was left out of the examples above and * has no affect as the mock value will be returned regardless of its value. * * Only the moment is mocked with setTestNow(), the timezone will still be the one passed * as parameter of date_default_timezone_get() as a fallback (see setTestNowAndTimezone()). * * To clear the test instance call this method using the default * parameter of null. * * /!\ Use this method for unit tests only. * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance */ public function setTestNow(mixed $testNow = null): void { $this->useTimezoneFromTestNow = false; $this->testNow = $testNow instanceof self || $testNow instanceof Closure ? $testNow : $this->make($testNow); } /** * Set a Carbon instance (real or mock) to be returned when a "now" * instance is created. The provided instance will be returned * specifically under the following conditions: * - A call to the static now() method, ex. Carbon::now() * - When a null (or blank string) is passed to the constructor or parse(), ex. new Carbon(null) * - When the string "now" is passed to the constructor or parse(), ex. new Carbon('now') * - When a string containing the desired time is passed to Carbon::parse(). * * It will also align default timezone (e.g. call date_default_timezone_set()) with * the second argument or if null, with the timezone of the given date object. * * To clear the test instance call this method using the default * parameter of null. * * /!\ Use this method for unit tests only. * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance */ public function setTestNowAndTimezone(mixed $testNow = null, $timezone = null): void { if ($testNow) { $this->testDefaultTimezone ??= date_default_timezone_get(); } $useDateInstanceTimezone = $testNow instanceof DateTimeInterface; if ($useDateInstanceTimezone) { $this->setDefaultTimezone($testNow->getTimezone()->getName(), $testNow); } $this->setTestNow($testNow); $this->useTimezoneFromTestNow = ($timezone === null && $testNow instanceof Closure); if (!$useDateInstanceTimezone) { $now = $this->getMockedTestNow(\func_num_args() === 1 ? null : $timezone); $this->setDefaultTimezone($now?->tzName ?? $this->testDefaultTimezone ?? 'UTC', $now); } if (!$testNow) { $this->testDefaultTimezone = null; } } /** * Temporarily sets a static date to be used within the callback. * Using setTestNow to set the date, executing the callback, then * clearing the test instance. * * /!\ Use this method for unit tests only. * * @template T * * @param DateTimeInterface|Closure|static|string|false|null $testNow real or mock Carbon instance * @param Closure(): T $callback * * @return T */ public function withTestNow(mixed $testNow, callable $callback): mixed { $this->setTestNow($testNow); try { $result = $callback(); } finally { $this->setTestNow(); } return $result; } /** * Get the Carbon instance (real or mock) to be returned when a "now" * instance is created. * * @return Closure|CarbonInterface|null the current instance used for testing */ public function getTestNow(): Closure|CarbonInterface|null { if ($this->testNow === null) { $factory = FactoryImmutable::getDefaultInstance(); if ($factory !== $this) { return $factory->getTestNow(); } } return $this->testNow; } public function handleTestNowClosure( Closure|CarbonInterface|null $testNow, DateTimeZone|string|int|null $timezone = null, ): ?CarbonInterface { if ($testNow instanceof Closure) { $callback = Callback::fromClosure($testNow); $realNow = new DateTimeImmutable('now'); $testNow = $testNow($callback->prepareParameter($this->parse( $realNow->format('Y-m-d H:i:s.u'), $timezone ?? $realNow->getTimezone(), ))); if ($testNow !== null && !($testNow instanceof DateTimeInterface)) { $function = $callback->getReflectionFunction(); $type = \is_object($testNow) ? $testNow::class : \gettype($testNow); throw new RuntimeException( 'The test closure defined in '.$function->getFileName(). ' at line '.$function->getStartLine().' returned '.$type. '; expected '.CarbonInterface::class.'|null', ); } if (!($testNow instanceof CarbonInterface)) { $timezone ??= $this->useTimezoneFromTestNow ? $testNow->getTimezone() : null; $testNow = $this->__call('instance', [$testNow, $timezone]); } } return $testNow; } /** * Determine if there is a valid test instance set. A valid test instance * is anything that is not null. * * @return bool true if there is a test instance, otherwise false */ public function hasTestNow(): bool { return $this->getTestNow() !== null; } public function withTimeZone(DateTimeZone|string|int|null $timezone): static { $factory = clone $this; $factory->settings['timezone'] = $timezone; return $factory; } public function __call(string $name, array $arguments): mixed { $method = new ReflectionMethod($this->className, $name); $settings = $this->settings; if ($settings && isset($settings['timezone'])) { $timezoneParameters = array_filter($method->getParameters(), function ($parameter) { return \in_array($parameter->getName(), ['tz', 'timezone'], true); }); $timezoneSetting = $settings['timezone']; if (isset($arguments[0]) && \in_array($name, ['instance', 'make', 'create', 'parse'], true)) { if ($arguments[0] instanceof DateTimeInterface) { $settings['innerTimezone'] = $settings['timezone']; } elseif (\is_string($arguments[0]) && date_parse($arguments[0])['is_localtime']) { unset($settings['timezone'], $settings['innerTimezone']); } } if (\count($timezoneParameters)) { $index = key($timezoneParameters); if (!isset($arguments[$index])) { array_splice($arguments, key($timezoneParameters), 0, [$timezoneSetting]); } unset($settings['timezone']); } } $clock = FactoryImmutable::getCurrentClock(); FactoryImmutable::setCurrentClock($this); try { $result = $this->className::$name(...$arguments); } finally { FactoryImmutable::setCurrentClock($clock); } if (isset($this->translator)) { $settings['translator'] = $this->translator; } return $result instanceof CarbonInterface && !empty($settings) ? $result->settings($settings) : $result; } /** * Get the mocked date passed in setTestNow() and if it's a Closure, execute it. */ protected function getMockedTestNow(DateTimeZone|string|int|null $timezone): ?CarbonInterface { $testNow = $this->handleTestNowClosure($this->getTestNow()); if ($testNow instanceof CarbonInterface) { $testNow = $testNow->avoidMutation(); if ($timezone !== null) { return $testNow->setTimezone($timezone); } } return $testNow; } /** * Checks if the (date)time string is in a given format with * given list of pattern replacements. * * @example * ``` * Carbon::hasFormat('11:12:45', 'h:i:s'); // true * Carbon::hasFormat('13:12:45', 'h:i:s'); // false * ``` * * @param string $date * @param string $format * @param array $replacements * * @return bool */ private function matchFormatPattern(string $date, string $format, array $replacements): bool { // Preg quote, but remove escaped backslashes since we'll deal with escaped characters in the format string. $regex = str_replace('\\\\', '\\', $format); // Replace not-escaped letters $regex = preg_replace_callback( '/(?<!\\\\)((?:\\\\{2})*)(['.implode('', array_keys($replacements)).'])/', static fn ($match) => $match[1].strtr($match[2], $replacements), $regex, ); // Replace escaped letters by the letter itself $regex = preg_replace('/(?<!\\\\)((?:\\\\{2})*)\\\\(\w)/', '$1$2', $regex); // Escape not escaped slashes $regex = preg_replace('#(?<!\\\\)((?:\\\\{2})*)/#', '$1\\/', $regex); return (bool) @preg_match('/^'.$regex.'$/', $date); } private function setDefaultTimezone(string $timezone, ?DateTimeInterface $date = null): void { $previous = null; $success = false; try { $success = date_default_timezone_set($timezone); } catch (Throwable $exception) { $previous = $exception; } if (!$success) { $suggestion = @CarbonTimeZone::create($timezone)->toRegionName($date); throw new InvalidArgumentException( "Timezone ID '$timezone' is invalid". ($suggestion && $suggestion !== $timezone ? ", did you mean '$suggestion'?" : '.')."\n". "It must be one of the IDs from DateTimeZone::listIdentifiers(),\n". 'For the record, hours/minutes offset are relevant only for a particular moment, '. 'but not as a default timezone.', 0, $previous ); } } }