├── .coveralls.yml
├── .editorconfig
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── composer.json
├── phpunit.xml.dist
├── sami.php
├── src
├── Bridge
│ ├── Symfony
│ │ ├── CocurHumanDateBundle.php
│ │ ├── CocurHumanDateExtension.php
│ │ └── Translation
│ │ │ └── SymfonyTranslation.php
│ └── Twig
│ │ └── HumanDateExtension.php
├── HumanDate.php
└── Translation
│ └── TranslationInterface.php
└── tests
├── Bridge
├── Symfony
│ ├── CocurHumanDateBundleTest.php
│ ├── CocurHumanDateExtensionTest.php
│ └── Translation
│ │ └── SymfonyTranslationTest.php
└── Twig
│ └── HumanDateExtensionTest.php
└── HumanDateTest.php
/.coveralls.yml:
--------------------------------------------------------------------------------
1 | service_name: travis-ci
2 |
3 | # for php-coveralls
4 | src_dir: src
5 | coverage_clover: build/logs/clover.xml
6 | json_path: build/logs/coveralls-upload.json
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | charset = utf-8
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.yml]
12 | indent_style = space
13 | indent_size = 2
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /build/api
2 | /build/logs/
3 | /cache/
4 | /phpunit.xml
5 | /vendor/
6 | /composer.lock
7 | /*.sublime-project
8 | /*.sublime-workspace
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.4
5 | - 5.5
6 | - 5.6
7 | - hhvm
8 |
9 | before_script:
10 | - wget http://getcomposer.org/composer.phar
11 | - php composer.phar --prefer-source --dev install
12 | - cp phpunit.xml.dist phpunit.xml
13 |
14 | script:
15 | - mkdir -p build/logs
16 | - ./vendor/bin/phpunit -c ./
17 |
18 | after_script:
19 | - php vendor/bin/coveralls -v
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2012-2014 Florian Eckerstorfer
3 |
4 | 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:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | 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.
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | cocur/human-date
2 | ================
3 |
4 | > Transforms dates into a human-readable format.
5 |
6 | [](https://packagist.org/packages/cocur/human-date)
7 | [](https://travis-ci.org/cocur/human-date)
8 | [](https://coveralls.io/r/cocur/human-date)
9 |
10 |
11 | Features
12 | --------
13 |
14 | - Transforms dates into a human-readable format
15 | - Supports translatable strings
16 | - No external dependencies.
17 | - PSR-4 compatible.
18 | - Compatible with PHP >= 5.4 and [HHVM](http://hhvm.com).
19 | - Integrations for [Symfony2](http://symfony.com) and [Twig](http://twig.sensiolabs.org).
20 |
21 |
22 | Installation
23 | ------------
24 |
25 | You can install `cocur/human-date` using [Composer](https://getcomposer.org):
26 |
27 | ```shell
28 | $ composer require cocur/human-date:@stable
29 | ```
30 |
31 | *In a production environment you should replace `@stable` with the [version](https://github.com/cocur/human-date/releases) you want to use.*
32 |
33 |
34 | Usage
35 | -----
36 |
37 | You can pass an instance of `DateTime` to the `HumanDate::transform()` method. For example, assuming that today is `2012-08-18`:
38 |
39 | ```php
40 |
41 | use Cocur\HumanDate\HumanDate;
42 |
43 | $humanDate = new HumanDate();
44 |
45 | echo $humanDate->transform(new DateTime('now'));
46 | // 'Today'
47 |
48 | echo $humanDate->transform(new DateTime('+1 day'));
49 | // 'Tomorrow'
50 |
51 | echo $humanDate->transform(new DateTime('-1 day'));
52 | // 'Yesterday'
53 |
54 | echo $humanDate->transform(new DateTime('2012-08-21'));
55 | // 'Next Tuesday'
56 |
57 | echo $humanDate->transform(new DateTime('2012-09-30'));
58 | // 'September 30'
59 |
60 | echo $humanDate->transform(new DateTime('2013-03-30'));
61 | // 'March 30, 2013'
62 | ```
63 |
64 |
65 | Translation
66 | -----------
67 |
68 | HumanDate supports translation of strings. The `Cocur\HumanDate\HumanDate` constructor accepts an instance of `Cocur\HumanDate\Translation\TranslationInterface`.
69 |
70 | ```php
71 | $translation = MyTranslation(); // must implement `Cocur\HumanDate\Translation\TranslationInterface`
72 | $humanDate = new HumanDate($translation);
73 |
74 | echo $humanDate->transform(new DateTime('now'));
75 | // Calls MyTranslation::trans()
76 | ```
77 |
78 | Additionally the library includes an adapter for the [Symfony Translation](http://symfony.com/doc/current/components/translation/index.html) component.
79 |
80 |
81 | Bridges
82 | -------
83 |
84 | `cocur/human-date` contains bridges for Symfony and Twig.
85 |
86 | ### Symfony
87 |
88 | The Symfony bridge provides you with a bundle and an extension to use `HumanDate` as a service in your application.
89 |
90 | ```php
91 | # app/AppKernel.php
92 |
93 | class AppKernel extends Kernel
94 | {
95 | public function registerBundles()
96 | {
97 | $bundles = array(
98 | // ...
99 | new Cocur\HumanDate\Bridge\Symfony\CocurHumanDateBundle(),
100 | );
101 | // ...
102 | }
103 |
104 | // ...
105 | }
106 | ```
107 |
108 | You can now use the `cocur_human_date` service everywhere in your application, for example, in your controller:
109 |
110 | ```php
111 | $slug = $this->get('cocur_human_date')->slugify(new DateTime('2014-04-14'));
112 | ```
113 |
114 | The bundle also provides an alias `human_date` for the `cocur_human_date` service:
115 |
116 | ```php
117 | $slug = $this->get('human_date')->slugify(new DateTime('2014-04-14'));
118 | ```
119 |
120 | #### Translation
121 |
122 | HumanDate includes an adapter for the [Symfony Translation](http://symfony.com/doc/current/components/translation/index.html) component. The adapter requires an instance of `Symfony\Component\Translation\TranslatorInterface` and additionally accepts a translation domain and locale. The adapters `trans()` method passes theses values to every call of `Symfony\Component\Translation\TranslatorInterface::trans()`.
123 |
124 | ```php
125 | use Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation;
126 | use Cocur\HumanDate\HumanDate;
127 |
128 | // Get or create an instance of Symfony\Component\Translation\TranslatorInterface
129 | // For example, inside a controller
130 | $sfTrans = $this->get('translation');
131 |
132 | // Create an adapter with translation domain "human_date" and locale "en"
133 | // trans() passes domain and locale to every call of Symfony\Component\Translation\TranslatorInterface::trans()
134 | // If you omit the domain and locale it uses the defaults.
135 | $trans = new SymfonyTranslation($sfTrans, 'human_date', 'en');
136 |
137 | $humanDate = new HumanDate($trans);
138 | ```
139 |
140 | ### Twig
141 |
142 | If you use the Symfony2 framework with Twig you can use the Twig filter `humanDate` in your templates after you have setup Symfony2 integrations (see above).
143 |
144 | ```twig
145 | {{ post.createdAt|humanDate }}
146 | ```
147 |
148 | If you use Twig outside of the Symfony2 framework you first need to add the extension to your environment:
149 |
150 | ```php
151 | use Cocur\HumanDate\Bridge\Twig\HumanDateExtension;
152 | use Cocur\HumanDate\HumanDate;
153 |
154 | $twig = new Twig_Environment($loader);
155 | $twig->addExtension(new HumanDateExtension(new HumanDate()));
156 | ```
157 |
158 | You can find more information about registering extensions in the [Twig documentation](http://twig.sensiolabs.org/doc/advanced.html#creating-an-extension).
159 |
160 |
161 | Changelog
162 | ---------
163 |
164 | ### Version 0.1 (14 May 2014)
165 |
166 | - Initial version (ported from `BraincraftedHumanDateBundle`)
167 |
168 |
169 | Authors
170 | -------
171 |
172 | - [Florian Eckerstorfer](http://florian.ec) ([Twitter](http://twitter.com/Florian_)) [](https://www.gittip.com/FlorianEckerstorfer/)
173 |
174 |
175 | License
176 | -------
177 |
178 | The MIT License (MIT)
179 | Copyright (c) 2012 Florian Eckerstorfer
180 |
181 | 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:
182 |
183 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
184 |
185 | 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.
186 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cocur/human-date",
3 | "description": "Transforms dates into a human-readable form",
4 | "keywords": ["date", "transformer", "human date"],
5 | "type": "library",
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "Florian Eckerstorfer",
10 | "email": "florian@eckerstorfer.co",
11 | "homepage": "https://florian.ec"
12 | }
13 | ],
14 | "require": {
15 | "php": ">=5.4"
16 | },
17 | "require-dev": {
18 | "phpunit/phpunit": "~4.0",
19 | "mockery/mockery": "~0.9",
20 | "satooshi/php-coveralls": "dev-master",
21 | "symfony/http-kernel": "~2.4",
22 | "symfony/dependency-injection": "~2.4",
23 | "symfony/translation": "~2.4",
24 | "twig/twig": "~1",
25 | "sami/sami": "~1.3"
26 | },
27 | "autoload": {
28 | "psr-4": {
29 | "Cocur\\HumanDate\\": "src"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | tests
7 |
8 |
9 |
10 |
11 |
12 | src
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/sami.php:
--------------------------------------------------------------------------------
1 | addFromTags('v0.*')
10 | ->add('master', 'master branch')
11 | ;
12 |
13 | return new Sami($dir, array(
14 | 'title' => 'HumanDate API',
15 | 'theme' => 'enhanced',
16 | 'versions' => $versions,
17 | 'build_dir' => __DIR__.'/build/api/%version%',
18 | 'cache_dir' => __DIR__.'/cache/api/%version%',
19 | 'default_opened_level' => 2,
20 | ));
21 |
--------------------------------------------------------------------------------
/src/Bridge/Symfony/CocurHumanDateBundle.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate\Bridge\Symfony;
13 |
14 | use Symfony\Component\DependencyInjection\ContainerBuilder;
15 | use Symfony\Component\HttpKernel\Bundle\Bundle;
16 |
17 | /**
18 | * CocurHumanDateBundle
19 | *
20 | * @package cocur/human-date
21 | * @subpackage bridge
22 | * @author Florian Eckerstorfer
23 | * @copyright 2012-2014 Florian Eckerstorfer
24 | * @license http://opensource.org/licenses/MIT The MIT License
25 | */
26 | class CocurHumanDateBundle extends Bundle
27 | {
28 | /**
29 | * {@inheritDoc}
30 | */
31 | public function build(ContainerBuilder $container)
32 | {
33 | parent::build($container);
34 |
35 | $extension = new CocurHumanDateExtension();
36 | $extension->load(array(), $container);
37 |
38 | $container->registerExtension($extension);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Bridge/Symfony/CocurHumanDateExtension.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate\Bridge\Symfony;
13 |
14 | use Symfony\Component\DependencyInjection\ContainerBuilder;
15 | use Symfony\Component\DependencyInjection\Definition;
16 | use Symfony\Component\DependencyInjection\Reference;
17 | use Symfony\Component\HttpKernel\DependencyInjection\Extension;
18 |
19 | /**
20 | * CocurHumanDateExtension
21 | *
22 | * @package cocur/human-date
23 | * @subpackage bridge
24 | * @author Florian Eckerstorfer
25 | * @copyright 2012-2014 Florian Eckerstorfer
26 | * @license http://opensource.org/licenses/MIT The MIT License
27 | */
28 | class CocurHumanDateExtension extends Extension
29 | {
30 | /**
31 | * {@inheritDoc}
32 | */
33 | public function load(array $configs, ContainerBuilder $container)
34 | {
35 | $container->setDefinition('cocur_human_date', new Definition('Cocur\HumanDate\HumanDate'));
36 | $container
37 | ->setDefinition(
38 | 'cocur_human_date.twig.human_date',
39 | new Definition(
40 | 'Cocur\HumanDate\Bridge\Twig\HumanDateExtension',
41 | array(new Reference('cocur_human_date'))
42 | )
43 | )
44 | ->addTag('twig.extension')
45 | ->setPublic(false);
46 | $container->setAlias('human_date', 'cocur_human_date');
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Bridge/Symfony/Translation/SymfonyTranslation.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate\Bridge\Symfony\Translation;
13 |
14 | use Cocur\HumanDate\Translation\TranslationInterface;
15 | use Symfony\Component\Translation\TranslatorInterface as SymfonyTranslationInterface;
16 |
17 | /**
18 | * SymfonyTranslation provides an adapter to translate strings using the Symfony Translation component.
19 | *
20 | * @package cocur/human-date
21 | * @subpackage bridge
22 | * @author Florian Eckerstorfer
23 | * @copyright 2012-2014 Florian Eckerstorfer
24 | * @license http://opensource.org/licenses/MIT The MIT License
25 | */
26 | class SymfonyTranslation implements TranslationInterface
27 | {
28 | /** @var SymfonyTranslationInterface */
29 | private $translation;
30 |
31 | /** @var string */
32 | private $domain;
33 |
34 | /** @var string */
35 | private $locale;
36 |
37 | /**
38 | * @param SymfonyTranslationInterface $translation Symfony translation
39 | * @param string $domain The domain for the message or null to use the default
40 | * @param string $locale The locale or null to use the default
41 | */
42 | public function __construct(SymfonyTranslationInterface $translation, $domain = null, $locale = null)
43 | {
44 | $this->translation = $translation;
45 | $this->domain = $domain;
46 | $this->locale = $locale;
47 | }
48 |
49 | /**
50 | * @return SymfonyTranslationInterface
51 | */
52 | public function getTranslation()
53 | {
54 | return $this->translation;
55 | }
56 |
57 | /**
58 | * @return string The domain for the message or null to use the default
59 | */
60 | public function getDomain()
61 | {
62 | return $this->domain;
63 | }
64 |
65 | /**
66 | * @return string The locale or null to use the default
67 | */
68 | public function getLocale()
69 | {
70 | return $this->locale;
71 | }
72 |
73 | /**
74 | * Translates the given message.
75 | *
76 | * @param string $message The message id (may also be an object that can be cast to string)
77 | * @param array $parameters An array of parameters for the message
78 | *
79 | * @return string The translated string
80 | */
81 | public function trans($message, array $parameters = array())
82 | {
83 | return $this->translation->trans($message, $parameters, $this->domain, $this->locale);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Bridge/Twig/HumanDateExtension.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate\Bridge\Twig;
13 |
14 | use \Twig_Extension;
15 | use \Twig_SimpleFilter;
16 | use \DateTimeInterface;
17 |
18 | use Cocur\HumanDate\HumanDate;
19 |
20 | /**
21 | * HumanDateExtension
22 | *
23 | * @package cocur/human-date
24 | * @subpackage bridge
25 | * @author Florian Eckerstorfer
26 | * @copyright 2012-2014 Florian Eckerstorfer
27 | * @license http://opensource.org/licenses/MIT The MIT License
28 | */
29 | class HumanDateExtension extends Twig_Extension
30 | {
31 | /** @var HumanDate */
32 | private $humanDate;
33 |
34 | /**
35 | * @param HumanDate $humanDate
36 | */
37 | public function __construct(HumanDate $humanDate)
38 | {
39 | $this->humanDate = $humanDate;
40 | }
41 |
42 | /**
43 | * @return \Twig_SimpleFilter[]
44 | */
45 | public function getFilters()
46 | {
47 | return array(new Twig_SimpleFilter('humanDate', array($this, 'humanDateFilter')));
48 | }
49 |
50 | /**
51 | * @param DateTimeInterface $date
52 | *
53 | * @return string
54 | */
55 | public function humanDateFilter($date)
56 | {
57 | return $this->humanDate->transform($date);
58 | }
59 |
60 | /**
61 | * {@inheritDoc}
62 | */
63 | public function getName()
64 | {
65 | return 'human_date';
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/HumanDate.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate;
13 |
14 | use Cocur\HumanDate\Translation\TranslationInterface;
15 | use DateTime;
16 | use DateTimeInterface;
17 | use InvalidArgumentException;
18 |
19 | /**
20 | * HumanDate
21 | *
22 | * @package cocur/human-date
23 | * @author Florian Eckerstorfer
24 | * @copyright 2012-2014 Florian Eckerstorfer
25 | * @license http://opensource.org/licenses/MIT The MIT License
26 | */
27 | class HumanDate
28 | {
29 | /** @var TranslationInterface */
30 | private $translation;
31 |
32 | /**
33 | * @param TranslationInterface|null $translation Object to translate messages.
34 | */
35 | public function __construct($translation = null)
36 | {
37 | if (null !== $translation && !$translation instanceof TranslationInterface) {
38 | throw new InvalidArgumentException('$translation must be null or an instance of TranslationInterface');
39 | }
40 |
41 | $this->translation = $translation;
42 | }
43 |
44 | /**
45 | * @return TranslationInterface Object to translate messages.
46 | */
47 | public function getTranslation()
48 | {
49 | return $this->translation;
50 | }
51 |
52 | /**
53 | * Transforms the given date into a human-readable date.
54 | *
55 | * @param DateTimeInterface|string $date Input date.
56 | *
57 | * @return string Human-readable date.
58 | */
59 | public function transform($date)
60 | {
61 | if (!$date instanceof DateTimeInterface) {
62 | $date = new DateTime($date);
63 | }
64 |
65 | $current = new DateTime('now');
66 |
67 | if ($this->isToday($date)) {
68 | return $this->trans('Today');
69 | }
70 |
71 | if ($this->isYesterday($date)) {
72 | return $this->trans('Yesterday');
73 | }
74 |
75 | if ($this->isTomorrow($date)) {
76 | return $this->trans('Tomorrow');
77 | }
78 |
79 | if ($this->isNextWeek($date)) {
80 | return $this->trans('Next %weekday%', [ '%weekday%' => $date->format('l') ]);
81 | }
82 |
83 | if ($this->isLastWeek($date)) {
84 | return $this->trans('Last %weekday%', [ '%weekday%' => $date->format('l') ]);
85 | }
86 |
87 | if ($this->isThisYear($date)) {
88 | return $date->format('F j');
89 | }
90 |
91 | return $date->format('F j, Y');
92 | }
93 |
94 | /**
95 | * @param DateTimeInterface $date Date.
96 | *
97 | * @return boolean `true` if the given date is today, `false` otherwise.
98 | */
99 | protected function isToday(DateTimeInterface $date)
100 | {
101 | $today = new DateTime('now');
102 | $start = new DateTime($today->format('Y-m-d') . ' 00:00:00');
103 | $end = new DateTime($today->format('Y-m-d') . ' 23:59:59');
104 |
105 | if ($date->getTimestamp() >= $start->getTimestamp() && $date->getTimestamp() <= $end->getTimestamp()) {
106 | return true;
107 | }
108 | return false;
109 | }
110 |
111 | /**
112 | * @param DateTimeInterface $date Date.
113 | *
114 | * @return boolean `true` if the given date is tomorrow, `false` otherwise.
115 | */
116 | protected function isTomorrow(DateTimeInterface $date)
117 | {
118 | $tomorrow = new DateTime('+1 day');
119 | $start = new DateTime($tomorrow->format('Y-m-d') . ' 00:00:00');
120 | $end = new DateTime($tomorrow->format('Y-m-d') . ' 23:59:59');
121 |
122 | if ($date->getTimestamp() >= $start->getTimestamp() && $date->getTimestamp() <= $end->getTimestamp()) {
123 | return true;
124 | }
125 | return false;
126 | }
127 |
128 | /**
129 | * @param DateTimeInterface $date Date.
130 | *
131 | * @return boolean `true` if the given date is yesterday, `false` otherwise.
132 | */
133 | protected function isYesterday(DateTimeInterface $date)
134 | {
135 | $yesterday = new DateTime('-1 day');
136 | $start = new DateTime($yesterday->format('Y-m-d') . ' 00:00:00');
137 | $end = new DateTime($yesterday->format('Y-m-d') . ' 23:59:59');
138 |
139 | if ($date->getTimestamp() >= $start->getTimestamp() && $date->getTimestamp() <= $end->getTimestamp()) {
140 | return true;
141 | }
142 | return false;
143 | }
144 |
145 | /**
146 | * @param DateTimeInterface $date Date.
147 | *
148 | * @return boolean `true` if the given date is next week, `false` otherwise.
149 | */
150 | protected function isNextWeek(DateTimeInterface $date)
151 | {
152 | $week = new DateTime('+7 days');
153 |
154 | if ($date->getTimestamp() >= time() && $date->getTimestamp() <= $week->getTimestamp()) {
155 | return true;
156 | }
157 | return false;
158 | }
159 |
160 | /**
161 | * @param DateTimeInterface $date Date.
162 | *
163 | * @return boolean `true` if the given date is last week, `false` otherwise.
164 | */
165 | protected function isLastWeek(DateTimeInterface $date)
166 | {
167 | $week = new DateTime('-7 days');
168 |
169 | if ($date->getTimestamp() <= time() && $date->getTimestamp() >= $week->getTimestamp()) {
170 | return true;
171 | }
172 | return false;
173 | }
174 |
175 | /**
176 | * @param DateTimeInterface $date Date.
177 | * @return boolean `true` if the given date is this year, `false` otherwise.
178 | */
179 | protected function isThisYear(DateTimeInterface $date)
180 | {
181 | if (date('Y') === $date->format('Y')) {
182 | return true;
183 | }
184 | return false;
185 | }
186 |
187 | /**
188 | * Translates the given message.
189 | *
190 | * @param string $id The message id (may also be an object that can be cast to string).
191 | * @param array $parameters An array of parameters for the message.
192 | *
193 | * @return string The translated message.
194 | */
195 | protected function trans($id, array $parameters = array())
196 | {
197 | if (null === $this->translation) {
198 | return str_replace(array_keys($parameters), array_values($parameters), $id);
199 | }
200 |
201 | return $this->translation->trans($id, $parameters);
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/src/Translation/TranslationInterface.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate\Translation;
13 |
14 | /**
15 | * TranslationInterface
16 | *
17 | * @package cocur/human-date
18 | * @subpackage translation
19 | * @author Florian Eckerstorfer
20 | * @copyright 2012-2014 Florian Eckerstorfer
21 | * @license http://opensource.org/licenses/MIT The MIT License
22 | */
23 | interface TranslationInterface
24 | {
25 | /**
26 | * Translates the given message.
27 | *
28 | * @param string $message The message id (may also be an object that can be cast to string)
29 | * @param array $parameters An array of parameters for the message
30 | *
31 | * @return string Translated message.
32 | */
33 | public function trans($message, array $parameters = array());
34 | }
35 |
--------------------------------------------------------------------------------
/tests/Bridge/Symfony/CocurHumanDateBundleTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate\Bridge\Symfony;
13 |
14 | use Cocur\HumanDate\Bridge\Symfony\CocurHumanDateBundle;
15 |
16 | /**
17 | * CocurHumanDateBundleTest
18 | *
19 | * @category test
20 | * @package cocur/human-date
21 | * @subpackage bridge
22 | * @author Florian Eckerstorfer
23 | * @copyright 2012-2014 Florian Eckerstorfer
24 | * @license http://www.opensource.org/licenses/MIT The MIT License
25 | * @group unit
26 | */
27 | class CocurHumanDateBundleTest extends \PHPUnit_Framework_TestCase
28 | {
29 | public function setUp()
30 | {
31 | $this->bundle = new CocurHumanDateBundle();
32 | }
33 |
34 | /**
35 | * @test
36 | * @covers Cocur\HumanDate\Bridge\Symfony\CocurHumanDateBundle::build()
37 | */
38 | public function build()
39 | {
40 | $container = $this->getMock(
41 | 'Symfony\Component\DependencyInjection\ContainerBuilder',
42 | array('registerExtension')
43 | );
44 | $container->expects($this->once())
45 | ->method('registerExtension')
46 | ->with($this->isInstanceOf('Cocur\HumanDate\Bridge\Symfony\CocurHumanDateExtension'));
47 |
48 | $this->bundle->build($container);
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/tests/Bridge/Symfony/CocurHumanDateExtensionTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate\Bridge\Bundle;
13 |
14 | use Cocur\HumanDate\Bridge\Symfony\CocurHumanDateExtension;
15 | use \Mockery as m;
16 |
17 |
18 | /**
19 | * CocurHumanDateExtensionTest
20 | *
21 | * @category test
22 | * @package cocur/human-date
23 | * @subpackage bridge
24 | * @author Florian Eckerstorfer
25 | * @copyright 2012-2014 Florian Eckerstorfer
26 | * @license http://www.opensource.org/licenses/MIT The MIT License
27 | * @group unit
28 | */
29 | class CocurHumanDateExtensionTest extends \PHPUnit_Framework_TestCase
30 | {
31 | public function setUp()
32 | {
33 | $this->extension = new CocurHumanDateExtension();
34 | }
35 |
36 | /**
37 | * @test
38 | * @covers Cocur\HumanDate\Bridge\Symfony\CocurHumanDateExtension::load()
39 | */
40 | public function load()
41 | {
42 | $twigDefinition = m::mock('Symfony\Component\DependencyInjection\Definition');
43 | $twigDefinition
44 | ->shouldReceive('addTag')
45 | ->with('twig.extension')
46 | ->once()
47 | ->andReturn($twigDefinition);
48 | $twigDefinition
49 | ->shouldReceive('setPublic')
50 | ->with(false)
51 | ->once();
52 |
53 | $container = m::mock('Symfony\Component\DependencyInjection\ContainerBuilder');
54 | $container
55 | ->shouldReceive('setDefinition')
56 | ->with('cocur_human_date', m::type('Symfony\Component\DependencyInjection\Definition'))
57 | ->once();
58 | $container
59 | ->shouldReceive('setDefinition')
60 | ->with('cocur_human_date.twig.human_date', m::type('Symfony\Component\DependencyInjection\Definition'))
61 | ->once()
62 | ->andReturn($twigDefinition);
63 | $container
64 | ->shouldReceive('setAlias')
65 | ->with('human_date', 'cocur_human_date')
66 | ->once();
67 |
68 | $this->extension->load(array(), $container);
69 | }
70 | }
71 |
72 |
--------------------------------------------------------------------------------
/tests/Bridge/Symfony/Translation/SymfonyTranslationTest.php:
--------------------------------------------------------------------------------
1 | symfonyTrans = m::mock('Symfony\Component\Translation\TranslatorInterface');
24 | $this->trans = new SymfonyTranslation($this->symfonyTrans, 'foo', 'en');
25 | }
26 |
27 | /**
28 | * @test
29 | * @covers Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation::__construct()
30 | * @covers Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation::getTranslation()
31 | */
32 | public function getTranslation()
33 | {
34 | $this->assertEquals($this->symfonyTrans, $this->trans->getTranslation());
35 | }
36 |
37 | /**
38 | * @test
39 | * @covers Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation::__construct()
40 | * @covers Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation::getDomain()
41 | */
42 | public function getDomain()
43 | {
44 | $this->assertEquals('foo', $this->trans->getDomain());
45 | }
46 |
47 | /**
48 | * @test
49 | * @covers Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation::__construct()
50 | * @covers Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation::getLocale()
51 | */
52 | public function getLocale()
53 | {
54 | $this->assertEquals('en', $this->trans->getLocale());
55 | }
56 |
57 | /**
58 | * @test
59 | * @covers Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation::trans()
60 | */
61 | public function trans()
62 | {
63 | $this->symfonyTrans
64 | ->shouldReceive('trans')
65 | ->with('string', [], 'foo', 'en')
66 | ->once()
67 | ->andReturn('translated string');
68 |
69 | $this->assertEquals('translated string', $this->trans->trans('string'));
70 | }
71 |
72 | /**
73 | * @test
74 | * @covers Cocur\HumanDate\Bridge\Symfony\Translation\SymfonyTranslation::trans()
75 | */
76 | public function transWithParameters()
77 | {
78 | $this->symfonyTrans
79 | ->shouldReceive('trans')
80 | ->with('string', [ 'key1' => 'val1' ], 'foo', 'en')
81 | ->once()
82 | ->andReturn('translated string');
83 |
84 | $this->assertEquals('translated string', $this->trans->trans('string', [ 'key1' => 'val1' ]));
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/tests/Bridge/Twig/HumanDateExtensionTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate\Bridge\Twig;
13 |
14 | use Cocur\HumanDate\Bridge\Twig\HumanDateExtension;
15 | use \Mockery as m;
16 |
17 |
18 | /**
19 | * HumanDateExtensionTest
20 | *
21 | * @category test
22 | * @package cocur/human-date
23 | * @subpackage bridge
24 | * @author Florian Eckerstorfer
25 | * @copyright 2012-2014 Florian Eckerstorfer
26 | * @license http://www.opensource.org/licenses/MIT The MIT License
27 | * @group unit
28 | */
29 | class HumanDateExtensionTest extends \PHPUnit_Framework_TestCase
30 | {
31 | /** @var HumanDate */
32 | private $humanDate;
33 |
34 | /** @var HumanDateExtension */
35 | private $extension;
36 |
37 | public function setUp()
38 | {
39 | $this->humanDate = m::mock('Cocur\HumanDate\HumanDate');
40 | $this->extension = new HumanDateExtension($this->humanDate);
41 | }
42 |
43 | /**
44 | * @test
45 | * @covers Cocur\HumanDate\Bridge\Twig\HumanDateExtension::getName()
46 | */
47 | public function getName($withDataSet = true)
48 | {
49 | $this->assertEquals('human_date', $this->extension->getName());
50 | }
51 |
52 | /**
53 | * @test
54 | * @covers Cocur\HumanDate\Bridge\Twig\HumanDateExtension::getFilters()
55 | */
56 | public function getFilters()
57 | {
58 | $filters = $this->extension->getFilters();
59 |
60 | $this->assertCount(1, $filters);
61 | $this->assertInstanceOf('\Twig_SimpleFilter', $filters[0]);
62 | }
63 |
64 | /**
65 | * @test
66 | * @covers Cocur\HumanDate\Bridge\Twig\HumanDateExtension::slugifyFilter()
67 | */
68 | public function slugifyFilter()
69 | {
70 | $this->humanDate->shouldReceive('transform')->with('2014-05-14')->once()->andReturn('Today');
71 |
72 | $this->assertEquals('Today', $this->extension->humanDateFilter('2014-05-14'));
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/tests/HumanDateTest.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace Cocur\HumanDate;
13 |
14 | use DateTime;
15 | use Cocur\HumanDate\HumanDate;
16 | use Mockery as m;
17 |
18 | /**
19 | * HumanDateTest
20 | *
21 | * @category test
22 | * @package cocur/human-date
23 | * @author Florian Eckerstorfer
24 | * @copyright 2012-2014 Florian Eckerstorfer
25 | * @license http://opensource.org/licenses/MIT The MIT License
26 | * @link https://github.com/braincrafted/human-date-bundle BraincraftedHumanDateBundle
27 | * @group unit
28 | */
29 | class HumanDateTest extends \PHPUnit_Framework_TestCase
30 | {
31 | /** @var HumanDateTransformer */
32 | protected $humanDate;
33 |
34 | public function setUp()
35 | {
36 | $this->humanDate = new HumanDate();
37 | }
38 |
39 | /**
40 | * @test
41 | * @covers Cocur\HumanDate\HumanDate::__construct()
42 | * @expectedException \InvalidArgumentException
43 | */
44 | public function constructorGetsInvalidTranslation()
45 | {
46 | new HumanDate('string');
47 | }
48 |
49 | /**
50 | * @test
51 | * @covers Cocur\HumanDate\HumanDate::transform()
52 | * @covers Cocur\HumanDate\HumanDate::isToday()
53 | * @covers Cocur\HumanDate\HumanDate::isTomorrow()
54 | * @covers Cocur\HumanDate\HumanDate::isYesterday()
55 | * @covers Cocur\HumanDate\HumanDate::isNextWeek()
56 | * @covers Cocur\HumanDate\HumanDate::isLastWeek()
57 | * @covers Cocur\HumanDate\HumanDate::isThisYear()
58 | * @covers Cocur\HumanDate\HumanDate::trans()
59 | * @dataProvider provider
60 | */
61 | public function transformDateTime($date, $expected)
62 | {
63 | $this->assertEquals($expected, $this->humanDate->transform(new DateTime($date)));
64 | }
65 |
66 | /**
67 | * @test
68 | * @covers Cocur\HumanDate\HumanDate::transform()
69 | * @covers Cocur\HumanDate\HumanDate::isToday()
70 | * @covers Cocur\HumanDate\HumanDate::isTomorrow()
71 | * @covers Cocur\HumanDate\HumanDate::isYesterday()
72 | * @covers Cocur\HumanDate\HumanDate::isNextWeek()
73 | * @covers Cocur\HumanDate\HumanDate::isLastWeek()
74 | * @covers Cocur\HumanDate\HumanDate::isThisYear()
75 | * @dataProvider provider
76 | */
77 | public function transformString($date, $expected)
78 | {
79 | $this->assertEquals($expected, $this->humanDate->transform($date));
80 | }
81 |
82 | /**
83 | * @return array[]
84 | */
85 | public function provider()
86 | {
87 | return array(
88 | array('', 'Today'),
89 | array('-1 day', 'Yesterday'),
90 | array('+1 day', 'Tomorrow'),
91 | array('+3 days', 'Next '.date('l', strtotime('+3 days'))),
92 | array('-3 days', 'Last '.date('l', strtotime('-3 days'))),
93 | array('+30 days', date('F j', strtotime('+30 days'))),
94 | array('-30 days', date('F j', strtotime('-30 days'))),
95 | array((date('Y')+1).'-03-31', 'March 31, '.(date('Y')+1)),
96 | array((date('Y')-1).'-03-31', 'March 31, '.(date('Y')-1))
97 | );
98 | }
99 |
100 | /**
101 | * @test
102 | * @covers Cocur\HumanDate\HumanDate::transform()
103 | * @covers Cocur\HumanDate\HumanDate::isToday()
104 | * @covers Cocur\HumanDate\HumanDate::isTomorrow()
105 | * @covers Cocur\HumanDate\HumanDate::isYesterday()
106 | * @covers Cocur\HumanDate\HumanDate::isNextWeek()
107 | * @covers Cocur\HumanDate\HumanDate::isLastWeek()
108 | * @covers Cocur\HumanDate\HumanDate::isThisYear()
109 | * @covers Cocur\HumanDate\HumanDate::trans()
110 | * @dataProvider translatedProvider
111 | */
112 | public function transformDateTimeWithTranslation($date, $expected)
113 | {
114 | $trans = m::mock('Cocur\HumanDate\Translation\TranslationInterface');
115 | $trans->shouldReceive('trans')->with('Today', [])->andReturn('Heute');
116 | $trans->shouldReceive('trans')->with('Yesterday', [])->andReturn('Gestern');
117 | $trans->shouldReceive('trans')->with('Tomorrow', [])->andReturn('Morgen');
118 | $trans
119 | ->shouldReceive('trans')
120 | ->with('Next %weekday%', [ '%weekday%' => date('l', strtotime('+3 days')) ])
121 | ->andReturn('Nächsten '.date('l', strtotime('+3 days')));
122 | $trans
123 | ->shouldReceive('trans')
124 | ->with('Last %weekday%', [ '%weekday%' => date('l', strtotime('-3 days')) ])
125 | ->andReturn('Letzten '.date('l', strtotime('-3 days')));
126 |
127 | $humanDate = new HumanDate($trans);
128 | $this->assertEquals($expected, $humanDate->transform(new DateTime($date)));
129 | }
130 |
131 | /**
132 | * @return array[]
133 | */
134 | public function translatedProvider()
135 | {
136 | return array(
137 | array('', 'Heute'),
138 | array('-1 day', 'Gestern'),
139 | array('+1 day', 'Morgen'),
140 | array('+3 days', 'Nächsten '.date('l', strtotime('+3 days'))),
141 | array('-3 days', 'Letzten '.date('l', strtotime('-3 days'))),
142 | array('+30 days', date('F j', strtotime('+30 days'))),
143 | array('-30 days', date('F j', strtotime('-30 days'))),
144 | array((date('Y')+1).'-03-31', 'March 31, '.(date('Y')+1)),
145 | array((date('Y')-1).'-03-31', 'March 31, '.(date('Y')-1))
146 | );
147 | }
148 | }
149 |
--------------------------------------------------------------------------------