├── .github ├── FUNDING.yml └── workflows │ ├── php-cs-fixer.yml │ ├── run-tests.yml │ └── update-changelog.yml ├── .php-cs-fixer.dist.php ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json └── src └── TestTime.php /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: spatie 2 | custom: https://spatie.be/open-source/support-us -------------------------------------------------------------------------------- /.github/workflows/php-cs-fixer.yml: -------------------------------------------------------------------------------- 1 | name: Check & fix styling 2 | 3 | on: [ push ] 4 | 5 | jobs: 6 | php-cs-fixer: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Checkout code 11 | uses: actions/checkout@v2 12 | with: 13 | ref: ${{ github.head_ref }} 14 | 15 | - name: Run PHP CS Fixer 16 | uses: docker://oskarstark/php-cs-fixer-ga 17 | with: 18 | args: --config=.php-cs-fixer.dist.php --allow-risky=yes 19 | 20 | - name: Commit changes 21 | uses: stefanzweifel/git-auto-commit-action@v4 22 | with: 23 | commit_message: Fix styling 24 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: run-tests 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | fail-fast: false 10 | matrix: 11 | php: [8.3, 8.2, 8.1, 8.0, 7.4, 7.3] 12 | carbon: [^3.0, ^2.63] 13 | dependency-version: [prefer-lowest, prefer-stable] 14 | 15 | name: P${{ matrix.php }} - ${{ matrix.dependency-version }} 16 | 17 | steps: 18 | - name: Checkout code 19 | uses: actions/checkout@v4 20 | 21 | - name: Install dependencies 22 | run: | 23 | composer require "nesbot/carbon:${{ matrix.carbon }}" --no-interaction --no-update 24 | composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest 25 | 26 | - name: Execute tests 27 | run: vendor/bin/phpunit 28 | -------------------------------------------------------------------------------- /.github/workflows/update-changelog.yml: -------------------------------------------------------------------------------- 1 | name: "Update Changelog" 2 | 3 | on: 4 | release: 5 | types: [released] 6 | 7 | jobs: 8 | update: 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@v2 14 | with: 15 | ref: main 16 | 17 | - name: Update Changelog 18 | uses: stefanzweifel/changelog-updater-action@v1 19 | with: 20 | latest-version: ${{ github.event.release.name }} 21 | release-notes: ${{ github.event.release.body }} 22 | 23 | - name: Commit updated CHANGELOG 24 | uses: stefanzweifel/git-auto-commit-action@v4 25 | with: 26 | branch: main 27 | commit_message: Update CHANGELOG 28 | file_pattern: CHANGELOG.md 29 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | notPath('bootstrap/*') 5 | ->notPath('storage/*') 6 | ->notPath('resources/view/mail/*') 7 | ->in([ 8 | __DIR__ . '/src', 9 | __DIR__ . '/tests', 10 | ]) 11 | ->name('*.php') 12 | ->notName('*.blade.php') 13 | ->ignoreDotFiles(true) 14 | ->ignoreVCS(true); 15 | 16 | return (new PhpCsFixer\Config) 17 | ->setRules([ 18 | '@PSR2' => true, 19 | 'array_syntax' => ['syntax' => 'short'], 20 | 'ordered_imports' => ['sort_algorithm' => 'alpha'], 21 | 'no_unused_imports' => true, 22 | 'not_operator_with_successor_space' => true, 23 | 'trailing_comma_in_multiline' => true, 24 | 'phpdoc_scalar' => true, 25 | 'unary_operator_spaces' => true, 26 | 'binary_operator_spaces' => true, 27 | 'blank_line_before_statement' => [ 28 | 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], 29 | ], 30 | 'phpdoc_single_line_var_spacing' => true, 31 | 'phpdoc_var_without_name' => true, 32 | 'method_argument_space' => [ 33 | 'on_multiline' => 'ensure_fully_multiline', 34 | 'keep_multiple_spaces_after_comma' => true, 35 | ] 36 | ]) 37 | ->setFinder($finder); 38 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `test-time` will be documented in this file 4 | 5 | ## 1.3.3 - 2024-02-05 6 | 7 | - support Carbon 3 8 | 9 | **Full Changelog**: https://github.com/spatie/test-time/compare/1.3.2...1.3.3 10 | 11 | ## 1.3.2 - 2023-01-10 12 | 13 | - fix for latest versions of Carbon 14 | 15 | ## 1.3.1 - 2023-01-10 16 | 17 | - accept timezone parameter 18 | 19 | ## 1.3.0 - 2022-02-04 20 | 21 | Add `unfreeze` 22 | 23 | ## 1.2.2 - 2020-11-03 24 | 25 | - add support for PHP 8 26 | 27 | ## 1.2.1 - 2020-07-16 28 | 29 | - support `CarbonImmutable` 30 | 31 | ## 1.2.0 - 2020-02-23 32 | 33 | - add `freezeAtSecond` method (#9) 34 | 35 | ## 1.1.3 - 2020-01-22 36 | 37 | - support carbon 1.26 38 | 39 | ## 1.1.2 - 2019-06-14 40 | 41 | - yet even more methods 42 | 43 | ## 1.1.1 - 2019-06-14 44 | 45 | - moarrrrr docblocked methods 46 | 47 | ## 1.1.0 - 2019-06-12 48 | 49 | - allow passing the format and time to `freeze` 50 | 51 | ## 1.0.0 - 2019-06-12 52 | 53 | - initial release 54 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Spatie bvba 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A helper to control the flow of time 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/spatie/test-time.svg?style=flat-square)](https://packagist.org/packages/spatie/test-time) 4 | [![run-tests](https://github.com/spatie/test-time/actions/workflows/run-tests.yml/badge.svg)](https://github.com/spatie/test-time/actions/workflows/run-tests.yml) 5 | [![Total Downloads](https://img.shields.io/packagist/dt/spatie/test-time.svg?style=flat-square)](https://packagist.org/packages/spatie/test-time) 6 | 7 | [Carbon](https://github.com/briannesbitt/Carbon) is an excellent library to work with time in PHP projects. The `Spatie\TestTime\TestTime` class contains a few functions that under the hood manipulate the time that's considered the current time by Carbon. 8 | 9 | ```php 10 | // the flow of time is frozen 11 | TestTime::freeze(); 12 | 13 | // we're now one year in the future 14 | TestTime::addYear(); 15 | 16 | // will report the real current year + 1 17 | $year = (new Carbon())->format('Y'); 18 | ``` 19 | 20 | ## Are you a visual learner? 21 | 22 | [In this video](https://www.youtube.com/watch?v=1dJphbcWRxI), you'll learn how we use this package to test time sensitive functionality in [Mailcoach](https://mailcoach.app). 23 | 24 | ## Support us 25 | 26 | [](https://spatie.be/github-ad-click/test-time) 27 | 28 | We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). 29 | 30 | We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). 31 | 32 | ## Installation 33 | 34 | You can install the package via composer. Probably you'll only need it when developing. 35 | 36 | ```bash 37 | composer require spatie/test-time --dev 38 | ``` 39 | 40 | ## Usage 41 | 42 | You can freeze the time with: 43 | 44 | ```php 45 | TestTime::freeze(); 46 | ``` 47 | 48 | Alternatively you can pass in a carbon instance that will be used as the current time. 49 | 50 | ```php 51 | TestTime::freeze($carbonInstance); 52 | ``` 53 | 54 | You can also pass a format and time. 55 | 56 | ```php 57 | TestTime::freeze('Y-m-d', '2019-06-12'); 58 | ``` 59 | 60 | ### Progressing time 61 | 62 | You can progress the time with any of the carbon functions starting with `add` or `sub`. 63 | 64 | ```php 65 | TestTime::addMinute(); 66 | 67 | TestTime::subHours(5); 68 | 69 | // you can also chain calls 70 | TestTime::addMonth(3)->addYear(); 71 | ``` 72 | 73 | ### Unfreezing time 74 | 75 | To let time flow naturally again, call `unfreeze`. 76 | 77 | ```php 78 | TestTime::unfreeze(); 79 | ``` 80 | 81 | ### Testing 82 | 83 | ``` bash 84 | composer test 85 | ``` 86 | 87 | ### Changelog 88 | 89 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 90 | 91 | ## Contributing 92 | 93 | Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details. 94 | 95 | ### Security 96 | 97 | If you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker. 98 | 99 | ## Postcardware 100 | 101 | You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. 102 | 103 | Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium. 104 | 105 | We publish all received postcards [on our company website](https://spatie.be/en/opensource/postcards). 106 | 107 | ## Credits 108 | 109 | - [Freek Van der Herten](https://github.com/freekmurze) 110 | - [Alex Vanderbist](https://github.com/AlexVanderbist) 111 | - [All Contributors](../../contributors) 112 | 113 | ## License 114 | 115 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 116 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spatie/test-time", 3 | "description": "A small package to control the flow time", 4 | "keywords": [ 5 | "spatie", 6 | "test-time" 7 | ], 8 | "homepage": "https://github.com/spatie/test-time", 9 | "license": "MIT", 10 | "authors": [ 11 | { 12 | "name": "Freek Van der Herten", 13 | "email": "freek@spatie.be", 14 | "homepage": "https://spatie.be", 15 | "role": "Developer" 16 | }, 17 | { 18 | "name": "Alex Vanderbist", 19 | "email": "alex@spatie.be", 20 | "homepage": "https://spatie.be", 21 | "role": "Developer" 22 | } 23 | ], 24 | "require": { 25 | "php": "^7.3|^8.0", 26 | "nesbot/carbon": "^2.63|^3.0" 27 | }, 28 | "require-dev": { 29 | "phpunit/phpunit": "^9.5.10" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "Spatie\\TestTime\\": "src" 34 | } 35 | }, 36 | "autoload-dev": { 37 | "psr-4": { 38 | "Spatie\\TestTime\\Tests\\": "tests" 39 | } 40 | }, 41 | "scripts": { 42 | "test": "vendor/bin/phpunit", 43 | "test-coverage": "vendor/bin/phpunit --coverage-html coverage" 44 | }, 45 | "config": { 46 | "sort-packages": true 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/TestTime.php: -------------------------------------------------------------------------------- 1 | startOfSecond(); 123 | 124 | return static::freeze($frozenTime); 125 | } 126 | 127 | public function __call($name, $arguments) 128 | { 129 | return $this->__callStatic($name, $arguments); 130 | } 131 | 132 | public static function __callStatic($name, $arguments) 133 | { 134 | $result = (new Carbon)->$name(...$arguments); 135 | 136 | if (! $result instanceof Carbon) { 137 | return $result; 138 | } 139 | 140 | Carbon::setTestNow($result); 141 | CarbonImmutable::setTestNow($result); 142 | 143 | return new TestTime(); 144 | } 145 | 146 | protected static function getCarbon(array $args): Carbon 147 | { 148 | if (count($args) === 0) { 149 | return Carbon::now(); 150 | } 151 | 152 | if (count($args) === 1) { 153 | if (! $args[0] instanceof Carbon) { 154 | throw new InvalidArgumentException('You must pass a Carbon instance to `freeze`'); 155 | } 156 | 157 | return $args[0]; 158 | } 159 | 160 | if (count($args) === 2) { 161 | return Carbon::createFromFormat($args[0], $args[1]); 162 | } 163 | 164 | if (count($args) === 3) { 165 | return Carbon::createFromFormat($args[0], $args[1], $args[2]); 166 | } 167 | 168 | throw new InvalidArgumentException('You can only pass a maximum of two arguments to `freeze`'); 169 | } 170 | } 171 | --------------------------------------------------------------------------------