Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK ! zķ carbon/extension.neonnu ÕIw¶“ services:
-
class: Carbon\PHPStan\MacroExtension
tags:
- phpstan.broker.methodsClassReflectionExtension
PK ! A_£Ņ Ņ carbon/readme.mdnu ÕIw¶“ # Carbon
[](https://packagist.org/packages/nesbot/carbon)
[](https://packagist.org/packages/nesbot/carbon)
[](https://actions-badge.atrox.dev/briannesbitt/Carbon/goto)
[](https://github.styleci.io/repos/5724990)
[](https://codecov.io/github/briannesbitt/Carbon?branch=master)
[](https://github.com/phpstan/phpstan)
[](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme)
An international PHP extension for DateTime. [http://carbon.nesbot.com](http://carbon.nesbot.com)
```php
toDateTimeString());
printf("Right now in Vancouver is %s", Carbon::now('America/Vancouver')); //implicit __toString()
$tomorrow = Carbon::now()->addDay();
$lastWeek = Carbon::now()->subWeek();
$nextSummerOlympics = Carbon::createFromDate(2016)->addYears(4);
$officialDate = Carbon::now()->toRfc2822String();
$howOldAmI = Carbon::createFromDate(1975, 5, 21)->age;
$noonTodayLondonTime = Carbon::createFromTime(12, 0, 0, 'Europe/London');
$internetWillBlowUpOn = Carbon::create(2038, 01, 19, 3, 14, 7, 'GMT');
// Don't really want this to happen so mock now
Carbon::setTestNow(Carbon::createFromDate(2000, 1, 1));
// comparisons are always done in UTC
if (Carbon::now()->gte($internetWillBlowUpOn)) {
die();
}
// Phew! Return to normal behaviour
Carbon::setTestNow();
if (Carbon::now()->isWeekend()) {
echo 'Party!';
}
// Over 200 languages (and over 500 regional variants) supported:
echo Carbon::now()->subMinutes(2)->diffForHumans(); // '2 minutes ago'
echo Carbon::now()->subMinutes(2)->locale('zh_CN')->diffForHumans(); // '2åéå'
echo Carbon::parse('2019-07-23 14:51')->isoFormat('LLLL'); // 'Tuesday, July 23, 2019 2:51 PM'
echo Carbon::parse('2019-07-23 14:51')->locale('fr_FR')->isoFormat('LLLL'); // 'mardi 23 juillet 2019 14:51'
// ... but also does 'from now', 'after' and 'before'
// rolling up to seconds, minutes, hours, days, months, years
$daysSinceEpoch = Carbon::createFromTimestamp(0)->diffInDays();
```
[Get supported nesbot/carbon with the Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme)
## Installation
### With Composer
```
$ composer require nesbot/carbon
```
```json
{
"require": {
"nesbot/carbon": "^2.16"
}
}
```
```php
### Translators
[Thanks to people helping us to translate Carbon in so many languages](https://carbon.nesbot.com/contribute/translators/)
### Backers
Thank you to all our backers! š [[Become a backer](https://opencollective.com/Carbon#backer)]
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/Carbon#sponsor)]
## Carbon for enterprise
Available as part of the Tidelift Subscription.
The maintainers of ``Carbon`` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
PK ! ^¬T carbon/LICENSEnu ÕIw¶“ Copyright (C) Brian Nesbitt
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
PK ! óT>Õ carbon/phpmd.xmlnu ÕIw¶“
Mess detection rules for Carbon
PK ! ÖÉ$Ī carbon/contributing.mdnu ÕIw¶“ # Contributing to Carbon
## Issue Contributions
Please report any security issue using [Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
Please don't disclose security bugs publicly until they have been handled by us.
For any other bug or issue, please click this link and follow the template:
[Create new issue](https://github.com/briannesbitt/Carbon/issues/new)
You may think this template does not apply to your case but please think again. A long description will never be as
clear as a code chunk with the output you expect from it (for either bug report or new features).
## Code Contributions
### Where to begin
We use the label **good first issue** to tag issues that could be a good fit for new contributors, see if there are such issues now following this link:
https://github.com/briannesbitt/Carbon/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
Else, check the roadmap to see what we plan to do in next releases:
https://github.com/briannesbitt/Carbon/issues/1681
### Develop locally, then submit changes
Fork the [GitHub project](https://github.com/briannesbitt/Carbon) and download it locally:
```shell
git clone https://github.com//Carbon.git
cd Carbon
git remote add upstream https://github.com/briannesbitt/Carbon.git
```
Replace `` with your GitHub username.
Then, you can work on the master or create a specific branch for your development:
```shell
git checkout -b my-feature-branch -t origin/master
```
You can now edit the "Carbon" directory contents.
Before committing, please set your name and your e-mail (use the same e-mail address as in your GitHub account):
```shell
git config --global user.name "Your Name"
git config --global user.email "your.email.address@example.com"
```
The ```--global``` argument will apply this setting for all your git repositories, remove it to set only your Carbon
fork with those settings.
Now you can commit your modifications as you usually do with git:
```shell
git add --all
git commit -m "The commit message log"
```
If your patch fixes an open issue, please insert ```#``` immediately followed by the issue number:
```shell
git commit -m "#21 Fix this or that"
```
Use git rebase (not git merge) to sync your work from time to time:
```shell
git fetch origin
git rebase origin/master
```
Please add some tests for bug fixes and features (so it will ensure next developments will not break your code),
then check all is right with phpunit:
Install PHP if you haven't yet, then install composer:
https://getcomposer.org/download/
Update dependencies:
```
./composer.phar update
```
Or if you installed composer globally:
```
composer update
```
Then call phpunit:
```
./vendor/bin/phpunit
```
Make sure all tests succeed before submitting your pull-request, else we will not be able to merge it.
Push your work on your remote GitHub fork with:
```
git push origin my-feature-branch
```
Go to https://github.com/yourusername/Carbon and select your feature branch. Click the 'Pull Request' button and fill
out the form.
We will review it within a few days. And we thank you in advance for your help.
## Versioning
### Note about Semantic Versioning and breaking changes
As a developer, you must understand every change is a breaking change. What is a bug for someone
is expected in someone else's workflow. The consequence of a change strongly depends on the usage.
[Semantic Versioning](https://semver.org/) relies to public API. In PHP, the public API of a class is its public
methods. However, if you extend a class, you can access protected methods, then if you use reflexion, you can
access private methods. So anything can become a public API if you force it to be. That doesn't mean we should handle
any possible usage, else we would have to publish a major release for each change and it would no longer make sense.
So before any complain about a breaking change, be warned, we do not guarantee a strict Semantic Versioning as you
may expect, we're following a pragmatic interpretation of Semantic Versioning that allows the software to evolve in a
reliable way with reasonable maintenance effort.
Concretely, we consider a change as breaking if it makes fail one of our unit test. We will do our best to avoid
incompatibilities with libraries that extends Carbon classes (such as Laravel that is continuously tested thanks to
Travis CI, [see the compatibility matrix](https://github.com/kylekatarnls/carbon-laravel/tree/master#carbon-1-dev-version-1next)).
If you're the owner of a library that strongly depends on Carbon, we recommend you to run unit tests daily requiring
`"nesbot/carbon": "dev-master"` (for `^2`) or `"nesbot/carbon": "dev-version-1.next"` (for `^1`), this way you can
detect incompatibilities earlier and report it to us before we tag a release. We'll pay attention and try to fix it to
make update to next minor releases as soft as possible.
We reserve the right to publish emergency patches within 24 hours after a release if a tag that does not respect
this pattern would have been released despite our vigilance. In this very rare and particular case, we would mark the
tag as broken on GitHub and backward compatibility would be based on previous stable tag.
Last, you must understand that Carbon extends PHP natives classes, that means Carbon can be impacted by any change
that occurs in the date/time API of PHP. We watch new PHP versions and handle those changes as quickly as possible
when detected, but as PHP does not follow the semantic versioning pattern, it basically means any releases (including
patches) can have unexpected consequences on Carbon methods results.
### Long term support
To benefit the better support, require Carbon using major version range (`^1` or `^2`). By requiring `1.26.*`,
`~1.26.0` or limited range such as `>=1.20 <1.33`, you fall to low priority support (only security and critical issues
will be fixed), our prior support goes to next minor releases of each major version. It applies to bug fixes and
low-cost features. Other new features will only be added in the last stable release. At the opposite, we recommend you
to restrain to a major number, as there is no compatibility guarantee from a major version to the next. It means
requiring `>=2`, as it allows any newer version, will probably leads to errors on releasing our next major version.
Open milestones can be patched if a minor bug is detected while if you're on a closed milestone, we'll more likely
ask you to update first to an open one. See currently open milestones:
https://github.com/briannesbitt/Carbon/milestones
PK ! ČqlŹ Ź carbon/composer.jsonnu ÕIw¶“ {
"name": "nesbot/carbon",
"type": "library",
"description": "An API extension for DateTime that supports 281 different languages.",
"keywords": [
"date",
"time",
"DateTime"
],
"homepage": "http://carbon.nesbot.com",
"support": {
"issues": "https://github.com/briannesbitt/Carbon/issues",
"source": "https://github.com/briannesbitt/Carbon"
},
"license": "MIT",
"authors": [
{
"name": "Brian Nesbitt",
"email": "brian@nesbot.com",
"homepage": "http://nesbot.com"
},
{
"name": "kylekatarnls",
"homepage": "http://github.com/kylekatarnls"
}
],
"prefer-stable": true,
"minimum-stability": "dev",
"bin": ["bin/carbon"],
"require": {
"php": "^7.1.8 || ^8.0",
"ext-json": "*",
"symfony/polyfill-mbstring": "^1.0",
"symfony/translation": "^3.4 || ^4.0 || ^5.0"
},
"require-dev": {
"doctrine/orm": "^2.7",
"friendsofphp/php-cs-fixer": "^2.14 || ^3.0",
"kylekatarnls/multi-tester": "^2.0",
"phpmd/phpmd": "^2.9",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "^0.12.54",
"phpunit/phpunit": "^7.5.20 || ^8.5.14",
"squizlabs/php_codesniffer": "^3.4"
},
"autoload": {
"psr-4": {
"Carbon\\": "src/Carbon/"
}
},
"autoload-dev": {
"files": [
"tests/Laravel/ServiceProvider.php"
],
"psr-4": {
"Tests\\": "tests/"
}
},
"config": {
"process-timeout": 0,
"sort-packages": true
},
"scripts": {
"test": [
"@phpunit",
"@style-check"
],
"style-check": [
"@phpcs",
"@phpstan",
"@phpmd"
],
"phpunit": "phpunit --verbose",
"phpcs": "php-cs-fixer fix -v --diff --dry-run",
"phpstan": "phpstan analyse --configuration phpstan.neon",
"phpmd": "phpmd src text /phpmd.xml",
"phpdoc": "php phpdoc.php"
},
"extra": {
"branch-alias": {
"dev-master": "2.x-dev",
"dev-3.x": "3.x-dev"
},
"laravel": {
"providers": [
"Carbon\\Laravel\\ServiceProvider"
]
},
"phpstan": {
"includes": [
"extension.neon"
]
}
}
}
PK ! {mu0] ] carbon/bin/carbon.batnu ÕIw¶“ @ECHO OFF
setlocal DISABLEDELAYEDEXPANSION
SET BIN_TARGET=%~dp0/carbon
php "%BIN_TARGET%" %*
PK ! #ėŖ²z z carbon/bin/carbonnu ½Ģż #!/usr/bin/env php
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon;
use DateTimeInterface;
interface CarbonConverterInterface
{
public function convertDate(DateTimeInterface $dateTime, bool $negated = false): CarbonInterface;
}
PK ! qWņ` ņ` $ carbon/src/Carbon/CarbonInterval.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon;
use Carbon\Exceptions\BadFluentConstructorException;
use Carbon\Exceptions\BadFluentSetterException;
use Carbon\Exceptions\InvalidCastException;
use Carbon\Exceptions\InvalidIntervalException;
use Carbon\Exceptions\ParseErrorException;
use Carbon\Exceptions\UnitNotConfiguredException;
use Carbon\Exceptions\UnknownGetterException;
use Carbon\Exceptions\UnknownSetterException;
use Carbon\Exceptions\UnknownUnitException;
use Carbon\Traits\IntervalRounding;
use Carbon\Traits\IntervalStep;
use Carbon\Traits\Mixin;
use Carbon\Traits\Options;
use Closure;
use DateInterval;
use Exception;
use ReflectionException;
use Throwable;
/**
* A simple API extension for DateInterval.
* The implementation provides helpers to handle weeks but only days are saved.
* Weeks are calculated based on the total days of the current instance.
*
* @property int $years Total years of the current interval.
* @property int $months Total months of the current interval.
* @property int $weeks Total weeks of the current interval calculated from the days.
* @property int $dayz Total days of the current interval (weeks * 7 + days).
* @property int $hours Total hours of the current interval.
* @property int $minutes Total minutes of the current interval.
* @property int $seconds Total seconds of the current interval.
* @property int $microseconds Total microseconds of the current interval.
* @property int $milliseconds Total microseconds of the current interval.
* @property int $microExcludeMilli Remaining microseconds without the milliseconds.
* @property int $dayzExcludeWeeks Total days remaining in the final week of the current instance (days % 7).
* @property int $daysExcludeWeeks alias of dayzExcludeWeeks
* @property-read float $totalYears Number of years equivalent to the interval.
* @property-read float $totalMonths Number of months equivalent to the interval.
* @property-read float $totalWeeks Number of weeks equivalent to the interval.
* @property-read float $totalDays Number of days equivalent to the interval.
* @property-read float $totalDayz Alias for totalDays.
* @property-read float $totalHours Number of hours equivalent to the interval.
* @property-read float $totalMinutes Number of minutes equivalent to the interval.
* @property-read float $totalSeconds Number of seconds equivalent to the interval.
* @property-read float $totalMilliseconds Number of milliseconds equivalent to the interval.
* @property-read float $totalMicroseconds Number of microseconds equivalent to the interval.
* @property-read string $locale locale of the current instance
*
* @method static CarbonInterval years($years = 1) Create instance specifying a number of years or modify the number of years if called on an instance.
* @method static CarbonInterval year($years = 1) Alias for years()
* @method static CarbonInterval months($months = 1) Create instance specifying a number of months or modify the number of months if called on an instance.
* @method static CarbonInterval month($months = 1) Alias for months()
* @method static CarbonInterval weeks($weeks = 1) Create instance specifying a number of weeks or modify the number of weeks if called on an instance.
* @method static CarbonInterval week($weeks = 1) Alias for weeks()
* @method static CarbonInterval days($days = 1) Create instance specifying a number of days or modify the number of days if called on an instance.
* @method static CarbonInterval dayz($days = 1) Alias for days()
* @method static CarbonInterval daysExcludeWeeks($days = 1) Create instance specifying a number of days or modify the number of days (keeping the current number of weeks) if called on an instance.
* @method static CarbonInterval dayzExcludeWeeks($days = 1) Alias for daysExcludeWeeks()
* @method static CarbonInterval day($days = 1) Alias for days()
* @method static CarbonInterval hours($hours = 1) Create instance specifying a number of hours or modify the number of hours if called on an instance.
* @method static CarbonInterval hour($hours = 1) Alias for hours()
* @method static CarbonInterval minutes($minutes = 1) Create instance specifying a number of minutes or modify the number of minutes if called on an instance.
* @method static CarbonInterval minute($minutes = 1) Alias for minutes()
* @method static CarbonInterval seconds($seconds = 1) Create instance specifying a number of seconds or modify the number of seconds if called on an instance.
* @method static CarbonInterval second($seconds = 1) Alias for seconds()
* @method static CarbonInterval milliseconds($milliseconds = 1) Create instance specifying a number of milliseconds or modify the number of milliseconds if called on an instance.
* @method static CarbonInterval millisecond($milliseconds = 1) Alias for milliseconds()
* @method static CarbonInterval microseconds($microseconds = 1) Create instance specifying a number of microseconds or modify the number of microseconds if called on an instance.
* @method static CarbonInterval microsecond($microseconds = 1) Alias for microseconds()
* @method $this addYears(int $years) Add given number of years to the current interval
* @method $this subYears(int $years) Subtract given number of years to the current interval
* @method $this addMonths(int $months) Add given number of months to the current interval
* @method $this subMonths(int $months) Subtract given number of months to the current interval
* @method $this addWeeks(int|float $weeks) Add given number of weeks to the current interval
* @method $this subWeeks(int|float $weeks) Subtract given number of weeks to the current interval
* @method $this addDays(int|float $days) Add given number of days to the current interval
* @method $this subDays(int|float $days) Subtract given number of days to the current interval
* @method $this addHours(int|float $hours) Add given number of hours to the current interval
* @method $this subHours(int|float $hours) Subtract given number of hours to the current interval
* @method $this addMinutes(int|float $minutes) Add given number of minutes to the current interval
* @method $this subMinutes(int|float $minutes) Subtract given number of minutes to the current interval
* @method $this addSeconds(int|float $seconds) Add given number of seconds to the current interval
* @method $this subSeconds(int|float $seconds) Subtract given number of seconds to the current interval
* @method $this addMilliseconds(int|float $milliseconds) Add given number of milliseconds to the current interval
* @method $this subMilliseconds(int|float $milliseconds) Subtract given number of milliseconds to the current interval
* @method $this addMicroseconds(int|float $microseconds) Add given number of microseconds to the current interval
* @method $this subMicroseconds(int|float $microseconds) Subtract given number of microseconds to the current interval
* @method $this roundYear(int|float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
* @method $this roundYears(int|float $precision = 1, string $function = "round") Round the current instance year with given precision using the given function.
* @method $this floorYear(int|float $precision = 1) Truncate the current instance year with given precision.
* @method $this floorYears(int|float $precision = 1) Truncate the current instance year with given precision.
* @method $this ceilYear(int|float $precision = 1) Ceil the current instance year with given precision.
* @method $this ceilYears(int|float $precision = 1) Ceil the current instance year with given precision.
* @method $this roundMonth(int|float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
* @method $this roundMonths(int|float $precision = 1, string $function = "round") Round the current instance month with given precision using the given function.
* @method $this floorMonth(int|float $precision = 1) Truncate the current instance month with given precision.
* @method $this floorMonths(int|float $precision = 1) Truncate the current instance month with given precision.
* @method $this ceilMonth(int|float $precision = 1) Ceil the current instance month with given precision.
* @method $this ceilMonths(int|float $precision = 1) Ceil the current instance month with given precision.
* @method $this roundWeek(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
* @method $this roundWeeks(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
* @method $this floorWeek(int|float $precision = 1) Truncate the current instance day with given precision.
* @method $this floorWeeks(int|float $precision = 1) Truncate the current instance day with given precision.
* @method $this ceilWeek(int|float $precision = 1) Ceil the current instance day with given precision.
* @method $this ceilWeeks(int|float $precision = 1) Ceil the current instance day with given precision.
* @method $this roundDay(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
* @method $this roundDays(int|float $precision = 1, string $function = "round") Round the current instance day with given precision using the given function.
* @method $this floorDay(int|float $precision = 1) Truncate the current instance day with given precision.
* @method $this floorDays(int|float $precision = 1) Truncate the current instance day with given precision.
* @method $this ceilDay(int|float $precision = 1) Ceil the current instance day with given precision.
* @method $this ceilDays(int|float $precision = 1) Ceil the current instance day with given precision.
* @method $this roundHour(int|float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
* @method $this roundHours(int|float $precision = 1, string $function = "round") Round the current instance hour with given precision using the given function.
* @method $this floorHour(int|float $precision = 1) Truncate the current instance hour with given precision.
* @method $this floorHours(int|float $precision = 1) Truncate the current instance hour with given precision.
* @method $this ceilHour(int|float $precision = 1) Ceil the current instance hour with given precision.
* @method $this ceilHours(int|float $precision = 1) Ceil the current instance hour with given precision.
* @method $this roundMinute(int|float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
* @method $this roundMinutes(int|float $precision = 1, string $function = "round") Round the current instance minute with given precision using the given function.
* @method $this floorMinute(int|float $precision = 1) Truncate the current instance minute with given precision.
* @method $this floorMinutes(int|float $precision = 1) Truncate the current instance minute with given precision.
* @method $this ceilMinute(int|float $precision = 1) Ceil the current instance minute with given precision.
* @method $this ceilMinutes(int|float $precision = 1) Ceil the current instance minute with given precision.
* @method $this roundSecond(int|float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
* @method $this roundSeconds(int|float $precision = 1, string $function = "round") Round the current instance second with given precision using the given function.
* @method $this floorSecond(int|float $precision = 1) Truncate the current instance second with given precision.
* @method $this floorSeconds(int|float $precision = 1) Truncate the current instance second with given precision.
* @method $this ceilSecond(int|float $precision = 1) Ceil the current instance second with given precision.
* @method $this ceilSeconds(int|float $precision = 1) Ceil the current instance second with given precision.
* @method $this roundMillennium(int|float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
* @method $this roundMillennia(int|float $precision = 1, string $function = "round") Round the current instance millennium with given precision using the given function.
* @method $this floorMillennium(int|float $precision = 1) Truncate the current instance millennium with given precision.
* @method $this floorMillennia(int|float $precision = 1) Truncate the current instance millennium with given precision.
* @method $this ceilMillennium(int|float $precision = 1) Ceil the current instance millennium with given precision.
* @method $this ceilMillennia(int|float $precision = 1) Ceil the current instance millennium with given precision.
* @method $this roundCentury(int|float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
* @method $this roundCenturies(int|float $precision = 1, string $function = "round") Round the current instance century with given precision using the given function.
* @method $this floorCentury(int|float $precision = 1) Truncate the current instance century with given precision.
* @method $this floorCenturies(int|float $precision = 1) Truncate the current instance century with given precision.
* @method $this ceilCentury(int|float $precision = 1) Ceil the current instance century with given precision.
* @method $this ceilCenturies(int|float $precision = 1) Ceil the current instance century with given precision.
* @method $this roundDecade(int|float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
* @method $this roundDecades(int|float $precision = 1, string $function = "round") Round the current instance decade with given precision using the given function.
* @method $this floorDecade(int|float $precision = 1) Truncate the current instance decade with given precision.
* @method $this floorDecades(int|float $precision = 1) Truncate the current instance decade with given precision.
* @method $this ceilDecade(int|float $precision = 1) Ceil the current instance decade with given precision.
* @method $this ceilDecades(int|float $precision = 1) Ceil the current instance decade with given precision.
* @method $this roundQuarter(int|float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
* @method $this roundQuarters(int|float $precision = 1, string $function = "round") Round the current instance quarter with given precision using the given function.
* @method $this floorQuarter(int|float $precision = 1) Truncate the current instance quarter with given precision.
* @method $this floorQuarters(int|float $precision = 1) Truncate the current instance quarter with given precision.
* @method $this ceilQuarter(int|float $precision = 1) Ceil the current instance quarter with given precision.
* @method $this ceilQuarters(int|float $precision = 1) Ceil the current instance quarter with given precision.
* @method $this roundMillisecond(int|float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
* @method $this roundMilliseconds(int|float $precision = 1, string $function = "round") Round the current instance millisecond with given precision using the given function.
* @method $this floorMillisecond(int|float $precision = 1) Truncate the current instance millisecond with given precision.
* @method $this floorMilliseconds(int|float $precision = 1) Truncate the current instance millisecond with given precision.
* @method $this ceilMillisecond(int|float $precision = 1) Ceil the current instance millisecond with given precision.
* @method $this ceilMilliseconds(int|float $precision = 1) Ceil the current instance millisecond with given precision.
* @method $this roundMicrosecond(int|float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
* @method $this roundMicroseconds(int|float $precision = 1, string $function = "round") Round the current instance microsecond with given precision using the given function.
* @method $this floorMicrosecond(int|float $precision = 1) Truncate the current instance microsecond with given precision.
* @method $this floorMicroseconds(int|float $precision = 1) Truncate the current instance microsecond with given precision.
* @method $this ceilMicrosecond(int|float $precision = 1) Ceil the current instance microsecond with given precision.
* @method $this ceilMicroseconds(int|float $precision = 1) Ceil the current instance microsecond with given precision.
*/
class CarbonInterval extends DateInterval implements CarbonConverterInterface
{
use IntervalRounding;
use IntervalStep;
use Mixin {
Mixin::mixin as baseMixin;
}
use Options;
/**
* Interval spec period designators
*/
const PERIOD_PREFIX = 'P';
const PERIOD_YEARS = 'Y';
const PERIOD_MONTHS = 'M';
const PERIOD_DAYS = 'D';
const PERIOD_TIME_PREFIX = 'T';
const PERIOD_HOURS = 'H';
const PERIOD_MINUTES = 'M';
const PERIOD_SECONDS = 'S';
/**
* A translator to ... er ... translate stuff
*
* @var \Symfony\Component\Translation\TranslatorInterface
*/
protected static $translator;
/**
* @var array|null
*/
protected static $cascadeFactors;
/**
* @var array
*/
protected static $formats = [
'y' => 'y',
'Y' => 'y',
'o' => 'y',
'm' => 'm',
'n' => 'm',
'W' => 'weeks',
'd' => 'd',
'j' => 'd',
'z' => 'd',
'h' => 'h',
'g' => 'h',
'H' => 'h',
'G' => 'h',
'i' => 'i',
's' => 's',
'u' => 'micro',
'v' => 'milli',
];
/**
* @var array|null
*/
private static $flipCascadeFactors;
/**
* The registered macros.
*
* @var array
*/
protected static $macros = [];
/**
* Timezone handler for settings() method.
*
* @var mixed
*/
protected $tzName;
/**
* Set the instance's timezone from a string or object and add/subtract the offset difference.
*
* @param \DateTimeZone|string $tzName
*
* @return static
*/
public function shiftTimezone($tzName)
{
$this->tzName = $tzName;
return $this;
}
/**
* Mapping of units and factors for cascading.
*
* Should only be modified by changing the factors or referenced constants.
*
* @return array
*/
public static function getCascadeFactors()
{
return static::$cascadeFactors ?: [
'milliseconds' => [Carbon::MICROSECONDS_PER_MILLISECOND, 'microseconds'],
'seconds' => [Carbon::MILLISECONDS_PER_SECOND, 'milliseconds'],
'minutes' => [Carbon::SECONDS_PER_MINUTE, 'seconds'],
'hours' => [Carbon::MINUTES_PER_HOUR, 'minutes'],
'dayz' => [Carbon::HOURS_PER_DAY, 'hours'],
'weeks' => [Carbon::DAYS_PER_WEEK, 'dayz'],
'months' => [Carbon::WEEKS_PER_MONTH, 'weeks'],
'years' => [Carbon::MONTHS_PER_YEAR, 'months'],
];
}
private static function standardizeUnit($unit)
{
$unit = rtrim($unit, 'sz').'s';
return $unit === 'days' ? 'dayz' : $unit;
}
private static function getFlipCascadeFactors()
{
if (!self::$flipCascadeFactors) {
self::$flipCascadeFactors = [];
foreach (static::getCascadeFactors() as $to => [$factor, $from]) {
self::$flipCascadeFactors[self::standardizeUnit($from)] = [self::standardizeUnit($to), $factor];
}
}
return self::$flipCascadeFactors;
}
/**
* Set default cascading factors for ->cascade() method.
*
* @param array $cascadeFactors
*/
public static function setCascadeFactors(array $cascadeFactors)
{
self::$flipCascadeFactors = null;
static::$cascadeFactors = $cascadeFactors;
}
///////////////////////////////////////////////////////////////////
//////////////////////////// CONSTRUCTORS /////////////////////////
///////////////////////////////////////////////////////////////////
/**
* Create a new CarbonInterval instance.
*
* @param int|null $years
* @param int|null $months
* @param int|null $weeks
* @param int|null $days
* @param int|null $hours
* @param int|null $minutes
* @param int|null $seconds
* @param int|null $microseconds
*
* @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
*/
public function __construct($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
{
if ($years instanceof Closure) {
$this->step = $years;
$years = null;
}
if ($years instanceof DateInterval) {
parent::__construct(static::getDateIntervalSpec($years));
$this->f = $years->f;
static::copyNegativeUnits($years, $this);
return;
}
$spec = $years;
if (!\is_string($spec) || \floatval($years) || preg_match('/^[0-9.]/', $years)) {
$spec = static::PERIOD_PREFIX;
$spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
$spec .= $months > 0 ? $months.static::PERIOD_MONTHS : '';
$specDays = 0;
$specDays += $weeks > 0 ? $weeks * static::getDaysPerWeek() : 0;
$specDays += $days > 0 ? $days : 0;
$spec .= $specDays > 0 ? $specDays.static::PERIOD_DAYS : '';
if ($hours > 0 || $minutes > 0 || $seconds > 0) {
$spec .= static::PERIOD_TIME_PREFIX;
$spec .= $hours > 0 ? $hours.static::PERIOD_HOURS : '';
$spec .= $minutes > 0 ? $minutes.static::PERIOD_MINUTES : '';
$spec .= $seconds > 0 ? $seconds.static::PERIOD_SECONDS : '';
}
if ($spec === static::PERIOD_PREFIX) {
// Allow the zero interval.
$spec .= '0'.static::PERIOD_YEARS;
}
}
parent::__construct($spec);
if (!\is_null($microseconds)) {
$this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
}
}
/**
* Returns the factor for a given source-to-target couple.
*
* @param string $source
* @param string $target
*
* @return int|null
*/
public static function getFactor($source, $target)
{
$source = self::standardizeUnit($source);
$target = self::standardizeUnit($target);
$factors = static::getFlipCascadeFactors();
if (isset($factors[$source])) {
[$to, $factor] = $factors[$source];
if ($to === $target) {
return $factor;
}
return $factor * static::getFactor($to, $target);
}
return null;
}
/**
* Returns current config for days per week.
*
* @return int
*/
public static function getDaysPerWeek()
{
return static::getFactor('dayz', 'weeks') ?: Carbon::DAYS_PER_WEEK;
}
/**
* Returns current config for hours per day.
*
* @return int
*/
public static function getHoursPerDay()
{
return static::getFactor('hours', 'dayz') ?: Carbon::HOURS_PER_DAY;
}
/**
* Returns current config for minutes per hour.
*
* @return int
*/
public static function getMinutesPerHour()
{
return static::getFactor('minutes', 'hours') ?: Carbon::MINUTES_PER_HOUR;
}
/**
* Returns current config for seconds per minute.
*
* @return int
*/
public static function getSecondsPerMinute()
{
return static::getFactor('seconds', 'minutes') ?: Carbon::SECONDS_PER_MINUTE;
}
/**
* Returns current config for microseconds per second.
*
* @return int
*/
public static function getMillisecondsPerSecond()
{
return static::getFactor('milliseconds', 'seconds') ?: Carbon::MILLISECONDS_PER_SECOND;
}
/**
* Returns current config for microseconds per second.
*
* @return int
*/
public static function getMicrosecondsPerMillisecond()
{
return static::getFactor('microseconds', 'milliseconds') ?: Carbon::MICROSECONDS_PER_MILLISECOND;
}
/**
* Create a new CarbonInterval instance from specific values.
* This is an alias for the constructor that allows better fluent
* syntax as it allows you to do CarbonInterval::create(1)->fn() rather than
* (new CarbonInterval(1))->fn().
*
* @param int $years
* @param int $months
* @param int $weeks
* @param int $days
* @param int $hours
* @param int $minutes
* @param int $seconds
* @param int $microseconds
*
* @throws Exception when the interval_spec (passed as $years) cannot be parsed as an interval.
*
* @return static
*/
public static function create($years = 1, $months = null, $weeks = null, $days = null, $hours = null, $minutes = null, $seconds = null, $microseconds = null)
{
return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $microseconds);
}
/**
* Parse a string into a new CarbonInterval object according to the specified format.
*
* @example
* ```
* echo Carboninterval::createFromFormat('H:i', '1:30');
* ```
*
* @param string $format Format of the $interval input string
* @param string $interval Input string to convert into an interval
*
* @throws Exception when the $interval cannot be parsed as an interval.
*
* @return static
*/
public static function createFromFormat(string $format, ?string $interval)
{
$instance = new static(0);
$length = mb_strlen($format);
if (preg_match('/s([,.])([uv])$/', $format, $match)) {
$interval = explode($match[1], $interval);
$index = \count($interval) - 1;
$interval[$index] = str_pad($interval[$index], $match[2] === 'v' ? 3 : 6, '0');
$interval = implode($match[1], $interval);
}
for ($index = 0; $index < $length; $index++) {
$expected = mb_substr($format, $index, 1);
$nextCharacter = mb_substr($interval, 0, 1);
$unit = static::$formats[$expected] ?? null;
if ($unit) {
if (!preg_match('/^-?\d+/', $interval, $match)) {
throw new ParseErrorException('number', $nextCharacter);
}
$interval = mb_substr($interval, mb_strlen($match[0]));
$instance->$unit += \intval($match[0]);
continue;
}
if ($nextCharacter !== $expected) {
throw new ParseErrorException(
"'$expected'",
$nextCharacter,
'Allowed substitutes for interval formats are '.implode(', ', array_keys(static::$formats))."\n".
'See https://www.php.net/manual/en/function.date.php for their meaning'
);
}
$interval = mb_substr($interval, 1);
}
if ($interval !== '') {
throw new ParseErrorException(
'end of string',
$interval
);
}
return $instance;
}
/**
* Get a copy of the instance.
*
* @return static
*/
public function copy()
{
$date = new static(0);
$date->copyProperties($this);
$date->step = $this->step;
return $date;
}
/**
* Get a copy of the instance.
*
* @return static
*/
public function clone()
{
return $this->copy();
}
/**
* Provide static helpers to create instances. Allows CarbonInterval::years(3).
*
* Note: This is done using the magic method to allow static and instance methods to
* have the same names.
*
* @param string $method magic method name called
* @param array $parameters parameters list
*
* @return static|null
*/
public static function __callStatic($method, $parameters)
{
try {
$interval = new static(0);
$localStrictModeEnabled = $interval->localStrictModeEnabled;
$interval->localStrictModeEnabled = true;
$result = static::hasMacro($method)
? static::bindMacroContext(null, function () use (&$method, &$parameters, &$interval) {
return $interval->callMacro($method, $parameters);
})
: $interval->$method(...$parameters);
$interval->localStrictModeEnabled = $localStrictModeEnabled;
return $result;
} catch (BadFluentSetterException $exception) {
if (Carbon::isStrictModeEnabled()) {
throw new BadFluentConstructorException($method, 0, $exception);
}
return null;
}
}
/**
* Return the current context from inside a macro callee or a new one if static.
*
* @return static
*/
protected static function this()
{
return end(static::$macroContextStack) ?: new static(0);
}
/**
* Creates a CarbonInterval from string.
*
* Format:
*
* Suffix | Unit | Example | DateInterval expression
* -------|---------|---------|------------------------
* y | years | 1y | P1Y
* mo | months | 3mo | P3M
* w | weeks | 2w | P2W
* d | days | 28d | P28D
* h | hours | 4h | PT4H
* m | minutes | 12m | PT12M
* s | seconds | 59s | PT59S
*
* e. g. `1w 3d 4h 32m 23s` is converted to 10 days 4 hours 32 minutes and 23 seconds.
*
* Special cases:
* - An empty string will return a zero interval
* - Fractions are allowed for weeks, days, hours and minutes and will be converted
* and rounded to the next smaller value (caution: 0.5w = 4d)
*
* @param string $intervalDefinition
*
* @return static
*/
public static function fromString($intervalDefinition)
{
if (empty($intervalDefinition)) {
return new static(0);
}
$years = 0;
$months = 0;
$weeks = 0;
$days = 0;
$hours = 0;
$minutes = 0;
$seconds = 0;
$milliseconds = 0;
$microseconds = 0;
$pattern = '/(\d+(?:\.\d+)?)\h*([^\d\h]*)/i';
preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
while ([$part, $value, $unit] = array_shift($parts)) {
$intValue = \intval($value);
$fraction = \floatval($value) - $intValue;
// Fix calculation precision
switch (round($fraction, 6)) {
case 1:
$fraction = 0;
$intValue++;
break;
case 0:
$fraction = 0;
break;
}
switch ($unit === 'µs' ? 'µs' : strtolower($unit)) {
case 'millennia':
case 'millennium':
$years += $intValue * CarbonInterface::YEARS_PER_MILLENNIUM;
break;
case 'century':
case 'centuries':
$years += $intValue * CarbonInterface::YEARS_PER_CENTURY;
break;
case 'decade':
case 'decades':
$years += $intValue * CarbonInterface::YEARS_PER_DECADE;
break;
case 'year':
case 'years':
case 'y':
$years += $intValue;
break;
case 'quarter':
case 'quarters':
$months += $intValue * CarbonInterface::MONTHS_PER_QUARTER;
break;
case 'month':
case 'months':
case 'mo':
$months += $intValue;
break;
case 'week':
case 'weeks':
case 'w':
$weeks += $intValue;
if ($fraction) {
$parts[] = [null, $fraction * static::getDaysPerWeek(), 'd'];
}
break;
case 'day':
case 'days':
case 'd':
$days += $intValue;
if ($fraction) {
$parts[] = [null, $fraction * static::getHoursPerDay(), 'h'];
}
break;
case 'hour':
case 'hours':
case 'h':
$hours += $intValue;
if ($fraction) {
$parts[] = [null, $fraction * static::getMinutesPerHour(), 'm'];
}
break;
case 'minute':
case 'minutes':
case 'm':
$minutes += $intValue;
if ($fraction) {
$parts[] = [null, $fraction * static::getSecondsPerMinute(), 's'];
}
break;
case 'second':
case 'seconds':
case 's':
$seconds += $intValue;
if ($fraction) {
$parts[] = [null, $fraction * static::getMillisecondsPerSecond(), 'ms'];
}
break;
case 'millisecond':
case 'milliseconds':
case 'milli':
case 'ms':
$milliseconds += $intValue;
if ($fraction) {
$microseconds += round($fraction * static::getMicrosecondsPerMillisecond());
}
break;
case 'microsecond':
case 'microseconds':
case 'micro':
case 'µs':
$microseconds += $intValue;
break;
default:
throw new InvalidIntervalException(
sprintf('Invalid part %s in definition %s', $part, $intervalDefinition)
);
}
}
return new static($years, $months, $weeks, $days, $hours, $minutes, $seconds, $milliseconds * Carbon::MICROSECONDS_PER_MILLISECOND + $microseconds);
}
/**
* Creates a CarbonInterval from string using a different locale.
*
* @param string $interval interval string in the given language (may also contain English).
* @param string|null $locale if locale is null or not specified, current global locale will be used instead.
*
* @return static
*/
public static function parseFromLocale($interval, $locale = null)
{
return static::fromString(Carbon::translateTimeString($interval, $locale ?: static::getLocale(), 'en'));
}
private static function castIntervalToClass(DateInterval $interval, string $className)
{
$mainClass = DateInterval::class;
if (!is_a($className, $mainClass, true)) {
throw new InvalidCastException("$className is not a sub-class of $mainClass.");
}
$microseconds = $interval->f;
$instance = new $className(static::getDateIntervalSpec($interval));
if ($microseconds) {
$instance->f = $microseconds;
}
if ($interval instanceof self && is_a($className, self::class, true)) {
static::copyStep($interval, $instance);
}
static::copyNegativeUnits($interval, $instance);
return $instance;
}
private static function copyNegativeUnits(DateInterval $from, DateInterval $to): void
{
$to->invert = $from->invert;
foreach (['y', 'm', 'd', 'h', 'i', 's'] as $unit) {
if ($from->$unit < 0) {
$to->$unit *= -1;
}
}
}
private static function copyStep(self $from, self $to): void
{
$to->setStep($from->getStep());
}
/**
* Cast the current instance into the given class.
*
* @param string $className The $className::instance() method will be called to cast the current object.
*
* @return DateInterval
*/
public function cast(string $className)
{
return self::castIntervalToClass($this, $className);
}
/**
* Create a CarbonInterval instance from a DateInterval one. Can not instance
* DateInterval objects created from DateTime::diff() as you can't externally
* set the $days field.
*
* @param DateInterval $interval
*
* @return static
*/
public static function instance(DateInterval $interval)
{
return self::castIntervalToClass($interval, static::class);
}
/**
* Make a CarbonInterval instance from given variable if possible.
*
* Always return a new instance. Parse only strings and only these likely to be intervals (skip dates
* and recurrences). Throw an exception for invalid format, but otherwise return null.
*
* @param mixed|int|DateInterval|string|Closure|null $interval interval or number of the given $unit
* @param string|null $unit if specified, $interval must be an integer
*
* @return static|null
*/
public static function make($interval, $unit = null)
{
if ($unit) {
$interval = "$interval ".Carbon::pluralUnit($unit);
}
if ($interval instanceof DateInterval) {
return static::instance($interval);
}
if ($interval instanceof Closure) {
return new static($interval);
}
if (!\is_string($interval)) {
return null;
}
return static::makeFromString($interval);
}
protected static function makeFromString(string $interval)
{
$interval = preg_replace('/\s+/', ' ', trim($interval));
if (preg_match('/^P[T0-9]/', $interval)) {
return new static($interval);
}
if (preg_match('/^(?:\h*\d+(?:\.\d+)?\h*[a-z]+)+$/i', $interval)) {
return static::fromString($interval);
}
/** @var static $interval */
$interval = static::createFromDateString($interval);
return !$interval || $interval->isEmpty() ? null : $interval;
}
protected function resolveInterval($interval)
{
if (!($interval instanceof self)) {
return self::make($interval);
}
return $interval;
}
/**
* Sets up a DateInterval from the relative parts of the string.
*
* @param string $time
*
* @return static
*
* @link http://php.net/manual/en/dateinterval.createfromdatestring.php
*/
public static function createFromDateString($time)
{
$interval = @parent::createFromDateString(strtr($time, [
',' => ' ',
' and ' => ' ',
]));
if ($interval instanceof DateInterval) {
$interval = static::instance($interval);
}
return $interval;
}
///////////////////////////////////////////////////////////////////
///////////////////////// GETTERS AND SETTERS /////////////////////
///////////////////////////////////////////////////////////////////
/**
* Get a part of the CarbonInterval object.
*
* @param string $name
*
* @throws UnknownGetterException
*
* @return int|float|string
*/
public function get($name)
{
if (substr($name, 0, 5) === 'total') {
return $this->total(substr($name, 5));
}
switch ($name) {
case 'years':
return $this->y;
case 'months':
return $this->m;
case 'dayz':
return $this->d;
case 'hours':
return $this->h;
case 'minutes':
return $this->i;
case 'seconds':
return $this->s;
case 'milli':
case 'milliseconds':
return (int) (round($this->f * Carbon::MICROSECONDS_PER_SECOND) / Carbon::MICROSECONDS_PER_MILLISECOND);
case 'micro':
case 'microseconds':
return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND);
case 'microExcludeMilli':
return (int) round($this->f * Carbon::MICROSECONDS_PER_SECOND) % Carbon::MICROSECONDS_PER_MILLISECOND;
case 'weeks':
return (int) ($this->d / static::getDaysPerWeek());
case 'daysExcludeWeeks':
case 'dayzExcludeWeeks':
return $this->d % static::getDaysPerWeek();
case 'locale':
return $this->getTranslatorLocale();
default:
throw new UnknownGetterException($name);
}
}
/**
* Get a part of the CarbonInterval object.
*
* @param string $name
*
* @throws UnknownGetterException
*
* @return int|float|string
*/
public function __get($name)
{
return $this->get($name);
}
/**
* Set a part of the CarbonInterval object.
*
* @param string|array $name
* @param int $value
*
* @throws UnknownSetterException
*
* @return $this
*/
public function set($name, $value = null)
{
$properties = \is_array($name) ? $name : [$name => $value];
foreach ($properties as $key => $value) {
switch (Carbon::singularUnit(rtrim($key, 'z'))) {
case 'year':
$this->y = $value;
break;
case 'month':
$this->m = $value;
break;
case 'week':
$this->d = $value * static::getDaysPerWeek();
break;
case 'day':
$this->d = $value;
break;
case 'daysexcludeweek':
case 'dayzexcludeweek':
$this->d = $this->weeks * static::getDaysPerWeek() + $value;
break;
case 'hour':
$this->h = $value;
break;
case 'minute':
$this->i = $value;
break;
case 'second':
$this->s = $value;
break;
case 'milli':
case 'millisecond':
$this->microseconds = $value * Carbon::MICROSECONDS_PER_MILLISECOND + $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND;
break;
case 'micro':
case 'microsecond':
$this->f = $value / Carbon::MICROSECONDS_PER_SECOND;
break;
default:
if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
throw new UnknownSetterException($key);
}
$this->$key = $value;
}
}
return $this;
}
/**
* Set a part of the CarbonInterval object.
*
* @param string $name
* @param int $value
*
* @throws UnknownSetterException
*/
public function __set($name, $value)
{
$this->set($name, $value);
}
/**
* Allow setting of weeks and days to be cumulative.
*
* @param int $weeks Number of weeks to set
* @param int $days Number of days to set
*
* @return static
*/
public function weeksAndDays($weeks, $days)
{
$this->dayz = ($weeks * static::getDaysPerWeek()) + $days;
return $this;
}
/**
* Returns true if the interval is empty for each unit.
*
* @return bool
*/
public function isEmpty()
{
return $this->years === 0 &&
$this->months === 0 &&
$this->dayz === 0 &&
!$this->days &&
$this->hours === 0 &&
$this->minutes === 0 &&
$this->seconds === 0 &&
$this->microseconds === 0;
}
/**
* Register a custom macro.
*
* @example
* ```
* CarbonInterval::macro('twice', function () {
* return $this->times(2);
* });
* echo CarbonInterval::hours(2)->twice();
* ```
*
* @param string $name
* @param object|callable $macro
*
* @return void
*/
public static function macro($name, $macro)
{
static::$macros[$name] = $macro;
}
/**
* Register macros from a mixin object.
*
* @example
* ```
* CarbonInterval::mixin(new class {
* public function daysToHours() {
* return function () {
* $this->hours += $this->days;
* $this->days = 0;
*
* return $this;
* };
* }
* public function hoursToDays() {
* return function () {
* $this->days += $this->hours;
* $this->hours = 0;
*
* return $this;
* };
* }
* });
* echo CarbonInterval::hours(5)->hoursToDays() . "\n";
* echo CarbonInterval::days(5)->daysToHours() . "\n";
* ```
*
* @param object|string $mixin
*
* @throws ReflectionException
*
* @return void
*/
public static function mixin($mixin)
{
static::baseMixin($mixin);
}
/**
* Check if macro is registered.
*
* @param string $name
*
* @return bool
*/
public static function hasMacro($name)
{
return isset(static::$macros[$name]);
}
/**
* Call given macro.
*
* @param string $name
* @param array $parameters
*
* @return mixed
*/
protected function callMacro($name, $parameters)
{
$macro = static::$macros[$name];
if ($macro instanceof Closure) {
$boundMacro = @$macro->bindTo($this, static::class) ?: @$macro->bindTo(null, static::class);
return ($boundMacro ?: $macro)(...$parameters);
}
return $macro(...$parameters);
}
/**
* Allow fluent calls on the setters... CarbonInterval::years(3)->months(5)->day().
*
* Note: This is done using the magic method to allow static and instance methods to
* have the same names.
*
* @param string $method magic method name called
* @param array $parameters parameters list
*
* @throws BadFluentSetterException|Throwable
*
* @return static
*/
public function __call($method, $parameters)
{
if (static::hasMacro($method)) {
return static::bindMacroContext($this, function () use (&$method, &$parameters) {
return $this->callMacro($method, $parameters);
});
}
$roundedValue = $this->callRoundMethod($method, $parameters);
if ($roundedValue !== null) {
return $roundedValue;
}
if (preg_match('/^(?add|sub)(?[A-Z].*)$/', $method, $match)) {
return $this->{$match['method']}($parameters[0], $match['unit']);
}
try {
$this->set($method, \count($parameters) === 0 ? 1 : $parameters[0]);
} catch (UnknownSetterException $exception) {
if ($this->localStrictModeEnabled ?? Carbon::isStrictModeEnabled()) {
throw new BadFluentSetterException($method, 0, $exception);
}
}
return $this;
}
protected function getForHumansInitialVariables($syntax, $short)
{
if (\is_array($syntax)) {
return $syntax;
}
if (\is_int($short)) {
return [
'parts' => $short,
'short' => false,
];
}
if (\is_bool($syntax)) {
return [
'short' => $syntax,
'syntax' => CarbonInterface::DIFF_ABSOLUTE,
];
}
return [];
}
/**
* @param mixed $syntax
* @param mixed $short
* @param mixed $parts
* @param mixed $options
*
* @return array
*/
protected function getForHumansParameters($syntax = null, $short = false, $parts = -1, $options = null)
{
$optionalSpace = ' ';
$default = $this->getTranslationMessage('list.0') ?? $this->getTranslationMessage('list') ?? ' ';
$join = $default === '' ? '' : ' ';
$altNumbers = false;
$aUnit = false;
$minimumUnit = 's';
extract($this->getForHumansInitialVariables($syntax, $short));
if (\is_null($syntax)) {
$syntax = CarbonInterface::DIFF_ABSOLUTE;
}
if ($parts === -1) {
$parts = INF;
}
if (\is_null($options)) {
$options = static::getHumanDiffOptions();
}
if ($join === false) {
$join = ' ';
} elseif ($join === true) {
$join = [
$default,
$this->getTranslationMessage('list.1') ?? $default,
];
}
if ($altNumbers) {
if ($altNumbers !== true) {
$language = new Language($this->locale);
$altNumbers = \in_array($language->getCode(), (array) $altNumbers);
}
}
if (\is_array($join)) {
[$default, $last] = $join;
if ($default !== ' ') {
$optionalSpace = '';
}
$join = function ($list) use ($default, $last) {
if (\count($list) < 2) {
return implode('', $list);
}
$end = array_pop($list);
return implode($default, $list).$last.$end;
};
}
if (\is_string($join)) {
if ($join !== ' ') {
$optionalSpace = '';
}
$glue = $join;
$join = function ($list) use ($glue) {
return implode($glue, $list);
};
}
$interpolations = [
':optional-space' => $optionalSpace,
];
return [$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit];
}
protected static function getRoundingMethodFromOptions(int $options): ?string
{
if ($options & CarbonInterface::ROUND) {
return 'round';
}
if ($options & CarbonInterface::CEIL) {
return 'ceil';
}
if ($options & CarbonInterface::FLOOR) {
return 'floor';
}
return null;
}
/**
* Returns interval values as an array where key are the unit names and values the counts.
*
* @return int[]
*/
public function toArray()
{
return [
'years' => $this->years,
'months' => $this->months,
'weeks' => $this->weeks,
'days' => $this->daysExcludeWeeks,
'hours' => $this->hours,
'minutes' => $this->minutes,
'seconds' => $this->seconds,
'microseconds' => $this->microseconds,
];
}
/**
* Returns interval non-zero values as an array where key are the unit names and values the counts.
*
* @return int[]
*/
public function getNonZeroValues()
{
return array_filter($this->toArray(), 'intval');
}
/**
* Returns interval values as an array where key are the unit names and values the counts
* from the biggest non-zero one the the smallest non-zero one.
*
* @return int[]
*/
public function getValuesSequence()
{
$nonZeroValues = $this->getNonZeroValues();
if ($nonZeroValues === []) {
return [];
}
$keys = array_keys($nonZeroValues);
$firstKey = $keys[0];
$lastKey = $keys[\count($keys) - 1];
$values = [];
$record = false;
foreach ($this->toArray() as $unit => $count) {
if ($unit === $firstKey) {
$record = true;
}
if ($record) {
$values[$unit] = $count;
}
if ($unit === $lastKey) {
$record = false;
}
}
return $values;
}
/**
* Get the current interval in a human readable format in the current locale.
*
* @example
* ```
* echo CarbonInterval::fromString('4d 3h 40m')->forHumans() . "\n";
* echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 2]) . "\n";
* echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['parts' => 3, 'join' => true]) . "\n";
* echo CarbonInterval::fromString('4d 3h 40m')->forHumans(['short' => true]) . "\n";
* echo CarbonInterval::fromString('1d 24h')->forHumans(['join' => ' or ']) . "\n";
* echo CarbonInterval::fromString('1d 24h')->forHumans(['minimumUnit' => 'hour']) . "\n";
* ```
*
* @param int|array $syntax if array passed, parameters will be extracted from it, the array may contains:
* - 'syntax' entry (see below)
* - 'short' entry (see below)
* - 'parts' entry (see below)
* - 'options' entry (see below)
* - 'aUnit' entry, prefer "an hour" over "1 hour" if true
* - 'join' entry determines how to join multiple parts of the string
* ` - if $join is a string, it's used as a joiner glue
* ` - if $join is a callable/closure, it get the list of string and should return a string
* ` - if $join is an array, the first item will be the default glue, and the second item
* ` will be used instead of the glue for the last item
* ` - if $join is true, it will be guessed from the locale ('list' translation file entry)
* ` - if $join is missing, a space will be used as glue
* - 'minimumUnit' entry determines the smallest unit of time to display can be long or
* ` short form of the units, e.g. 'hour' or 'h' (default value: s)
* if int passed, it add modifiers:
* Possible values:
* - CarbonInterface::DIFF_ABSOLUTE no modifiers
* - CarbonInterface::DIFF_RELATIVE_TO_NOW add ago/from now modifier
* - CarbonInterface::DIFF_RELATIVE_TO_OTHER add before/after modifier
* Default value: CarbonInterface::DIFF_ABSOLUTE
* @param bool $short displays short format of time units
* @param int $parts maximum number of parts to display (default value: -1: no limits)
* @param int $options human diff options
*
* @throws Exception
*
* @return string
*/
public function forHumans($syntax = null, $short = false, $parts = -1, $options = null)
{
[$syntax, $short, $parts, $options, $join, $aUnit, $altNumbers, $interpolations, $minimumUnit] = $this->getForHumansParameters($syntax, $short, $parts, $options);
$interval = [];
$syntax = (int) ($syntax === null ? CarbonInterface::DIFF_ABSOLUTE : $syntax);
$absolute = $syntax === CarbonInterface::DIFF_ABSOLUTE;
$relativeToNow = $syntax === CarbonInterface::DIFF_RELATIVE_TO_NOW;
$count = 1;
$unit = $short ? 's' : 'second';
$isFuture = $this->invert === 1;
$transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
/** @var \Symfony\Component\Translation\Translator $translator */
$translator = $this->getLocalTranslator();
$handleDeclensions = function ($unit, $count) use ($interpolations, $transId, $translator, $altNumbers, $absolute) {
if (!$absolute) {
// Some languages have special pluralization for past and future tense.
$key = $unit.'_'.$transId;
$result = $this->translate($key, $interpolations, $count, $translator, $altNumbers);
if ($result !== $key) {
return $result;
}
}
$result = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
if ($result !== $unit) {
return $result;
}
return null;
};
$intervalValues = $this;
$method = static::getRoundingMethodFromOptions($options);
if ($method) {
$previousCount = INF;
while (
\count($intervalValues->getNonZeroValues()) > $parts &&
($count = \count($keys = array_keys($intervalValues->getValuesSequence()))) > 1
) {
$intervalValues = $this->copy()->roundUnit(
$keys[min($count, $previousCount - 1) - 2],
1,
$method
);
$previousCount = $count;
}
}
$diffIntervalArray = [
['value' => $intervalValues->years, 'unit' => 'year', 'unitShort' => 'y'],
['value' => $intervalValues->months, 'unit' => 'month', 'unitShort' => 'm'],
['value' => $intervalValues->weeks, 'unit' => 'week', 'unitShort' => 'w'],
['value' => $intervalValues->daysExcludeWeeks, 'unit' => 'day', 'unitShort' => 'd'],
['value' => $intervalValues->hours, 'unit' => 'hour', 'unitShort' => 'h'],
['value' => $intervalValues->minutes, 'unit' => 'minute', 'unitShort' => 'min'],
['value' => $intervalValues->seconds, 'unit' => 'second', 'unitShort' => 's'],
['value' => $intervalValues->milliseconds, 'unit' => 'millisecond', 'unitShort' => 'ms'],
['value' => $intervalValues->microExcludeMilli, 'unit' => 'microsecond', 'unitShort' => 'µs'],
];
$transChoice = function ($short, $unitData) use ($absolute, $handleDeclensions, $translator, $aUnit, $altNumbers, $interpolations) {
$count = $unitData['value'];
if ($short) {
$result = $handleDeclensions($unitData['unitShort'], $count);
if ($result !== null) {
return $result;
}
} elseif ($aUnit) {
$result = $handleDeclensions('a_'.$unitData['unit'], $count);
if ($result !== null) {
return $result;
}
}
if (!$absolute) {
return $handleDeclensions($unitData['unit'], $count);
}
return $this->translate($unitData['unit'], $interpolations, $count, $translator, $altNumbers);
};
$fallbackUnit = ['second', 's'];
foreach ($diffIntervalArray as $diffIntervalData) {
if ($diffIntervalData['value'] > 0) {
$unit = $short ? $diffIntervalData['unitShort'] : $diffIntervalData['unit'];
$count = $diffIntervalData['value'];
$interval[] = $transChoice($short, $diffIntervalData);
} elseif ($options & CarbonInterface::SEQUENTIAL_PARTS_ONLY && \count($interval) > 0) {
break;
}
// break the loop after we get the required number of parts in array
if (\count($interval) >= $parts) {
break;
}
// break the loop after we have reached the minimum unit
if (\in_array($minimumUnit, [$diffIntervalData['unit'], $diffIntervalData['unitShort']])) {
$fallbackUnit = [$diffIntervalData['unit'], $diffIntervalData['unitShort']];
break;
}
}
if (\count($interval) === 0) {
if ($relativeToNow && $options & CarbonInterface::JUST_NOW) {
$key = 'diff_now';
$translation = $this->translate($key, $interpolations, null, $translator);
if ($translation !== $key) {
return $translation;
}
}
$count = $options & CarbonInterface::NO_ZERO_DIFF ? 1 : 0;
$unit = $fallbackUnit[$short ? 1 : 0];
$interval[] = $this->translate($unit, $interpolations, $count, $translator, $altNumbers);
}
// join the interval parts by a space
$time = $join($interval);
unset($diffIntervalArray, $interval);
if ($absolute) {
return $time;
}
$isFuture = $this->invert === 1;
$transId = $relativeToNow ? ($isFuture ? 'from_now' : 'ago') : ($isFuture ? 'after' : 'before');
if ($parts === 1) {
if ($relativeToNow && $unit === 'day') {
if ($count === 1 && $options & CarbonInterface::ONE_DAY_WORDS) {
$key = $isFuture ? 'diff_tomorrow' : 'diff_yesterday';
$translation = $this->translate($key, $interpolations, null, $translator);
if ($translation !== $key) {
return $translation;
}
}
if ($count === 2 && $options & CarbonInterface::TWO_DAY_WORDS) {
$key = $isFuture ? 'diff_after_tomorrow' : 'diff_before_yesterday';
$translation = $this->translate($key, $interpolations, null, $translator);
if ($translation !== $key) {
return $translation;
}
}
}
$aTime = $aUnit ? $handleDeclensions('a_'.$unit, $count) : null;
$time = $aTime ?: $handleDeclensions($unit, $count) ?: $time;
}
$time = [':time' => $time];
return $this->translate($transId, array_merge($time, $interpolations, $time), null, $translator);
}
/**
* Format the instance as a string using the forHumans() function.
*
* @throws Exception
*
* @return string
*/
public function __toString()
{
$format = $this->localToStringFormat;
if ($format) {
if ($format instanceof Closure) {
return $format($this);
}
return $this->format($format);
}
return $this->forHumans();
}
/**
* Return native DateInterval PHP object matching the current instance.
*
* @example
* ```
* var_dump(CarbonInterval::hours(2)->toDateInterval());
* ```
*
* @return DateInterval
*/
public function toDateInterval()
{
return self::castIntervalToClass($this, DateInterval::class);
}
/**
* Convert the interval to a CarbonPeriod.
*
* @param array ...$params Start date, [end date or recurrences] and optional settings.
*
* @return CarbonPeriod
*/
public function toPeriod(...$params)
{
return CarbonPeriod::create($this, ...$params);
}
/**
* Invert the interval.
*
* @param bool|int $inverted if a parameter is passed, the passed value casted as 1 or 0 is used
* as the new value of the ->invert property.
*
* @return $this
*/
public function invert($inverted = null)
{
$this->invert = (\func_num_args() === 0 ? !$this->invert : $inverted) ? 1 : 0;
return $this;
}
protected function solveNegativeInterval()
{
if (!$this->isEmpty() && $this->years <= 0 && $this->months <= 0 && $this->dayz <= 0 && $this->hours <= 0 && $this->minutes <= 0 && $this->seconds <= 0 && $this->microseconds <= 0) {
$this->years *= -1;
$this->months *= -1;
$this->dayz *= -1;
$this->hours *= -1;
$this->minutes *= -1;
$this->seconds *= -1;
$this->microseconds *= -1;
$this->invert();
}
return $this;
}
/**
* Add the passed interval to the current instance.
*
* @param string|DateInterval $unit
* @param int|float $value
*
* @return $this
*/
public function add($unit, $value = 1)
{
if (is_numeric($unit)) {
[$value, $unit] = [$unit, $value];
}
if (\is_string($unit) && !preg_match('/^\s*\d/', $unit)) {
$unit = "$value $unit";
$value = 1;
}
$interval = static::make($unit);
if (!$interval) {
throw new InvalidIntervalException('This type of data cannot be added/subtracted.');
}
if ($value !== 1) {
$interval->times($value);
}
$sign = ($this->invert === 1) !== ($interval->invert === 1) ? -1 : 1;
$this->years += $interval->y * $sign;
$this->months += $interval->m * $sign;
$this->dayz += ($interval->days === false ? $interval->d : $interval->days) * $sign;
$this->hours += $interval->h * $sign;
$this->minutes += $interval->i * $sign;
$this->seconds += $interval->s * $sign;
$this->microseconds += $interval->microseconds * $sign;
$this->solveNegativeInterval();
return $this;
}
/**
* Subtract the passed interval to the current instance.
*
* @param string|DateInterval $unit
* @param int|float $value
*
* @return $this
*/
public function sub($unit, $value = 1)
{
if (is_numeric($unit)) {
[$value, $unit] = [$unit, $value];
}
return $this->add($unit, -\floatval($value));
}
/**
* Subtract the passed interval to the current instance.
*
* @param string|DateInterval $unit
* @param int|float $value
*
* @return $this
*/
public function subtract($unit, $value = 1)
{
return $this->sub($unit, $value);
}
/**
* Add given parameters to the current interval.
*
* @param int $years
* @param int $months
* @param int|float $weeks
* @param int|float $days
* @param int|float $hours
* @param int|float $minutes
* @param int|float $seconds
* @param int|float $microseconds
*
* @return $this
*/
public function plus(
$years = 0,
$months = 0,
$weeks = 0,
$days = 0,
$hours = 0,
$minutes = 0,
$seconds = 0,
$microseconds = 0
): self {
return $this->add("
$years years $months months $weeks weeks $days days
$hours hours $minutes minutes $seconds seconds $microseconds microseconds
");
}
/**
* Add given parameters to the current interval.
*
* @param int $years
* @param int $months
* @param int|float $weeks
* @param int|float $days
* @param int|float $hours
* @param int|float $minutes
* @param int|float $seconds
* @param int|float $microseconds
*
* @return $this
*/
public function minus(
$years = 0,
$months = 0,
$weeks = 0,
$days = 0,
$hours = 0,
$minutes = 0,
$seconds = 0,
$microseconds = 0
): self {
return $this->sub("
$years years $months months $weeks weeks $days days
$hours hours $minutes minutes $seconds seconds $microseconds microseconds
");
}
/**
* Multiply current instance given number of times. times() is naive, it multiplies each unit
* (so day can be greater than 31, hour can be greater than 23, etc.) and the result is rounded
* separately for each unit.
*
* Use times() when you want a fast and approximated calculation that does not cascade units.
*
* For a precise and cascaded calculation,
*
* @see multiply()
*
* @param float|int $factor
*
* @return $this
*/
public function times($factor)
{
if ($factor < 0) {
$this->invert = $this->invert ? 0 : 1;
$factor = -$factor;
}
$this->years = (int) round($this->years * $factor);
$this->months = (int) round($this->months * $factor);
$this->dayz = (int) round($this->dayz * $factor);
$this->hours = (int) round($this->hours * $factor);
$this->minutes = (int) round($this->minutes * $factor);
$this->seconds = (int) round($this->seconds * $factor);
$this->microseconds = (int) round($this->microseconds * $factor);
return $this;
}
/**
* Divide current instance by a given divider. shares() is naive, it divides each unit separately
* and the result is rounded for each unit. So 5 hours and 20 minutes shared by 3 becomes 2 hours
* and 7 minutes.
*
* Use shares() when you want a fast and approximated calculation that does not cascade units.
*
* For a precise and cascaded calculation,
*
* @see divide()
*
* @param float|int $divider
*
* @return $this
*/
public function shares($divider)
{
return $this->times(1 / $divider);
}
protected function copyProperties(self $interval, $ignoreSign = false)
{
$this->years = $interval->years;
$this->months = $interval->months;
$this->dayz = $interval->dayz;
$this->hours = $interval->hours;
$this->minutes = $interval->minutes;
$this->seconds = $interval->seconds;
$this->microseconds = $interval->microseconds;
if (!$ignoreSign) {
$this->invert = $interval->invert;
}
return $this;
}
/**
* Multiply and cascade current instance by a given factor.
*
* @param float|int $factor
*
* @return $this
*/
public function multiply($factor)
{
if ($factor < 0) {
$this->invert = $this->invert ? 0 : 1;
$factor = -$factor;
}
$yearPart = (int) floor($this->years * $factor); // Split calculation to prevent imprecision
if ($yearPart) {
$this->years -= $yearPart / $factor;
}
return $this->copyProperties(
static::create($yearPart)
->microseconds(abs($this->totalMicroseconds) * $factor)
->cascade(),
true
);
}
/**
* Divide and cascade current instance by a given divider.
*
* @param float|int $divider
*
* @return $this
*/
public function divide($divider)
{
return $this->multiply(1 / $divider);
}
/**
* Get the interval_spec string of a date interval.
*
* @param DateInterval $interval
*
* @return string
*/
public static function getDateIntervalSpec(DateInterval $interval)
{
$date = array_filter([
static::PERIOD_YEARS => abs($interval->y),
static::PERIOD_MONTHS => abs($interval->m),
static::PERIOD_DAYS => abs($interval->d),
]);
$time = array_filter([
static::PERIOD_HOURS => abs($interval->h),
static::PERIOD_MINUTES => abs($interval->i),
static::PERIOD_SECONDS => abs($interval->s),
]);
$specString = static::PERIOD_PREFIX;
foreach ($date as $key => $value) {
$specString .= $value.$key;
}
if (\count($time) > 0) {
$specString .= static::PERIOD_TIME_PREFIX;
foreach ($time as $key => $value) {
$specString .= $value.$key;
}
}
return $specString === static::PERIOD_PREFIX ? 'PT0S' : $specString;
}
/**
* Get the interval_spec string.
*
* @return string
*/
public function spec()
{
return static::getDateIntervalSpec($this);
}
/**
* Comparing 2 date intervals.
*
* @param DateInterval $first
* @param DateInterval $second
*
* @return int
*/
public static function compareDateIntervals(DateInterval $first, DateInterval $second)
{
$current = Carbon::now();
$passed = $current->copy()->add($second);
$current->add($first);
if ($current < $passed) {
return -1;
}
if ($current > $passed) {
return 1;
}
return 0;
}
/**
* Comparing with passed interval.
*
* @param DateInterval $interval
*
* @return int
*/
public function compare(DateInterval $interval)
{
return static::compareDateIntervals($this, $interval);
}
private function invertCascade(array $values)
{
return $this->set(array_map(function ($value) {
return -$value;
}, $values))->doCascade(true)->invert();
}
private function doCascade(bool $deep)
{
$originalData = $this->toArray();
$originalData['milliseconds'] = (int) ($originalData['microseconds'] / static::getMicrosecondsPerMillisecond());
$originalData['microseconds'] = $originalData['microseconds'] % static::getMicrosecondsPerMillisecond();
$originalData['daysExcludeWeeks'] = $originalData['days'];
unset($originalData['days']);
$newData = $originalData;
foreach (static::getFlipCascadeFactors() as $source => [$target, $factor]) {
foreach (['source', 'target'] as $key) {
if ($$key === 'dayz') {
$$key = 'daysExcludeWeeks';
}
}
$value = $newData[$source];
$modulo = ($factor + ($value % $factor)) % $factor;
$newData[$source] = $modulo;
$newData[$target] += ($value - $modulo) / $factor;
}
$positive = null;
if (!$deep) {
foreach ($newData as $value) {
if ($value) {
if ($positive === null) {
$positive = ($value > 0);
continue;
}
if (($value > 0) !== $positive) {
return $this->invertCascade($originalData)
->solveNegativeInterval();
}
}
}
}
return $this->set($newData)
->solveNegativeInterval();
}
/**
* Convert overflowed values into bigger units.
*
* @return $this
*/
public function cascade()
{
return $this->doCascade(false);
}
public function hasNegativeValues(): bool
{
foreach ($this->toArray() as $value) {
if ($value < 0) {
return true;
}
}
return false;
}
public function hasPositiveValues(): bool
{
foreach ($this->toArray() as $value) {
if ($value > 0) {
return true;
}
}
return false;
}
/**
* Get amount of given unit equivalent to the interval.
*
* @param string $unit
*
* @throws UnknownUnitException|UnitNotConfiguredException
*
* @return float
*/
public function total($unit)
{
$realUnit = $unit = strtolower($unit);
if (\in_array($unit, ['days', 'weeks'])) {
$realUnit = 'dayz';
} elseif (!\in_array($unit, ['microseconds', 'milliseconds', 'seconds', 'minutes', 'hours', 'dayz', 'months', 'years'])) {
throw new UnknownUnitException($unit);
}
$result = 0;
$cumulativeFactor = 0;
$unitFound = false;
$factors = static::getFlipCascadeFactors();
$daysPerWeek = static::getDaysPerWeek();
$values = [
'years' => $this->years,
'months' => $this->months,
'weeks' => (int) ($this->d / $daysPerWeek),
'dayz' => (int) ($this->d % $daysPerWeek),
'hours' => $this->hours,
'minutes' => $this->minutes,
'seconds' => $this->seconds,
'milliseconds' => (int) ($this->microseconds / Carbon::MICROSECONDS_PER_MILLISECOND),
'microseconds' => (int) ($this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND),
];
if (isset($factors['dayz']) && $factors['dayz'][0] !== 'weeks') {
$values['dayz'] += $values['weeks'] * $daysPerWeek;
$values['weeks'] = 0;
}
foreach ($factors as $source => [$target, $factor]) {
if ($source === $realUnit) {
$unitFound = true;
$value = $values[$source];
$result += $value;
$cumulativeFactor = 1;
}
if ($factor === false) {
if ($unitFound) {
break;
}
$result = 0;
$cumulativeFactor = 0;
continue;
}
if ($target === $realUnit) {
$unitFound = true;
}
if ($cumulativeFactor) {
$cumulativeFactor *= $factor;
$result += $values[$target] * $cumulativeFactor;
continue;
}
$value = $values[$source];
$result = ($result + $value) / $factor;
}
if (isset($target) && !$cumulativeFactor) {
$result += $values[$target];
}
if (!$unitFound) {
throw new UnitNotConfiguredException($unit);
}
if ($this->invert) {
$result *= -1;
}
if ($unit === 'weeks') {
return $result / $daysPerWeek;
}
return $result;
}
/**
* Determines if the instance is equal to another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @see equalTo()
*
* @return bool
*/
public function eq($interval): bool
{
return $this->equalTo($interval);
}
/**
* Determines if the instance is equal to another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @return bool
*/
public function equalTo($interval): bool
{
$interval = $this->resolveInterval($interval);
return $interval !== null && $this->totalMicroseconds === $interval->totalMicroseconds;
}
/**
* Determines if the instance is not equal to another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @see notEqualTo()
*
* @return bool
*/
public function ne($interval): bool
{
return $this->notEqualTo($interval);
}
/**
* Determines if the instance is not equal to another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @return bool
*/
public function notEqualTo($interval): bool
{
return !$this->eq($interval);
}
/**
* Determines if the instance is greater (longer) than another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @see greaterThan()
*
* @return bool
*/
public function gt($interval): bool
{
return $this->greaterThan($interval);
}
/**
* Determines if the instance is greater (longer) than another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @return bool
*/
public function greaterThan($interval): bool
{
$interval = $this->resolveInterval($interval);
return $interval === null || $this->totalMicroseconds > $interval->totalMicroseconds;
}
/**
* Determines if the instance is greater (longer) than or equal to another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @see greaterThanOrEqualTo()
*
* @return bool
*/
public function gte($interval): bool
{
return $this->greaterThanOrEqualTo($interval);
}
/**
* Determines if the instance is greater (longer) than or equal to another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @return bool
*/
public function greaterThanOrEqualTo($interval): bool
{
return $this->greaterThan($interval) || $this->equalTo($interval);
}
/**
* Determines if the instance is less (shorter) than another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @see lessThan()
*
* @return bool
*/
public function lt($interval): bool
{
return $this->lessThan($interval);
}
/**
* Determines if the instance is less (shorter) than another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @return bool
*/
public function lessThan($interval): bool
{
$interval = $this->resolveInterval($interval);
return $interval !== null && $this->totalMicroseconds < $interval->totalMicroseconds;
}
/**
* Determines if the instance is less (shorter) than or equal to another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @see lessThanOrEqualTo()
*
* @return bool
*/
public function lte($interval): bool
{
return $this->lessThanOrEqualTo($interval);
}
/**
* Determines if the instance is less (shorter) than or equal to another
*
* @param CarbonInterval|DateInterval|mixed $interval
*
* @return bool
*/
public function lessThanOrEqualTo($interval): bool
{
return $this->lessThan($interval) || $this->equalTo($interval);
}
/**
* Determines if the instance is between two others.
*
* The third argument allow you to specify if bounds are included or not (true by default)
* but for when you including/excluding bounds may produce different results in your application,
* we recommend to use the explicit methods ->betweenIncluded() or ->betweenExcluded() instead.
*
* @example
* ```
* CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(3)); // true
* CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::hours(36)); // false
* CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2)); // true
* CarbonInterval::hours(48)->between(CarbonInterval::day(), CarbonInterval::days(2), false); // false
* ```
*
* @param CarbonInterval|DateInterval|mixed $interval1
* @param CarbonInterval|DateInterval|mixed $interval2
* @param bool $equal Indicates if an equal to comparison should be done
*
* @return bool
*/
public function between($interval1, $interval2, $equal = true): bool
{
return $equal
? $this->greaterThanOrEqualTo($interval1) && $this->lessThanOrEqualTo($interval2)
: $this->greaterThan($interval1) && $this->lessThan($interval2);
}
/**
* Determines if the instance is between two others, bounds excluded.
*
* @example
* ```
* CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
* CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
* CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // true
* ```
*
* @param CarbonInterval|DateInterval|mixed $interval1
* @param CarbonInterval|DateInterval|mixed $interval2
*
* @return bool
*/
public function betweenIncluded($interval1, $interval2): bool
{
return $this->between($interval1, $interval2, true);
}
/**
* Determines if the instance is between two others, bounds excluded.
*
* @example
* ```
* CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(3)); // true
* CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::hours(36)); // false
* CarbonInterval::hours(48)->betweenExcluded(CarbonInterval::day(), CarbonInterval::days(2)); // false
* ```
*
* @param CarbonInterval|DateInterval|mixed $interval1
* @param CarbonInterval|DateInterval|mixed $interval2
*
* @return bool
*/
public function betweenExcluded($interval1, $interval2): bool
{
return $this->between($interval1, $interval2, false);
}
/**
* Determines if the instance is between two others
*
* @example
* ```
* CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(3)); // true
* CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::hours(36)); // false
* CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2)); // true
* CarbonInterval::hours(48)->isBetween(CarbonInterval::day(), CarbonInterval::days(2), false); // false
* ```
*
* @param CarbonInterval|DateInterval|mixed $interval1
* @param CarbonInterval|DateInterval|mixed $interval2
* @param bool $equal Indicates if an equal to comparison should be done
*
* @return bool
*/
public function isBetween($interval1, $interval2, $equal = true): bool
{
return $this->between($interval1, $interval2, $equal);
}
/**
* Round the current instance at the given unit with given precision if specified and the given function.
*
* @param string $unit
* @param float|int|string|DateInterval|null $precision
* @param string $function
*
* @throws Exception
*
* @return $this
*/
public function roundUnit($unit, $precision = 1, $function = 'round')
{
$base = CarbonImmutable::parse('2000-01-01 00:00:00', 'UTC')
->roundUnit($unit, $precision, $function);
$next = $base->add($this);
$inverted = $next < $base;
if ($inverted) {
$next = $base->sub($this);
}
$this->copyProperties(
$next
->roundUnit($unit, $precision, $function)
->diffAsCarbonInterval($base)
);
return $this->invert($inverted);
}
/**
* Truncate the current instance at the given unit with given precision if specified.
*
* @param string $unit
* @param float|int|string|DateInterval|null $precision
*
* @throws Exception
*
* @return $this
*/
public function floorUnit($unit, $precision = 1)
{
return $this->roundUnit($unit, $precision, 'floor');
}
/**
* Ceil the current instance at the given unit with given precision if specified.
*
* @param string $unit
* @param float|int|string|DateInterval|null $precision
*
* @throws Exception
*
* @return $this
*/
public function ceilUnit($unit, $precision = 1)
{
return $this->roundUnit($unit, $precision, 'ceil');
}
/**
* Round the current instance second with given precision if specified.
*
* @param float|int|string|DateInterval|null $precision
* @param string $function
*
* @throws Exception
*
* @return $this
*/
public function round($precision = 1, $function = 'round')
{
return $this->roundWith($precision, $function);
}
/**
* Round the current instance second with given precision if specified.
*
* @param float|int|string|DateInterval|null $precision
*
* @throws Exception
*
* @return $this
*/
public function floor($precision = 1)
{
return $this->round($precision, 'floor');
}
/**
* Ceil the current instance second with given precision if specified.
*
* @param float|int|string|DateInterval|null $precision
*
* @throws Exception
*
* @return $this
*/
public function ceil($precision = 1)
{
return $this->round($precision, 'ceil');
}
}
PK ! 4Ž] 8 carbon/src/Carbon/Exceptions/NotLocaleAwareException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
class NotLocaleAwareException extends BaseInvalidArgumentException implements InvalidArgumentException
{
/**
* Constructor.
*
* @param mixed $object
* @param int $code
* @param Exception|null $previous
*/
public function __construct($object, $code = 0, Exception $previous = null)
{
$dump = \is_object($object) ? \get_class($object) : \gettype($object);
parent::__construct("$dump does neither implements Symfony\Contracts\Translation\LocaleAwareInterface nor getLocale() method.", $code, $previous);
}
}
PK !
_ęBµ µ ; carbon/src/Carbon/Exceptions/UnitNotConfiguredException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
class UnitNotConfiguredException extends UnitException
{
/**
* Constructor.
*
* @param string $unit
* @param int $code
* @param Exception|null $previous
*/
public function __construct($unit, $code = 0, Exception $previous = null)
{
parent::__construct("Unit $unit have no configuration to get total from other units.", $code, $previous);
}
}
PK ! ®ź²zĶ Ķ 5 carbon/src/Carbon/Exceptions/UnreachableException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
use RuntimeException as BaseRuntimeException;
class UnreachableException extends BaseRuntimeException implements RuntimeException
{
/**
* Constructor.
*
* @param string $message
* @param int $code
* @param Exception|null $previous
*/
public function __construct($message, $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
PK ! |ŠĶń ń 3 carbon/src/Carbon/Exceptions/ImmutableException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
use RuntimeException as BaseRuntimeException;
class ImmutableException extends BaseRuntimeException implements RuntimeException
{
/**
* Constructor.
*
* @param string $value the immutable type/value
* @param int $code
* @param Exception|null $previous
*/
public function __construct($value, $code = 0, Exception $previous = null)
{
parent::__construct("$value is immutable.", $code, $previous);
}
}
PK ! hZäń ń 9 carbon/src/Carbon/Exceptions/InvalidTimeZoneException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
class InvalidTimeZoneException extends BaseInvalidArgumentException implements InvalidArgumentException
{
/**
* Constructor.
*
* @param string $message
* @param int $code
* @param Exception|null $previous
*/
public function __construct($message, $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
PK ! ·žN=ģ ģ 4 carbon/src/Carbon/Exceptions/NotAPeriodException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
class NotAPeriodException extends BaseInvalidArgumentException implements InvalidArgumentException
{
/**
* Constructor.
*
* @param string $message
* @param int $code
* @param Exception|null $previous
*/
public function __construct($message, $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
PK ! H1¼/ 7 carbon/src/Carbon/Exceptions/UnknownGetterException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
class UnknownGetterException extends BaseInvalidArgumentException implements InvalidArgumentException
{
/**
* Constructor.
*
* @param string $name getter name
* @param int $code
* @param Exception|null $previous
*/
public function __construct($name, $code = 0, Exception $previous = null)
{
parent::__construct("Unknown getter '$name'", $code, $previous);
}
}
PK ! wĒŅń ń 9 carbon/src/Carbon/Exceptions/InvalidIntervalException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
class InvalidIntervalException extends BaseInvalidArgumentException implements InvalidArgumentException
{
/**
* Constructor.
*
* @param string $message
* @param int $code
* @param Exception|null $previous
*/
public function __construct($message, $code = 0, Exception $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
PK ! øZ 4 carbon/src/Carbon/Exceptions/ParseErrorException.phpnu ÕIw¶“
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Carbon\Exceptions;
use Exception;
use InvalidArgumentException as BaseInvalidArgumentException;
class ParseErrorException extends BaseInvalidArgumentException implements InvalidArgumentException
{
/**
* Constructor.
*
* @param string $expected
* @param string $actual
* @param int $code
* @param Exception|null $previous
*/
public function __construct($expected, $actual, $help = '', $code = 0, Exception $previous = null)
{
$actual = $actual === '' ? 'data is missing' : "get '$actual'";
parent::__construct(trim("Format expected $expected but $actual\n$help"), $code, $previous);
}
}
PK ! |;