├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── doc ├── Symfony2_twig_extension.md └── example.php ├── spec └── Smirik │ └── PHPDateTimeAgo │ └── DateTimeAgoSpec.php ├── src └── Smirik │ └── PHPDateTimeAgo │ ├── DateTimeAgo.php │ └── TextTranslator │ ├── AbstractTextTranslator.php │ ├── EnglishTextTranslator.php │ ├── GermanTextTranslator.php │ ├── ItalianTextTranslator.php │ ├── PolishTextTranslator.php │ ├── PortugueseTextTranslator.php │ ├── RussianTextTranslator.php │ └── TextTranslatorInterface.php └── test └── PolishTextTranslatorTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /bin/ 3 | composer.lock 4 | .idea 5 | .DS_Store -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 5.5 7 | 8 | before_script: 9 | - curl -s https://getcomposer.org/installer | php 10 | - php composer.phar install --dev 11 | 12 | script: 13 | - php bin/phpspec run 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Evgeny Smirnov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | php-datetime-ago 2 | ================ 3 | 4 | This library helps to format the date/time interval into text. 5 | 6 | Examples 7 | ------- 8 | 9 | | Condition | Text | 10 | | --------- | ---- | 11 | | Now | now | 12 | | Less than an hour | xx minutes ago | 13 | | Between 1 and 2 hours | 1 hour ago | 14 | | Between 2 and 24 hours | xx hours ago | 15 | | Between 1 and 2 days | 1 day ago | 16 | | Between 2 and 6 days | xx days ago | 17 | | 7 or more days ago | xx weeks ago | 18 | | 30 or more days ago | xx months ago | 19 | | 365 or more days ago | xx years ago | 20 | 21 | Notice that not every translator supports weeks, months and years 22 | 23 | Usage 24 | ----- 25 | 26 | `DateTimeAgo` class has public method `get`. It accepts 1 required argument (`\DateTime` object) and 1 optional (reference date. If it is `null`, current time is used). 27 | 28 | ```php 29 | get(new \DateTime('-24 hours')); /* returns "1 day ago" */ 32 | $date_ago->get(new \DateTime('-69 minutes')); /* returns "1 hour ago" */ 33 | $date_ago->get(new \DateTime('-100 minutes')); /* returns "2 hours ago" */ 34 | $date_ago->get(new \DateTime('-155 minutes')); /* returns "3 hours ago" */ 35 | ``` 36 | 37 | Russian translation: 38 | ```php 39 | get(new \DateTime('-24 hours')); /* returns "1 день назад" */ 42 | $date_ago->get(new \DateTime('-69 minutes')); /* returns "1 час назад" */ 43 | $date_ago->get(new \DateTime('-100 minutes')); /* returns "2 часа назад" */ 44 | $date_ago->get(new \DateTime('-155 minutes')); /* returns "3 часа назад" */ 45 | ``` 46 | 47 | Customization 48 | ------------- 49 | 50 | #### Date formatter for more than 6 days 51 | 52 | ```php 53 | setFormat('d.m.Y H:i:s'); 56 | ``` 57 | This setup date in format `01.01.2001 22:52:12`. 58 | 59 | #### Custom translator 60 | 61 | The DateTimeAgo constructor accept `TextTranslator` file as the first argument. By default `EnglishTextTranslator` is provided. You can add your custom translator to this constructor. Just make sure that your class implements `Smirik\PHPDateTimeAgo\TextTranslator\TextTranslatorInterface`. There is also standard way for translations based on pluralization procedure. The methods are already implemented for any language in `AbstractTextTranslator` class. English & Russian samples are already included in this package. You can also change the translator after creation: 62 | 63 | ```php 64 | setTextTranslator(new \Smirik\PHPDateTimeAgo\TextTranslator\RussianTextTranslator()); 67 | ``` 68 | 69 | #### Implementation 70 | 71 | * [How to integrate library with Symfony2](doc/Symfony2_twig_extension.md) 72 | 73 | #### Tests 74 | 75 | Most parts of the code are tested via `phpspec`. To run the tests clone the repository and run 76 | ```bash 77 | $ php bin/phpspec run 78 | ``` 79 | 80 | ## Development workflow 81 | 82 | * In order to keep git versioning accurate please use [git-flow](https://github.com/nvie/gitflow) pattern. 83 | * So all pull requests except hotfix should go to the develop branch. 84 | * Hotfix should go to both development branches: develop & master at the same time. 85 | 86 | ## Contribution 87 | 88 | Any contribution is welcome. 89 | 90 | ## Acknowledgements 91 | 92 | * Symfony cookbook for [Russian pluralization rule](http://symfony.com/doc/current/book/translation.html#explicit-interval-pluralization). 93 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "smirik/php-datetime-ago", 3 | "description": "How much time ago in text format", 4 | "require-dev": { 5 | "phpspec/phpspec": "2.0.*@dev" 6 | }, 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Evgeny Smirnov", 11 | "email": "smirik@gmail.com" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=5.3.3" 16 | }, 17 | "autoload": { 18 | "psr-0": { "Smirik\\PHPDateTimeAgo\\": "src/" } 19 | }, 20 | "config": { 21 | "bin-dir": "bin" 22 | }, 23 | "minimum-stability": "dev" 24 | } 25 | -------------------------------------------------------------------------------- /doc/Symfony2_twig_extension.md: -------------------------------------------------------------------------------- 1 | How to integrate with Symfony2 2 | ============================== 3 | 4 | It is easy to integrate `PHPDateTime` library with Symfony2 via Twig Extension. 5 | 6 | 7 | #### Step 0. Add to composer 8 | 9 | ``` json 10 | "require": { 11 | ... 12 | "smirik/php-datetime-ago": "dev-master" 13 | }, ... 14 | ``` 15 | 16 | You can also use tags (~v1.0). 17 | 18 | #### Step 1. Creating Twig Extension 19 | 20 | First of all, create class in `Twig/Extension` directory in your bundle: 21 | 22 | ``` php 23 | container = $container; 41 | } 42 | 43 | public function getFilters() 44 | { 45 | return array( 46 | 'ago' => new Twig_Filter_Method($this, 'ago') 47 | ); 48 | } 49 | 50 | public function ago($date) 51 | { 52 | /** Add your custom logic depending on locale */ 53 | $locale = $this->container->get('request')->getLocale(); 54 | if ($locale == 'ru') { 55 | $datetime_ago = new DateTimeAgo(new \Smirik\PHPDateTimeAgo\TextTranslator\RussianTextTranslator()); 56 | $datetime_ago->setFormat('d.m.Y'); 57 | } 58 | return $datetime_ago->get($date); 59 | } 60 | 61 | public function getName() 62 | { 63 | return 'ago.twig.extension'; 64 | } 65 | 66 | } 67 | ``` 68 | 69 | #### Step 2. Register extension in services.yml 70 | 71 | Define the extension in `services.yml`. Container dependence is optional. If you don't need in locale support --- just remove it. 72 | 73 | ``` yaml 74 | ago.twig.extension: 75 | class: Smirik\CoreBundle\Twig\Extension\DateTimeAgoExtension 76 | tags: 77 | - { name: twig.extension } 78 | calls: 79 | - [ setContainer, [ "@service_container" ]] 80 | ``` 81 | 82 | #### Step 3. Use it! 83 | 84 | Remember, that `PHPDateTime` library accepts only `DateTime` objects. To format the date use `ago` twig filter. 85 | 86 | ``` php 87 | get(new \DateTime('-24 hours')); // 1 day ago 9 | 10 | $italian_date_ago = new \Smirik\PHPDateTimeAgo\DateTimeAgo(new \Smirik\PHPDateTimeAgo\TextTranslator\ItalianTextTranslator()); 11 | 12 | echo $italian_date_ago->get(new \DateTime('-24 hours')); // 1 giorno fa 13 | -------------------------------------------------------------------------------- /spec/Smirik/PHPDateTimeAgo/DateTimeAgoSpec.php: -------------------------------------------------------------------------------- 1 | shouldHaveType('Smirik\PHPDateTimeAgo\DateTimeAgo'); 14 | } 15 | 16 | function it_checks_daily() 17 | { 18 | $now = new \DateTime(); 19 | $diff = $now->diff(new \DateTime('-3 hours')); 20 | $this->daily($diff)->shouldBe(true); 21 | 22 | $diff = $now->diff(new \DateTime('-25 hours')); 23 | $this->daily($diff)->shouldBe(false); 24 | 25 | $diff = $now->diff(new \DateTime('-50 hours')); 26 | $this->daily($diff)->shouldBe(false); 27 | } 28 | 29 | function it_checks_hourly() 30 | { 31 | $now = new \DateTime(); 32 | $diff = $now->diff(new \DateTime('-3 minute')); 33 | $this->hourly($diff)->shouldBe(true); 34 | 35 | $diff = $now->diff(new \DateTime('-64 minutes')); 36 | $this->hourly($diff)->shouldBe(false); 37 | 38 | $diff = $now->diff(new \DateTime('-2 hours')); 39 | $this->hourly($diff)->shouldBe(false); 40 | } 41 | 42 | function it_checks_now() 43 | { 44 | $this->get(new \DateTime())->shouldReturn("now"); 45 | $this->get(new \DateTime('-5 seconds'))->shouldReturn("now"); 46 | $this->get(new \DateTime('-25 seconds'))->shouldReturn("now"); 47 | $this->get(new \DateTime('-59 seconds'))->shouldReturn("now"); 48 | } 49 | 50 | function it_checks_minutes() 51 | { 52 | $this->get(new \DateTime('-3 minutes'))->shouldBe('3 minutes ago'); 53 | $this->get(new \DateTime('-25 minutes'))->shouldBe('25 minutes ago'); 54 | $this->get(new \DateTime('-61 minutes'))->shouldBe('1 hour ago'); 55 | } 56 | 57 | function it_checks_hours() 58 | { 59 | $this->get(new \DateTime('-90 minutes'))->shouldBe('1 hour ago'); 60 | $this->get(new \DateTime('-119 minutes'))->shouldBe('1 hour ago'); 61 | $this->get(new \DateTime('-120 minutes'))->shouldBe('2 hours ago'); 62 | $this->get(new \DateTime('-2 hours'))->shouldBe('2 hours ago'); 63 | } 64 | 65 | function it_checks_days() 66 | { 67 | $this->get(new \DateTime('-24 hours'))->shouldBe('1 day ago'); 68 | $this->get(new \DateTime('-2 days'))->shouldBe('2 days ago'); 69 | $this->get(new \DateTime('-5 days'))->shouldBe('5 days ago'); 70 | $this->setMaxDaysCount(3); 71 | $this->get(new \DateTime('-5 days'))->shouldNotBe('5 days ago'); 72 | } 73 | 74 | function it_checks_weeks_in_english_when_enabled() 75 | { 76 | $translator = new \Smirik\PHPDateTimeAgo\TextTranslator\EnglishTextTranslator; 77 | $translator->enableWeeksMonthsYears(TRUE); 78 | $this->setTextTranslator($translator); 79 | $this->get(new \DateTime('-6 days'))->shouldBe('6 days ago'); 80 | $this->get(new \DateTime('-7 days'))->shouldBe('1 week ago'); 81 | $this->get(new \DateTime('-14 days'))->shouldBe('2 weeks ago'); 82 | $this->get(new \DateTime('-29 days'))->shouldBe('4 weeks ago'); 83 | } 84 | 85 | function it_checks_months_in_english_when_enabled() 86 | { 87 | $translator = new \Smirik\PHPDateTimeAgo\TextTranslator\EnglishTextTranslator; 88 | $translator->enableWeeksMonthsYears(TRUE); 89 | $this->setTextTranslator($translator); 90 | $this->get(new \DateTime('-30 days'))->shouldBe('1 month ago'); 91 | $this->get(new \DateTime('-70 days'))->shouldBe('2 months ago'); 92 | $this->get(new \DateTime('-364 days'))->shouldBe('11 months ago'); 93 | } 94 | 95 | function it_checks_years_in_english_when_enabled() 96 | { 97 | $translator = new \Smirik\PHPDateTimeAgo\TextTranslator\EnglishTextTranslator; 98 | $translator->enableWeeksMonthsYears(TRUE); 99 | $this->setTextTranslator($translator); 100 | $this->get(new \DateTime('-365 days'))->shouldBe('1 year ago'); 101 | $this->get(new \DateTime('-729 days'))->shouldBe('1 year ago'); 102 | $this->get(new \DateTime('-15 years'))->shouldBe('15 years ago'); 103 | } 104 | 105 | function it_checks_format() 106 | { 107 | $this->get(new \DateTime('2001-01-01 23:59'), new \DateTime('2001-01-20 01:00'))->shouldBe('2001-01-01'); 108 | $this->setFormat('Y-m-d H:i'); 109 | $this->get(new \DateTime('2001-01-01 23:59'), new \DateTime('2001-01-20 01:00'))->shouldBe('2001-01-01 23:59'); 110 | } 111 | 112 | function it_checks_russian() 113 | { 114 | $this->setTextTranslator(new \Smirik\PHPDateTimeAgo\TextTranslator\RussianTextTranslator()); 115 | $this->get(new \DateTime())->shouldBe('сейчас'); 116 | $this->get(new \DateTime('-3 minutes'))->shouldBe('3 минуты назад'); 117 | $this->get(new \DateTime('-25 minutes'))->shouldBe('25 минут назад'); 118 | $this->get(new \DateTime('-59 minutes'))->shouldBe('59 минут назад'); 119 | $this->get(new \DateTime('-61 minutes'))->shouldBe('1 час назад'); 120 | 121 | $this->get(new \DateTime('-24 hours'))->shouldBe('1 день назад'); 122 | $this->get(new \DateTime('-2 days'))->shouldBe('2 дня назад'); 123 | $this->get(new \DateTime('-5 days'))->shouldBe('5 дней назад'); 124 | 125 | } 126 | 127 | function it_checks_italian() 128 | { 129 | $this->setTextTranslator(new \Smirik\PHPDateTimeAgo\TextTranslator\ItalianTextTranslator()); 130 | 131 | $this->get(new \DateTime())->shouldBe('ora'); 132 | $this->get(new \DateTime('-5 seconds'))->shouldReturn('ora'); 133 | $this->get(new \DateTime('-25 seconds'))->shouldReturn('ora'); 134 | $this->get(new \DateTime('-59 seconds'))->shouldReturn('ora'); 135 | 136 | $this->get(new \DateTime('-1 minutes'))->shouldBe('1 minuto fa'); 137 | $this->get(new \DateTime('-3 minutes'))->shouldBe('3 minuti fa'); 138 | $this->get(new \DateTime('-25 minutes'))->shouldBe('25 minuti fa'); 139 | $this->get(new \DateTime('-59 minutes'))->shouldBe('59 minuti fa'); 140 | $this->get(new \DateTime('-61 minutes'))->shouldBe('1 ora fa'); 141 | 142 | $this->get(new \DateTime('-24 hours'))->shouldBe('1 giorno fa'); 143 | $this->get(new \DateTime('-2 days'))->shouldBe('2 giorni fa'); 144 | $this->get(new \DateTime('-5 days'))->shouldBe('5 giorni fa'); 145 | 146 | } 147 | 148 | function it_checks_german() 149 | { 150 | $this->setTextTranslator(new \Smirik\PHPDateTimeAgo\TextTranslator\GermanTextTranslator()); 151 | 152 | //now 153 | $this->get(new \DateTime())->shouldReturn('jetzt'); 154 | $this->get(new \DateTime('-5 seconds'))->shouldReturn('jetzt'); 155 | $this->get(new \DateTime('-25 seconds'))->shouldReturn('jetzt'); 156 | $this->get(new \DateTime('-59 seconds'))->shouldReturn('jetzt'); 157 | 158 | //minutes 159 | $this->get(new \DateTime('-1 minutes'))->shouldBe('vor einer Minute'); 160 | $this->get(new \DateTime('-3 minutes'))->shouldBe('vor 3 Minuten'); 161 | $this->get(new \DateTime('-25 minutes'))->shouldBe('vor 25 Minuten'); 162 | $this->get(new \DateTime('-59 minutes'))->shouldBe('vor 59 Minuten'); 163 | $this->get(new \DateTime('-61 minutes'))->shouldBe('vor einer Stunde'); 164 | 165 | //hours 166 | $this->get(new \DateTime('-90 minutes'))->shouldBe('vor einer Stunde'); 167 | $this->get(new \DateTime('-119 minutes'))->shouldBe('vor einer Stunde'); 168 | $this->get(new \DateTime('-2 hours'))->shouldBe('vor 2 Stunden'); 169 | 170 | //days 171 | $this->get(new \DateTime('-24 hours'))->shouldBe('vor einem Tag'); 172 | $this->get(new \DateTime('-2 days'))->shouldBe('vor 2 Tagen'); 173 | $this->get(new \DateTime('-5 days'))->shouldBe('vor 5 Tagen'); 174 | } 175 | 176 | function it_checks_portuguese() 177 | { 178 | $this->setTextTranslator(new \Smirik\PHPDateTimeAgo\TextTranslator\PortugueseTextTranslator()); 179 | 180 | $this->get(new \DateTime())->shouldBe('agora'); 181 | $this->get(new \DateTime('-5 seconds'))->shouldReturn('agora'); 182 | $this->get(new \DateTime('-25 seconds'))->shouldReturn('agora'); 183 | $this->get(new \DateTime('-59 seconds'))->shouldReturn('agora'); 184 | 185 | $this->get(new \DateTime('-1 minutes'))->shouldBe('1 minuto atrás'); 186 | $this->get(new \DateTime('-3 minutes'))->shouldBe('3 minutos atrás'); 187 | $this->get(new \DateTime('-25 minutes'))->shouldBe('25 minutos atrás'); 188 | $this->get(new \DateTime('-59 minutes'))->shouldBe('59 minutos atrás'); 189 | $this->get(new \DateTime('-61 minutes'))->shouldBe('1 hora atrás'); 190 | 191 | $this->get(new \DateTime('-24 hours'))->shouldBe('1 dia atrás'); 192 | $this->get(new \DateTime('-2 days'))->shouldBe('2 dias atrás'); 193 | $this->get(new \DateTime('-5 days'))->shouldBe('5 dias atrás'); 194 | 195 | } 196 | 197 | function it_checks_polish() 198 | { 199 | $this->setTextTranslator(new \Smirik\PHPDateTimeAgo\TextTranslator\PolishTextTranslator); 200 | 201 | $this->get(new \DateTime())->shouldBe('teraz'); 202 | $this->get(new \DateTime('-5 seconds'))->shouldReturn('teraz'); 203 | $this->get(new \DateTime('-25 seconds'))->shouldReturn('teraz'); 204 | $this->get(new \DateTime('-59 seconds'))->shouldReturn('teraz'); 205 | 206 | $this->get(new \DateTime('-1 minutes'))->shouldBe('1 minutę temu'); 207 | $this->get(new \DateTime('-3 minutes'))->shouldBe('3 minuty temu'); 208 | $this->get(new \DateTime('-25 minutes'))->shouldBe('25 minut temu'); 209 | $this->get(new \DateTime('-59 minutes'))->shouldBe('59 minut temu'); 210 | $this->get(new \DateTime('-61 minutes'))->shouldBe('1 godzinę temu'); 211 | 212 | $this->get(new \DateTime('-121 minutes'))->shouldBe('2 godziny temu'); 213 | 214 | $this->get(new \DateTime('-24 hours'))->shouldBe('1 dzień temu'); 215 | $this->get(new \DateTime('-2 days'))->shouldBe('2 dni temu'); 216 | $this->get(new \DateTime('-5 days'))->shouldBe('5 dni temu'); 217 | $this->get(new \DateTime('-6 days'))->shouldBe('6 dni temu'); 218 | 219 | $this->get(new \DateTime('-7 days'))->shouldBe('1 tydzień temu'); 220 | $this->get(new \DateTime('-18 days'))->shouldBe('2 tygodnie temu'); 221 | $this->get(new \DateTime('-29 days'))->shouldBe('4 tygodnie temu'); 222 | 223 | $this->get(new \DateTime('-30 days'))->shouldBe('1 miesiąc temu'); 224 | $this->get(new \DateTime('2015-09-08'), new \DateTime('2015-08-06'))->shouldBe('1 miesiąc temu'); 225 | $this->get(new \DateTime('-80 days'))->shouldBe('2 miesiące temu'); 226 | $this->get(new \DateTime('-364 days'))->shouldBe('11 miesięcy temu'); 227 | 228 | $this->get(new \DateTime('-365 days'))->shouldBe('1 rok temu'); 229 | $this->get(new \DateTime('-729 days'))->shouldBe('1 rok temu'); 230 | $this->get(new \DateTime('-730 days'))->shouldBe('2 lata temu'); 231 | $this->get(new \DateTime('-95 years'))->shouldBe('95 lat temu'); 232 | } 233 | 234 | } 235 | -------------------------------------------------------------------------------- /src/Smirik/PHPDateTimeAgo/DateTimeAgo.php: -------------------------------------------------------------------------------- 1 | text_translator = $text_translator; 35 | } 36 | 37 | /** 38 | * Get string representation of the date with given translator 39 | * @param DateTime $date 40 | * @param DateTime|null $reference_date 41 | * @return string 42 | */ 43 | public function get(DateTime $date, DateTime $reference_date = null ) 44 | { 45 | if (is_null($reference_date)) { 46 | $reference_date = new DateTime(); 47 | } 48 | 49 | $diff = $reference_date->diff($date); 50 | return $this->getText($diff, $date); 51 | } 52 | 53 | /** 54 | * Get string related to DateInterval object 55 | * @param DateInterval $diff 56 | * @return string 57 | */ 58 | public function getText(DateInterval $diff, $date) 59 | { 60 | if ($this->now($diff)) { 61 | return $this->text_translator->now(); 62 | } 63 | 64 | if ($this->minutes($diff)) { 65 | return $this->text_translator->minutes($this->minutes($diff)); 66 | } 67 | 68 | if ($this->hours($diff)) { 69 | return $this->text_translator->hours($this->hours($diff)); 70 | } 71 | 72 | if ($this->days($diff)) { 73 | return $this->text_translator->days($this->days($diff)); 74 | } 75 | 76 | if ($this->text_translator->supportsWeeks() && $this->weeks($diff)) { 77 | return $this->text_translator->weeks($this->weeks($diff)); 78 | } 79 | 80 | if ($this->text_translator->supportsMonths() && $this->months($diff)) { 81 | return $this->text_translator->months($this->months($diff)); 82 | } 83 | 84 | if ($this->text_translator->supportsYears() && $this->years($diff)) { 85 | return $this->text_translator->years($this->years($diff)); 86 | } 87 | 88 | return $date->format($this->format); 89 | } 90 | 91 | /** 92 | * Is date limit by day 93 | * @param DateInterval $diff 94 | * @return bool 95 | */ 96 | public function daily($diff) 97 | { 98 | if (($diff->y == 0) && ($diff->m == 0) && (($diff->d == 0) || (($diff->d == 1) && ($diff->h == 0) && ($diff->i == 0)))) { 99 | return true; 100 | } 101 | return false; 102 | } 103 | 104 | /** 105 | * Is date limit by hour 106 | * @param DateInterval $diff 107 | * @return bool 108 | */ 109 | public function hourly($diff) 110 | { 111 | if ($this->daily($diff) && ($diff->d == 0) && (($diff->h == 0) || (($diff->h == 1) && ($diff->i == 0)))) { 112 | return true; 113 | } 114 | return false; 115 | } 116 | 117 | /** 118 | * @param DateInterval $diff 119 | * @return bool 120 | */ 121 | public function now(DateInterval $diff) 122 | { 123 | if ($this->hourly($diff) && ($diff->h == 0) && ($diff->i == 0) && ($diff->s <= 59)) { 124 | return true; 125 | } 126 | return false; 127 | } 128 | 129 | /** 130 | * Number of minutes related to the interval or false if more. 131 | * @param DateInterval $diff 132 | * @return integer|false 133 | */ 134 | public function minutes(DateInterval $diff) 135 | { 136 | if ($this->hourly($diff)) { 137 | return $diff->i; 138 | } 139 | return false; 140 | } 141 | 142 | /** 143 | * Number of hours related to the interval or false if more. 144 | * @param DateInterval $diff 145 | * @return integer|false 146 | */ 147 | public function hours(DateInterval $diff) 148 | { 149 | if ($this->daily($diff)) { 150 | return $diff->h; 151 | } 152 | return false; 153 | } 154 | 155 | /** 156 | * Number of days related to the interval or false if more. 157 | * @param DateInterval $diff 158 | * @return integer|false 159 | */ 160 | public function days(DateInterval $diff) 161 | { 162 | if ($diff->days <= $this->max_days_count) { 163 | return $diff->days; 164 | } 165 | return false; 166 | } 167 | 168 | /** 169 | * Get Number of weeks 170 | * @param DateInterval $diff 171 | * @return integer|false 172 | */ 173 | public function weeks(DateInterval $diff) 174 | { 175 | if ($diff->days < 30) { 176 | return (int) floor($diff->days / 7); 177 | } 178 | return false; 179 | } 180 | 181 | /** 182 | * Get Number of months 183 | * @param DateInterval $diff 184 | * @return integer|false 185 | */ 186 | public function months(DateInterval $diff) 187 | { 188 | if ($diff->days >= 365) { 189 | return FALSE; 190 | } 191 | 192 | $x = (int) floor($diff->days / 30.417); 193 | if ($x === 0) { 194 | return 1; 195 | } else { 196 | return $x; 197 | } 198 | } 199 | 200 | /** 201 | * Get Number of years 202 | * @param DateInterval $diff 203 | * @return integer|false 204 | */ 205 | public function years(DateInterval $diff) 206 | { 207 | return (int) floor($diff->days / 365); 208 | } 209 | 210 | /** 211 | * Setters 212 | */ 213 | 214 | /** 215 | * @param TextTranslatorInterface $text_translator 216 | */ 217 | public function setTextTranslator(TextTranslatorInterface $text_translator) 218 | { 219 | $this->text_translator = $text_translator; 220 | } 221 | 222 | /** 223 | * @param integer $max_days_count 224 | */ 225 | public function setMaxDaysCount($max_days_count) 226 | { 227 | $this->max_days_count = $max_days_count; 228 | } 229 | 230 | /** 231 | * @param string $format 232 | */ 233 | public function setFormat($format) 234 | { 235 | $this->format = $format; 236 | } 237 | 238 | } -------------------------------------------------------------------------------- /src/Smirik/PHPDateTimeAgo/TextTranslator/AbstractTextTranslator.php: -------------------------------------------------------------------------------- 1 | minute_words[$this->pluralization($minutes)]; 17 | } 18 | 19 | /** 20 | * Returns hours with correct pluralization based on hour_words property & pluralization method 21 | * @param integer $hours 22 | * @return string 23 | */ 24 | public function hours($hours) 25 | { 26 | return $hours.' '.$this->hour_words[$this->pluralization($hours)]; 27 | } 28 | 29 | /** 30 | * Returns days with correct pluralization based on day_words property & pluralization method 31 | * @param integer $days 32 | * @return string 33 | */ 34 | public function days($days) 35 | { 36 | return $days.' '.$this->day_words[$this->pluralization($days)]; 37 | } 38 | 39 | /** 40 | * Returns "weeks ago" like string 41 | * @param integer $weeks 42 | * @return string 43 | */ 44 | public function weeks($weeks) 45 | { 46 | return sprintf($this->formatPattern, $weeks, $this->week_words[$this->pluralization($weeks)]); 47 | } 48 | 49 | /** 50 | * Returns "months ago" like string 51 | * @param integer $months 52 | * @return string 53 | */ 54 | public function months($months) 55 | { 56 | return sprintf($this->formatPattern, $months, $this->month_words[$this->pluralization($months)]); 57 | } 58 | 59 | /** 60 | * Returns "years ago" like string 61 | * @param integer $years 62 | * @return string 63 | */ 64 | public function years($years) 65 | { 66 | return sprintf($this->formatPattern, $years, $this->year_words[$this->pluralization($years)]); 67 | } 68 | 69 | /** 70 | * Pluralize the number according to the language. Returns key in related array (minute_words, hour_words, day_words) 71 | * @param integer $number 72 | * @return integer 73 | */ 74 | abstract protected function pluralization($number); 75 | 76 | /** 77 | * Does the translator support weeks 78 | * 79 | * @return bool 80 | */ 81 | public function supportsWeeks() 82 | { 83 | return false; 84 | } 85 | 86 | /** 87 | * Does the translator support months 88 | * 89 | * @return bool 90 | */ 91 | public function supportsMonths() 92 | { 93 | return false; 94 | } 95 | 96 | /** 97 | * Does the translator support years 98 | * 99 | * @return bool 100 | */ 101 | public function supportsYears() 102 | { 103 | return false; 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /src/Smirik/PHPDateTimeAgo/TextTranslator/EnglishTextTranslator.php: -------------------------------------------------------------------------------- 1 | weeks_months_years = $enable; 25 | } 26 | 27 | /** 28 | * {@inheritdoc} 29 | */ 30 | public function now() 31 | { 32 | return 'now'; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function pluralization($number) 39 | { 40 | return ($number == 1) ? 0 : 1; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function supportsWeeks() 47 | { 48 | return $this->weeks_months_years; 49 | } 50 | 51 | /** 52 | * {@inheritdoc} 53 | */ 54 | public function supportsMonths() 55 | { 56 | return $this->weeks_months_years; 57 | } 58 | 59 | /** 60 | * {@inheritdoc} 61 | */ 62 | public function supportsYears() 63 | { 64 | return $this->weeks_months_years; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/Smirik/PHPDateTimeAgo/TextTranslator/GermanTextTranslator.php: -------------------------------------------------------------------------------- 1 | pluralization($number)]; 19 | if ($number === 1) { 20 | $number = $oneWord; 21 | } 22 | return $this->pre_word . ' ' . $number . ' ' . $typeWord; 23 | } 24 | 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | public function now() 29 | { 30 | return 'jetzt'; 31 | } 32 | 33 | /** 34 | * {@inheritdoc} 35 | */ 36 | public function minutes($minutes) 37 | { 38 | return $this->format($minutes, $this->one_words[0], $this->minute_words); 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function hours($hours) 45 | { 46 | return $this->format($hours, $this->one_words[0], $this->hour_words); 47 | } 48 | 49 | /** 50 | * {@inheritdoc} 51 | */ 52 | public function days($days) 53 | { 54 | return $this->format($days, $this->one_words[1], $this->day_words); 55 | } 56 | 57 | /** 58 | * Pluralize the number. Returns key in related array (minute_words, hour_words, day_words) 59 | * @param integer $number 60 | * @return integer 61 | */ 62 | public function pluralization($number) 63 | { 64 | return $number === 1 ? 0 : 1; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Smirik/PHPDateTimeAgo/TextTranslator/ItalianTextTranslator.php: -------------------------------------------------------------------------------- 1 | 10 && $number < 21) //for 10-20 67 | { 68 | return 2; 69 | } 70 | 71 | if ($number % 10 < 5) //for x1..x4 72 | { 73 | return 1; 74 | } 75 | 76 | return 2; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Smirik/PHPDateTimeAgo/TextTranslator/PortugueseTextTranslator.php: -------------------------------------------------------------------------------- 1 | = 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/Smirik/PHPDateTimeAgo/TextTranslator/TextTranslatorInterface.php: -------------------------------------------------------------------------------- 1 | getText(new \DateInterval($format), new \DateTime()); 14 | $this->assertEquals($expected, $formattedText); 15 | } 16 | 17 | public function textFormattingData() 18 | { 19 | return [ 20 | ['PT1M', '1 minutę temu'], 21 | ['PT2M', '2 minuty temu'], 22 | ['PT3M', '3 minuty temu'], 23 | ['PT4M', '4 minuty temu'], 24 | ['PT5M', '5 minut temu'], 25 | ['PT10M', '10 minut temu'], 26 | 27 | ['PT11M', '11 minut temu'], 28 | ['PT12M', '12 minut temu'], 29 | ['PT13M', '13 minut temu'], 30 | ['PT14M', '14 minut temu'], 31 | ['PT15M', '15 minut temu'], 32 | ['PT16M', '16 minut temu'], 33 | ['PT17M', '17 minut temu'], 34 | ['PT18M', '18 minut temu'], 35 | ['PT19M', '19 minut temu'], 36 | 37 | ['PT20M', '20 minut temu'], 38 | ['PT21M', '21 minut temu'], 39 | ['PT22M', '22 minuty temu'], 40 | 41 | ['PT120M', '120 minut temu'], 42 | ['PT121M', '121 minut temu'], 43 | ['PT122M', '122 minuty temu'], 44 | ['PT123M', '123 minuty temu'], 45 | ['PT124M', '124 minuty temu'], 46 | ['PT125M', '125 minut temu'], 47 | ['PT126M', '126 minut temu'], 48 | ['PT127M', '127 minut temu'], 49 | ['PT128M', '128 minut temu'], 50 | ['PT129M', '129 minut temu'], 51 | ['PT130M', '130 minut temu'], 52 | 53 | ['P1D', '1 dzień temu'], 54 | ['P2D', '2 dni temu'], 55 | ['P3D', '3 dni temu'], 56 | ['P4D', '4 dni temu'], 57 | ['P5D', '5 dni temu'], 58 | 59 | ['PT1H', '1 godzinę temu'], 60 | ['PT2H', '2 godziny temu'], 61 | ['PT5H', '5 godzin temu'], 62 | 63 | 64 | ['P7D', '1 tydzień temu'], 65 | ['P8D', '1 tydzień temu'], 66 | ['P9D', '1 tydzień temu'], 67 | ['P10D', '1 tydzień temu'], 68 | 69 | ['P11D', '2 tygodnie temu'], 70 | ['P12D', '2 tygodnie temu'], 71 | ['P13D', '2 tygodnie temu'], 72 | ['P14D', '2 tygodnie temu'], 73 | ['P15D', '2 tygodnie temu'], 74 | ['P16D', '2 tygodnie temu'], 75 | ['P17D', '2 tygodnie temu'], 76 | 77 | ['P18D', '3 tygodnie temu'], 78 | ['P19D', '3 tygodnie temu'], 79 | ['P20D', '3 tygodnie temu'], 80 | ['P21D', '3 tygodnie temu'], 81 | ['P22D', '3 tygodnie temu'], 82 | ['P22D', '3 tygodnie temu'], 83 | ['P23D', '3 tygodnie temu'], 84 | ['P24D', '3 tygodnie temu'], 85 | 86 | ['P25D', '1 miesiąc temu'], 87 | ['P35D', '1 miesiąc temu'], 88 | ['P45D', '2 miesiące temu'], 89 | ['P55D', '2 miesiące temu'], 90 | ['P65D', '2 miesiące temu'], 91 | ['P75D', '3 miesiące temu'], 92 | ['P85D', '3 miesiące temu'], 93 | ['P95D', '3 miesiące temu'], 94 | ['P105D', '4 miesiące temu'], 95 | ['P155D', '5 miesięcy temu'], 96 | 97 | ['P360D', '1 rok temu'], 98 | ['P400D', '1 rok temu'], 99 | ['P500D', '1 rok temu'], 100 | ['P600D', '2 lata temu'], 101 | ['P600D', '2 lata temu'], 102 | ['P1800D', '5 lat temu'], 103 | 104 | 105 | ]; 106 | } 107 | } --------------------------------------------------------------------------------