From e77ffe2c4a75a8777fec42274f4c97fac7d18b74 Mon Sep 17 00:00:00 2001 From: David Renty Date: Wed, 12 Mar 2014 14:29:49 +0100 Subject: [PATCH 01/11] Added asElapsedTime function --- framework/base/Formatter.php | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 80c08e1744..481387711b 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -455,4 +455,54 @@ class Formatter extends Component return $verbose ? Yii::t('yii', '{n, plural, =1{# petabyte} other{# petabytes}}', $params) : Yii::t('yii', '{n} PB', $params); } } + + /** + * Formats the value as a the time elapsed since then in human readable form. + * @param integer|string|DateTime $value the value to be formatted. The following + * types of value are supported: + * + * - an integer representing a UNIX timestamp + * - a string that can be parsed into a UNIX timestamp via `strtotime()` + * - a PHP DateTime object + * + * @return string the formatted result + */ + public function asElapsedTime($value) + { + if ($value === null) { + return $this->nullDisplay; + } + $value = $this->normalizeDatetimeValue($value); + + $now = new \DateTime(); + $date = new DateTime(null, new \DateTimeZone($this->timeZone)); + $date->setTimestamp($value); + + $interval = $now->diff($date); + + if ($interval->y >= 1) { + $delta = $interval->y; + $format = '{delta, plural, =1{a year} other{# years}} ago'; + } elseif ($interval->m >= 1) { + $delta = $interval->m; + $format = '{delta, plural, =1{a month} other{# months}} ago'; + } elseif ($interval->d >= 7) { + $delta = floor($interval->d / 7); + $format = '{delta, plural, =1{a week} other{# weeks}} ago'; + } elseif ($interval->d >= 1) { + $delta = $interval->d; + $format = '{delta, plural, =1{yesterday} other{# days ago}}'; + } elseif ($interval->h >= 1) { + $delta = $interval->h; + $format = '{delta, plural, =1{an hour} other{# hours}} ago'; + } elseif ($interval->i >= 1) { + $delta = $interval->i; + $format = '{delta, plural, =1{a minute} other{# minutes}} ago'; + } else { + $delta = $interval->s; + $format = '{delta, plural, =1{a second} other{# seconds}} ago'; + } + + return Yii::t('yii', $format, ['delta' => $delta]); + } } From fd7ed282213f75f2bc9f5ca3d039a612cf682b0c Mon Sep 17 00:00:00 2001 From: David Renty Date: Wed, 12 Mar 2014 14:38:00 +0100 Subject: [PATCH 02/11] Typo in asElapsedTime description --- framework/base/Formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 481387711b..3de6442f19 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -457,7 +457,7 @@ class Formatter extends Component } /** - * Formats the value as a the time elapsed since then in human readable form. + * Formats the value as the time elapsed since then in human readable form. * @param integer|string|DateTime $value the value to be formatted. The following * types of value are supported: * From ced45c5450de5c6dda588036e347ef66ccbf1719 Mon Sep 17 00:00:00 2001 From: David Renty Date: Wed, 12 Mar 2014 14:49:28 +0100 Subject: [PATCH 03/11] Call Yii::t everytime instead of passing a template variable --- framework/base/Formatter.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 3de6442f19..31a2c15b89 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -457,7 +457,7 @@ class Formatter extends Component } /** - * Formats the value as the time elapsed since then in human readable form. + * Formats the value as the time elapsed since then in human readable form. * @param integer|string|DateTime $value the value to be formatted. The following * types of value are supported: * @@ -482,27 +482,25 @@ class Formatter extends Component if ($interval->y >= 1) { $delta = $interval->y; - $format = '{delta, plural, =1{a year} other{# years}} ago'; + return Yii::t('yii', '{delta, plural, =1{a year} other{# years}} ago', ['delta' => $delta]); } elseif ($interval->m >= 1) { $delta = $interval->m; - $format = '{delta, plural, =1{a month} other{# months}} ago'; + return Yii::t('yii', '{delta, plural, =1{a month} other{# months}} ago', ['delta' => $delta]); } elseif ($interval->d >= 7) { $delta = floor($interval->d / 7); - $format = '{delta, plural, =1{a week} other{# weeks}} ago'; + return Yii::t('yii', '{delta, plural, =1{a week} other{# weeks}} ago', ['delta' => $delta]); } elseif ($interval->d >= 1) { $delta = $interval->d; - $format = '{delta, plural, =1{yesterday} other{# days ago}}'; + return Yii::t('yii', '{delta, plural, =1{yesterday} other{# days ago}}', ['delta' => $delta]); } elseif ($interval->h >= 1) { $delta = $interval->h; - $format = '{delta, plural, =1{an hour} other{# hours}} ago'; + return Yii::t('yii', '{delta, plural, =1{an hour} other{# hours}} ago', ['delta' => $delta]); } elseif ($interval->i >= 1) { $delta = $interval->i; - $format = '{delta, plural, =1{a minute} other{# minutes}} ago'; + return Yii::t('yii', '{delta, plural, =1{a minute} other{# minutes}} ago', ['delta' => $delta]); } else { $delta = $interval->s; - $format = '{delta, plural, =1{a second} other{# seconds}} ago'; + return Yii::t('yii', '{delta, plural, =1{a second} other{# seconds}} ago', ['delta' => $delta]); } - - return Yii::t('yii', $format, ['delta' => $delta]); } } From a74fa20d2d0f107d4666a8e8cf9fc3c320ba7e25 Mon Sep 17 00:00:00 2001 From: David Renty Date: Wed, 12 Mar 2014 14:51:20 +0100 Subject: [PATCH 04/11] Typo --- framework/base/Formatter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 31a2c15b89..19a7419f19 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -457,7 +457,7 @@ class Formatter extends Component } /** - * Formats the value as the time elapsed since then in human readable form. + * Formats the value as the time elapsed since then in human readable form. * @param integer|string|DateTime $value the value to be formatted. The following * types of value are supported: * From f7871e2458124ac8cfb5b66ee7b97ec43a363c8a Mon Sep 17 00:00:00 2001 From: David Renty Date: Wed, 12 Mar 2014 15:57:20 +0100 Subject: [PATCH 05/11] asElapsedTime can now take DateInterval as parameter --- framework/base/Formatter.php | 46 ++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 19a7419f19..81f40ab57b 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -458,49 +458,59 @@ class Formatter extends Component /** * Formats the value as the time elapsed since then in human readable form. - * @param integer|string|DateTime $value the value to be formatted. The following + * @param integer|string|DateTime|DateInterval $value the value to be formatted. The following * types of value are supported: * * - an integer representing a UNIX timestamp * - a string that can be parsed into a UNIX timestamp via `strtotime()` * - a PHP DateTime object + * - a PHP DateInterval object * * @return string the formatted result */ public function asElapsedTime($value) { - if ($value === null) { - return $this->nullDisplay; + if ($value instanceof \DateInterval) { + $interval = $value; + } else { + if ($value === null) { + return $this->nullDisplay; + } + $value = $this->normalizeDatetimeValue($value); + + $dateNow = new DateTime('now', new \DateTimeZone($this->timeZone)); + $dateThen = new DateTime(null, new \DateTimeZone($this->timeZone)); + $dateThen->setTimestamp($value); + + $interval = $dateNow->diff($dateThen); } - $value = $this->normalizeDatetimeValue($value); - - $now = new \DateTime(); - $date = new DateTime(null, new \DateTimeZone($this->timeZone)); - $date->setTimestamp($value); - - $interval = $now->diff($date); if ($interval->y >= 1) { $delta = $interval->y; return Yii::t('yii', '{delta, plural, =1{a year} other{# years}} ago', ['delta' => $delta]); - } elseif ($interval->m >= 1) { + } + if ($interval->m >= 1) { $delta = $interval->m; return Yii::t('yii', '{delta, plural, =1{a month} other{# months}} ago', ['delta' => $delta]); - } elseif ($interval->d >= 7) { + } + if ($interval->d >= 7) { $delta = floor($interval->d / 7); return Yii::t('yii', '{delta, plural, =1{a week} other{# weeks}} ago', ['delta' => $delta]); - } elseif ($interval->d >= 1) { + } + if ($interval->d >= 1) { $delta = $interval->d; return Yii::t('yii', '{delta, plural, =1{yesterday} other{# days ago}}', ['delta' => $delta]); - } elseif ($interval->h >= 1) { + } + if ($interval->h >= 1) { $delta = $interval->h; return Yii::t('yii', '{delta, plural, =1{an hour} other{# hours}} ago', ['delta' => $delta]); - } elseif ($interval->i >= 1) { + } + if ($interval->i >= 1) { $delta = $interval->i; return Yii::t('yii', '{delta, plural, =1{a minute} other{# minutes}} ago', ['delta' => $delta]); - } else { - $delta = $interval->s; - return Yii::t('yii', '{delta, plural, =1{a second} other{# seconds}} ago', ['delta' => $delta]); } + + $delta = $interval->s; + return Yii::t('yii', '{delta, plural, =1{a second} other{# seconds}} ago', ['delta' => $delta]); } } From b7cf6183481c4749165344c639aa0025714cbed3 Mon Sep 17 00:00:00 2001 From: David Renty Date: Wed, 12 Mar 2014 16:02:45 +0100 Subject: [PATCH 06/11] asElapsedTime style improvements --- framework/base/Formatter.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 81f40ab57b..270e4d0ebe 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -470,16 +470,19 @@ class Formatter extends Component */ public function asElapsedTime($value) { + if ($value === null) { + return $this->nullDisplay; + } + if ($value instanceof \DateInterval) { $interval = $value; } else { - if ($value === null) { - return $this->nullDisplay; - } $value = $this->normalizeDatetimeValue($value); - $dateNow = new DateTime('now', new \DateTimeZone($this->timeZone)); - $dateThen = new DateTime(null, new \DateTimeZone($this->timeZone)); + $timezone = new \DateTimeZone($this->timeZone); + + $dateNow = new DateTime('now', $timezone); + $dateThen = new DateTime(null, $timezone); $dateThen->setTimestamp($value); $interval = $dateNow->diff($dateThen); From b5cd0a6f0cb326c1de6f899d642023619b6590e9 Mon Sep 17 00:00:00 2001 From: David Renty Date: Wed, 12 Mar 2014 16:58:12 +0100 Subject: [PATCH 07/11] asElapsedTime can now take a DateInterval string as a parameter --- framework/base/Formatter.php | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 270e4d0ebe..01153d21bd 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -462,7 +462,7 @@ class Formatter extends Component * types of value are supported: * * - an integer representing a UNIX timestamp - * - a string that can be parsed into a UNIX timestamp via `strtotime()` + * - a string that can be parsed into a UNIX timestamp via `strtotime()` or that can be passed to a DateInterval constructor. * - a PHP DateTime object * - a PHP DateInterval object * @@ -477,15 +477,26 @@ class Formatter extends Component if ($value instanceof \DateInterval) { $interval = $value; } else { - $value = $this->normalizeDatetimeValue($value); + $timestamp = $this->normalizeDatetimeValue($value); - $timezone = new \DateTimeZone($this->timeZone); + if ($timestamp === false) { + // $value is not a valid date/time value, so we try + // to create a DateInterval with it + try { + $interval = new \DateInterval($value); + } catch (Exception $e) { + // invalid date/time and invalid interval + return $this->nullDisplay; + } + } else { + $timezone = new \DateTimeZone($this->timeZone); - $dateNow = new DateTime('now', $timezone); - $dateThen = new DateTime(null, $timezone); - $dateThen->setTimestamp($value); + $dateNow = new DateTime('now', $timezone); + $dateThen = new DateTime(null, $timezone); + $dateThen->setTimestamp($timestamp); - $interval = $dateNow->diff($dateThen); + $interval = $dateNow->diff($dateThen); + } } if ($interval->y >= 1) { From cb3eb9c6d80720dada5e9f12ab553c8e456d2f0b Mon Sep 17 00:00:00 2001 From: David Renty Date: Fri, 14 Mar 2014 18:29:23 +0100 Subject: [PATCH 08/11] Added support for inverted intervals (future time) and unit tests --- framework/base/Formatter.php | 77 ++++++---- tests/unit/framework/base/FormatterTest.php | 154 ++++++++++++++++++++ 2 files changed, 202 insertions(+), 29 deletions(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index 01153d21bd..d4e4f092a2 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -468,7 +468,7 @@ class Formatter extends Component * * @return string the formatted result */ - public function asElapsedTime($value) + public function asRelativeTime($value, $referenceTime=null) { if ($value === null) { return $this->nullDisplay; @@ -490,41 +490,60 @@ class Formatter extends Component } } else { $timezone = new \DateTimeZone($this->timeZone); + + if ($referenceTime === null) { + $dateNow = new DateTime('now', $timezone); + } else { + $referenceTime = $this->normalizeDatetimeValue($referenceTime); + $dateNow = new DateTime(null, $timezone); + $dateNow->setTimestamp($referenceTime); + } - $dateNow = new DateTime('now', $timezone); $dateThen = new DateTime(null, $timezone); $dateThen->setTimestamp($timestamp); - $interval = $dateNow->diff($dateThen); + $interval = $dateThen->diff($dateNow); + var_dump($dateThen); + var_dump($dateNow); } } - if ($interval->y >= 1) { - $delta = $interval->y; - return Yii::t('yii', '{delta, plural, =1{a year} other{# years}} ago', ['delta' => $delta]); - } - if ($interval->m >= 1) { - $delta = $interval->m; - return Yii::t('yii', '{delta, plural, =1{a month} other{# months}} ago', ['delta' => $delta]); - } - if ($interval->d >= 7) { - $delta = floor($interval->d / 7); - return Yii::t('yii', '{delta, plural, =1{a week} other{# weeks}} ago', ['delta' => $delta]); - } - if ($interval->d >= 1) { - $delta = $interval->d; - return Yii::t('yii', '{delta, plural, =1{yesterday} other{# days ago}}', ['delta' => $delta]); - } - if ($interval->h >= 1) { - $delta = $interval->h; - return Yii::t('yii', '{delta, plural, =1{an hour} other{# hours}} ago', ['delta' => $delta]); - } - if ($interval->i >= 1) { - $delta = $interval->i; - return Yii::t('yii', '{delta, plural, =1{a minute} other{# minutes}} ago', ['delta' => $delta]); - } + if ($interval->invert) { + if ($interval->y >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{a year} other{# years}}', ['delta' => $interval->y]); + } + if ($interval->m >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{a month} other{# months}}', ['delta' => $interval->m]); + } + if ($interval->d >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{a day} other{# days}}', ['delta' => $interval->d]); + } + if ($interval->h >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{an hour} other{# hours}}', ['delta' => $interval->h]); + } + if ($interval->i >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{a minute} other{# minutes}}', ['delta' => $interval->i]); + } - $delta = $interval->s; - return Yii::t('yii', '{delta, plural, =1{a second} other{# seconds}} ago', ['delta' => $delta]); + return Yii::t('yii', 'in {delta, plural, =1{a second} other{# seconds}}', ['delta' => $interval->s]); + } else { + if ($interval->y >= 1) { + return Yii::t('yii', '{delta, plural, =1{a year} other{# years}} ago', ['delta' => $interval->y]); + } + if ($interval->m >= 1) { + return Yii::t('yii', '{delta, plural, =1{a month} other{# months}} ago', ['delta' => $interval->m]); + } + if ($interval->d >= 1) { + return Yii::t('yii', '{delta, plural, =1{a day} other{# days}} ago', ['delta' => $interval->d]); + } + if ($interval->h >= 1) { + return Yii::t('yii', '{delta, plural, =1{an hour} other{# hours}} ago', ['delta' => $interval->h]); + } + if ($interval->i >= 1) { + return Yii::t('yii', '{delta, plural, =1{a minute} other{# minutes}} ago', ['delta' => $interval->i]); + } + + return Yii::t('yii', '{delta, plural, =1{a second} other{# seconds}} ago', ['delta' => $interval->s]); + } } } diff --git a/tests/unit/framework/base/FormatterTest.php b/tests/unit/framework/base/FormatterTest.php index 322b751a11..97a87be694 100644 --- a/tests/unit/framework/base/FormatterTest.php +++ b/tests/unit/framework/base/FormatterTest.php @@ -8,6 +8,8 @@ namespace yiiunit\framework\base; use yii\base\Formatter; use yiiunit\TestCase; +use DateTime; +use DateInterval; /** * @group base @@ -197,4 +199,156 @@ class FormatterTest extends TestCase $this->setExpectedException('\yii\base\InvalidParamException'); $this->assertSame(date('Y-m-d', $value), $this->formatter->format($value, 'data')); } + + private function buildDateSubIntervals($referenceDate, $intervals) + { + $date = new DateTime($referenceDate); + foreach ($intervals as $interval) { + $date->sub($interval); + } + return $date; + } + + public function testAsRelativeTime() + { + $interval_1_second = new DateInterval("PT1S"); + $interval_244_seconds = new DateInterval("PT244S"); + $interval_1_minute = new DateInterval("PT1M"); + $interval_33_minutes = new DateInterval("PT33M"); + $interval_1_hour = new DateInterval("PT1H"); + $interval_6_hours = new DateInterval("PT6H"); + $interval_1_day = new DateInterval("P1D"); + $interval_89_days = new DateInterval("P89D"); + $interval_1_month = new DateInterval("P1M"); + $interval_5_months = new DateInterval("P5M"); + $interval_1_year = new DateInterval("P1Y"); + $interval_12_years = new DateInterval("P12Y"); + + // Pass a DateInterval + $this->assertSame('a second ago', $this->formatter->asRelativeTime($interval_1_second)); + $this->assertSame('244 seconds ago', $this->formatter->asRelativeTime($interval_244_seconds)); + $this->assertSame('a minute ago', $this->formatter->asRelativeTime($interval_1_minute)); + $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($interval_33_minutes)); + $this->assertSame('an hour ago', $this->formatter->asRelativeTime($interval_1_hour)); + $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($interval_6_hours)); + $this->assertSame('a day ago', $this->formatter->asRelativeTime($interval_1_day)); + $this->assertSame('89 days ago', $this->formatter->asRelativeTime($interval_89_days)); + $this->assertSame('a month ago', $this->formatter->asRelativeTime($interval_1_month)); + $this->assertSame('5 months ago', $this->formatter->asRelativeTime($interval_5_months)); + $this->assertSame('a year ago', $this->formatter->asRelativeTime($interval_1_year)); + $this->assertSame('12 years ago', $this->formatter->asRelativeTime($interval_12_years)); + + // Pass a DateInterval string + $this->assertSame('a year ago', $this->formatter->asRelativeTime('2007-03-01T13:00:00Z/2008-05-11T15:30:00Z')); + $this->assertSame('a year ago', $this->formatter->asRelativeTime('2007-03-01T13:00:00Z/P1Y2M10DT2H30M')); + $this->assertSame('a year ago', $this->formatter->asRelativeTime('P1Y2M10DT2H30M/2008-05-11T15:30:00Z')); + $this->assertSame('a year ago', $this->formatter->asRelativeTime('P1Y2M10DT2H30M')); + $this->assertSame('94 months ago', $this->formatter->asRelativeTime('P94M')); + + // Force the reference time and pass a past DateTime + $dateNow = new DateTime('2014-03-13'); + $this->assertSame('a second ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_second]), $dateNow)); + $this->assertSame('4 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_244_seconds]), $dateNow)); + $this->assertSame('a minute ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_minute]), $dateNow)); + $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_33_minutes]), $dateNow)); + $this->assertSame('an hour ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_hour]), $dateNow)); + $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_6_hours]), $dateNow)); + $this->assertSame('a day ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_day]), $dateNow)); + $this->assertSame('2 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_89_days]), $dateNow)); + $this->assertSame('a month ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_month]), $dateNow)); + $this->assertSame('5 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_5_months]), $dateNow)); + $this->assertSame('a year ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_year]), $dateNow)); + $this->assertSame('12 years ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_12_years]), $dateNow)); + + // Tricky 31-days month stuff + // See: http://www.gnu.org/software/tar/manual/html_section/Relative-items-in-date-strings.html + $dateNow = new DateTime('2014-03-31'); + $dateThen = new DateTime('2014-03-03'); + $this->assertSame('28 days ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-31', [$interval_1_month]), $dateNow)); + $this->assertSame('28 days ago', $this->formatter->asRelativeTime($dateThen, $dateNow)); + $dateThen = new DateTime('2014-02-28'); + $this->assertSame('a month ago', $this->formatter->asRelativeTime($dateThen, $dateNow)); + + // Relative to current time tests (can't test with seconds though) + $this->assertSame('4 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_244_seconds]))); + $this->assertSame('a minute ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_minute]))); + $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_33_minutes]))); + $this->assertSame('an hour ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_hour]))); + $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_6_hours]))); + $this->assertSame('a day ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_day]))); + $this->assertSame('2 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_89_days]))); + $this->assertSame('a month ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_month]))); + $this->assertSame('5 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_5_months]))); + $this->assertSame('a year ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_year]))); + $this->assertSame('12 years ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_12_years]))); + + // Invert all the DateIntervals + $interval_1_second->invert = true; + $interval_244_seconds->invert = true; + $interval_1_minute->invert = true; + $interval_33_minutes->invert = true; + $interval_1_hour->invert = true; + $interval_6_hours->invert = true; + $interval_1_day->invert = true; + $interval_89_days->invert = true; + $interval_1_month->invert = true; + $interval_5_months->invert = true; + $interval_1_year->invert = true; + $interval_12_years->invert = true; + + // Pass a inverted DateInterval + $this->assertSame('in a second', $this->formatter->asRelativeTime($interval_1_second)); + $this->assertSame('in 244 seconds', $this->formatter->asRelativeTime($interval_244_seconds)); + $this->assertSame('in a minute', $this->formatter->asRelativeTime($interval_1_minute)); + $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($interval_33_minutes)); + $this->assertSame('in an hour', $this->formatter->asRelativeTime($interval_1_hour)); + $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($interval_6_hours)); + $this->assertSame('in a day', $this->formatter->asRelativeTime($interval_1_day)); + $this->assertSame('in 89 days', $this->formatter->asRelativeTime($interval_89_days)); + $this->assertSame('in a month', $this->formatter->asRelativeTime($interval_1_month)); + $this->assertSame('in 5 months', $this->formatter->asRelativeTime($interval_5_months)); + $this->assertSame('in a year', $this->formatter->asRelativeTime($interval_1_year)); + $this->assertSame('in 12 years', $this->formatter->asRelativeTime($interval_12_years)); + + // Pass a inverted DateInterval string + $this->assertSame('in a year', $this->formatter->asRelativeTime('2008-05-11T15:30:00Z/2007-03-01T13:00:00Z')); + + // Force the reference time and pass a future DateTime + $dateNow = new DateTime('2014-03-13'); + $this->assertSame('in a second', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_second]), $dateNow)); + $this->assertSame('in 4 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_244_seconds]), $dateNow)); + $this->assertSame('in a minute', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_minute]), $dateNow)); + $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_33_minutes]), $dateNow)); + $this->assertSame('in an hour', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_hour]), $dateNow)); + $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_6_hours]), $dateNow)); + $this->assertSame('in a day', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_day]), $dateNow)); + $this->assertSame('in 2 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_89_days]), $dateNow)); + $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_month]), $dateNow)); + $this->assertSame('in 5 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_5_months]), $dateNow)); + $this->assertSame('in a year', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_year]), $dateNow)); + $this->assertSame('in 12 years', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_12_years]), $dateNow)); + + // Tricky 31-days month stuff + // See: http://www.gnu.org/software/tar/manual/html_section/Relative-items-in-date-strings.html + $dateNow = new DateTime('2014-03-03'); + $dateThen = new DateTime('2014-03-31'); + $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-03', [$interval_1_month]), $dateNow)); + $this->assertSame('in 28 days', $this->formatter->asRelativeTime($dateThen, $dateNow)); + + // Relative to current time tests (can't test with seconds though) + // We add 5 seconds to compensate for tests computation time + $interval_5_seconds = new DateInterval('PT5S'); + $interval_5_seconds->invert = true; + $this->assertSame('in 4 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_244_seconds, $interval_5_seconds]))); + $this->assertSame('in a minute', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_minute, $interval_5_seconds]))); + $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_33_minutes, $interval_5_seconds]))); + $this->assertSame('in an hour', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_hour, $interval_5_seconds]))); + $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_6_hours, $interval_5_seconds]))); + $this->assertSame('in a day', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_day, $interval_5_seconds]))); + $this->assertSame('in 2 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_89_days, $interval_5_seconds]))); + $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_month, $interval_5_seconds]))); + $this->assertSame('in 5 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_5_months, $interval_5_seconds]))); + $this->assertSame('in a year', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_year, $interval_5_seconds]))); + $this->assertSame('in 12 years', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_12_years, $interval_5_seconds]))); + } } From 0fa5230cd062ebe2653dbf759b6afcd8092fc380 Mon Sep 17 00:00:00 2001 From: David Renty Date: Fri, 14 Mar 2014 18:37:11 +0100 Subject: [PATCH 09/11] Removed debug code, changed doc --- framework/base/Formatter.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index d4e4f092a2..c23d43b026 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -457,7 +457,7 @@ class Formatter extends Component } /** - * Formats the value as the time elapsed since then in human readable form. + * Formats the value as the time interval between a date and now in human readable form. * @param integer|string|DateTime|DateInterval $value the value to be formatted. The following * types of value are supported: * @@ -503,8 +503,6 @@ class Formatter extends Component $dateThen->setTimestamp($timestamp); $interval = $dateThen->diff($dateNow); - var_dump($dateThen); - var_dump($dateNow); } } From 91e4ad5978c0ae155407b0b60a828e8e0e7ffebf Mon Sep 17 00:00:00 2001 From: David Renty Date: Mon, 17 Mar 2014 12:02:26 +0100 Subject: [PATCH 10/11] PSR-2 compliance --- framework/base/Formatter.php | 972 ++++++++++---------- tests/unit/framework/base/FormatterTest.php | 610 ++++++------ 2 files changed, 792 insertions(+), 790 deletions(-) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index c23d43b026..790419451b 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -27,521 +27,523 @@ use yii\helpers\Html; */ class Formatter extends Component { - /** - * @var string the timezone to use for formatting time and date values. - * This can be any value that may be passed to [date_default_timezone_set()](http://www.php.net/manual/en/function.date-default-timezone-set.php) - * e.g. `UTC`, `Europe/Berlin` or `America/Chicago`. - * Refer to the [php manual](http://www.php.net/manual/en/timezones.php) for available timezones. - * If this property is not set, [[\yii\base\Application::timezone]] will be used. - */ - public $timeZone; - /** - * @var string the default format string to be used to format a date using PHP date() function. - */ - public $dateFormat = 'Y/m/d'; - /** - * @var string the default format string to be used to format a time using PHP date() function. - */ - public $timeFormat = 'h:i:s A'; - /** - * @var string the default format string to be used to format a date and time using PHP date() function. - */ - public $datetimeFormat = 'Y/m/d h:i:s A'; - /** - * @var string the text to be displayed when formatting a null. Defaults to '(not set)'. - */ - public $nullDisplay; - /** - * @var array the text to be displayed when formatting a boolean value. The first element corresponds - * to the text display for false, the second element for true. Defaults to `['No', 'Yes']`. - */ - public $booleanFormat; - /** - * @var string the character displayed as the decimal point when formatting a number. - * If not set, "." will be used. - */ - public $decimalSeparator; - /** - * @var string the character displayed as the thousands separator character when formatting a number. - * If not set, "," will be used. - */ - public $thousandSeparator; - /** - * @var array the format used to format size (bytes). Three elements may be specified: "base", "decimals" and "decimalSeparator". - * They correspond to the base at which a kilobyte is calculated (1000 or 1024 bytes per kilobyte, defaults to 1024), - * the number of digits after the decimal point (defaults to 2) and the character displayed as the decimal point. - */ - public $sizeFormat = [ - 'base' => 1024, - 'decimals' => 2, - 'decimalSeparator' => null, - ]; + /** + * @var string the timezone to use for formatting time and date values. + * This can be any value that may be passed to [date_default_timezone_set()](http://www.php.net/manual/en/function.date-default-timezone-set.php) + * e.g. `UTC`, `Europe/Berlin` or `America/Chicago`. + * Refer to the [php manual](http://www.php.net/manual/en/timezones.php) for available timezones. + * If this property is not set, [[\yii\base\Application::timezone]] will be used. + */ + public $timeZone; + /** + * @var string the default format string to be used to format a date using PHP date() function. + */ + public $dateFormat = 'Y/m/d'; + /** + * @var string the default format string to be used to format a time using PHP date() function. + */ + public $timeFormat = 'h:i:s A'; + /** + * @var string the default format string to be used to format a date and time using PHP date() function. + */ + public $datetimeFormat = 'Y/m/d h:i:s A'; + /** + * @var string the text to be displayed when formatting a null. Defaults to '(not set)'. + */ + public $nullDisplay; + /** + * @var array the text to be displayed when formatting a boolean value. The first element corresponds + * to the text display for false, the second element for true. Defaults to `['No', 'Yes']`. + */ + public $booleanFormat; + /** + * @var string the character displayed as the decimal point when formatting a number. + * If not set, "." will be used. + */ + public $decimalSeparator; + /** + * @var string the character displayed as the thousands separator character when formatting a number. + * If not set, "," will be used. + */ + public $thousandSeparator; + /** + * @var array the format used to format size (bytes). Three elements may be specified: "base", "decimals" and "decimalSeparator". + * They correspond to the base at which a kilobyte is calculated (1000 or 1024 bytes per kilobyte, defaults to 1024), + * the number of digits after the decimal point (defaults to 2) and the character displayed as the decimal point. + */ + public $sizeFormat = [ + 'base' => 1024, + 'decimals' => 2, + 'decimalSeparator' => null, + ]; - /** - * Initializes the component. - */ - public function init() - { - if ($this->timeZone === null) { - $this->timeZone = Yii::$app->timeZone; - } + /** + * Initializes the component. + */ + public function init() + { + if ($this->timeZone === null) { + $this->timeZone = Yii::$app->timeZone; + } - if (empty($this->booleanFormat)) { - $this->booleanFormat = [Yii::t('yii', 'No'), Yii::t('yii', 'Yes')]; - } - if ($this->nullDisplay === null) { - $this->nullDisplay = '' . Yii::t('yii', '(not set)') . ''; - } - } + if (empty($this->booleanFormat)) { + $this->booleanFormat = [Yii::t('yii', 'No'), Yii::t('yii', 'Yes')]; + } + if ($this->nullDisplay === null) { + $this->nullDisplay = '' . Yii::t('yii', '(not set)') . ''; + } + } - /** - * Formats the value based on the given format type. - * This method will call one of the "as" methods available in this class to do the formatting. - * For type "xyz", the method "asXyz" will be used. For example, if the format is "html", - * then [[asHtml()]] will be used. Format names are case insensitive. - * @param mixed $value the value to be formatted - * @param string|array $format the format of the value, e.g., "html", "text". To specify additional - * parameters of the formatting method, you may use an array. The first element of the array - * specifies the format name, while the rest of the elements will be used as the parameters to the formatting - * method. For example, a format of `['date', 'Y-m-d']` will cause the invocation of `asDate($value, 'Y-m-d')`. - * @return string the formatting result - * @throws InvalidParamException if the type is not supported by this class. - */ - public function format($value, $format) - { - if (is_array($format)) { - if (!isset($format[0])) { - throw new InvalidParamException('The $format array must contain at least one element.'); - } - $f = $format[0]; - $format[0] = $value; - $params = $format; - $format = $f; - } else { - $params = [$value]; - } - $method = 'as' . $format; - if ($this->hasMethod($method)) { - return call_user_func_array([$this, $method], $params); - } else { - throw new InvalidParamException("Unknown type: $format"); - } - } + /** + * Formats the value based on the given format type. + * This method will call one of the "as" methods available in this class to do the formatting. + * For type "xyz", the method "asXyz" will be used. For example, if the format is "html", + * then [[asHtml()]] will be used. Format names are case insensitive. + * @param mixed $value the value to be formatted + * @param string|array $format the format of the value, e.g., "html", "text". To specify additional + * parameters of the formatting method, you may use an array. The first element of the array + * specifies the format name, while the rest of the elements will be used as the parameters to the formatting + * method. For example, a format of `['date', 'Y-m-d']` will cause the invocation of `asDate($value, 'Y-m-d')`. + * @return string the formatting result + * @throws InvalidParamException if the type is not supported by this class. + */ + public function format($value, $format) + { + if (is_array($format)) { + if (!isset($format[0])) { + throw new InvalidParamException('The $format array must contain at least one element.'); + } + $f = $format[0]; + $format[0] = $value; + $params = $format; + $format = $f; + } else { + $params = [$value]; + } + $method = 'as' . $format; + if ($this->hasMethod($method)) { + return call_user_func_array([$this, $method], $params); + } else { + throw new InvalidParamException("Unknown type: $format"); + } + } - /** - * Formats the value as is without any formatting. - * This method simply returns back the parameter without any format. - * @param mixed $value the value to be formatted - * @return string the formatted result - */ - public function asRaw($value) - { - if ($value === null) { - return $this->nullDisplay; - } - return $value; - } + /** + * Formats the value as is without any formatting. + * This method simply returns back the parameter without any format. + * @param mixed $value the value to be formatted + * @return string the formatted result + */ + public function asRaw($value) + { + if ($value === null) { + return $this->nullDisplay; + } + return $value; + } - /** - * Formats the value as an HTML-encoded plain text. - * @param mixed $value the value to be formatted - * @return string the formatted result - */ - public function asText($value) - { - if ($value === null) { - return $this->nullDisplay; - } - return Html::encode($value); - } + /** + * Formats the value as an HTML-encoded plain text. + * @param mixed $value the value to be formatted + * @return string the formatted result + */ + public function asText($value) + { + if ($value === null) { + return $this->nullDisplay; + } + return Html::encode($value); + } - /** - * Formats the value as an HTML-encoded plain text with newlines converted into breaks. - * @param mixed $value the value to be formatted - * @return string the formatted result - */ - public function asNtext($value) - { - if ($value === null) { - return $this->nullDisplay; - } - return nl2br(Html::encode($value)); - } + /** + * Formats the value as an HTML-encoded plain text with newlines converted into breaks. + * @param mixed $value the value to be formatted + * @return string the formatted result + */ + public function asNtext($value) + { + if ($value === null) { + return $this->nullDisplay; + } + return nl2br(Html::encode($value)); + } - /** - * Formats the value as HTML-encoded text paragraphs. - * Each text paragraph is enclosed within a `

` tag. - * One or multiple consecutive empty lines divide two paragraphs. - * @param mixed $value the value to be formatted - * @return string the formatted result - */ - public function asParagraphs($value) - { - if ($value === null) { - return $this->nullDisplay; - } - return str_replace('

', '', - '

' . preg_replace('/[\r\n]{2,}/', "

\n

", Html::encode($value)) . '

' - ); - } + /** + * Formats the value as HTML-encoded text paragraphs. + * Each text paragraph is enclosed within a `

` tag. + * One or multiple consecutive empty lines divide two paragraphs. + * @param mixed $value the value to be formatted + * @return string the formatted result + */ + public function asParagraphs($value) + { + if ($value === null) { + return $this->nullDisplay; + } + return str_replace( + '

', + '', + '

' . preg_replace('/[\r\n]{2,}/', "

\n

", Html::encode($value)) . '

' + ); + } - /** - * Formats the value as HTML text. - * The value will be purified using [[HtmlPurifier]] to avoid XSS attacks. - * Use [[asRaw()]] if you do not want any purification of the value. - * @param mixed $value the value to be formatted - * @param array|null $config the configuration for the HTMLPurifier class. - * @return string the formatted result - */ - public function asHtml($value, $config = null) - { - if ($value === null) { - return $this->nullDisplay; - } - return HtmlPurifier::process($value, $config); - } + /** + * Formats the value as HTML text. + * The value will be purified using [[HtmlPurifier]] to avoid XSS attacks. + * Use [[asRaw()]] if you do not want any purification of the value. + * @param mixed $value the value to be formatted + * @param array|null $config the configuration for the HTMLPurifier class. + * @return string the formatted result + */ + public function asHtml($value, $config = null) + { + if ($value === null) { + return $this->nullDisplay; + } + return HtmlPurifier::process($value, $config); + } - /** - * Formats the value as a mailto link. - * @param mixed $value the value to be formatted - * @return string the formatted result - */ - public function asEmail($value) - { - if ($value === null) { - return $this->nullDisplay; - } - return Html::mailto(Html::encode($value), $value); - } + /** + * Formats the value as a mailto link. + * @param mixed $value the value to be formatted + * @return string the formatted result + */ + public function asEmail($value) + { + if ($value === null) { + return $this->nullDisplay; + } + return Html::mailto(Html::encode($value), $value); + } - /** - * Formats the value as an image tag. - * @param mixed $value the value to be formatted - * @return string the formatted result - */ - public function asImage($value) - { - if ($value === null) { - return $this->nullDisplay; - } - return Html::img($value); - } + /** + * Formats the value as an image tag. + * @param mixed $value the value to be formatted + * @return string the formatted result + */ + public function asImage($value) + { + if ($value === null) { + return $this->nullDisplay; + } + return Html::img($value); + } - /** - * Formats the value as a hyperlink. - * @param mixed $value the value to be formatted - * @return string the formatted result - */ - public function asUrl($value) - { - if ($value === null) { - return $this->nullDisplay; - } - $url = $value; - if (strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) { - $url = 'http://' . $url; - } - return Html::a(Html::encode($value), $url); - } + /** + * Formats the value as a hyperlink. + * @param mixed $value the value to be formatted + * @return string the formatted result + */ + public function asUrl($value) + { + if ($value === null) { + return $this->nullDisplay; + } + $url = $value; + if (strpos($url, 'http://') !== 0 && strpos($url, 'https://') !== 0) { + $url = 'http://' . $url; + } + return Html::a(Html::encode($value), $url); + } - /** - * Formats the value as a boolean. - * @param mixed $value the value to be formatted - * @return string the formatted result - * @see booleanFormat - */ - public function asBoolean($value) - { - if ($value === null) { - return $this->nullDisplay; - } - return $value ? $this->booleanFormat[1] : $this->booleanFormat[0]; - } + /** + * Formats the value as a boolean. + * @param mixed $value the value to be formatted + * @return string the formatted result + * @see booleanFormat + */ + public function asBoolean($value) + { + if ($value === null) { + return $this->nullDisplay; + } + return $value ? $this->booleanFormat[1] : $this->booleanFormat[0]; + } - /** - * Formats the value as a date. - * @param integer|string|DateTime $value the value to be formatted. The following - * types of value are supported: - * - * - an integer representing a UNIX timestamp - * - a string that can be parsed into a UNIX timestamp via `strtotime()` - * - a PHP DateTime object - * - * @param string $format the format used to convert the value into a date string. - * If null, [[dateFormat]] will be used. The format string should be one - * that can be recognized by the PHP `date()` function. - * @return string the formatted result - * @see dateFormat - */ - public function asDate($value, $format = null) - { - if ($value === null) { - return $this->nullDisplay; - } - $value = $this->normalizeDatetimeValue($value); - return $this->formatTimestamp($value, $format === null ? $this->dateFormat : $format); - } + /** + * Formats the value as a date. + * @param integer|string|DateTime $value the value to be formatted. The following + * types of value are supported: + * + * - an integer representing a UNIX timestamp + * - a string that can be parsed into a UNIX timestamp via `strtotime()` + * - a PHP DateTime object + * + * @param string $format the format used to convert the value into a date string. + * If null, [[dateFormat]] will be used. The format string should be one + * that can be recognized by the PHP `date()` function. + * @return string the formatted result + * @see dateFormat + */ + public function asDate($value, $format = null) + { + if ($value === null) { + return $this->nullDisplay; + } + $value = $this->normalizeDatetimeValue($value); + return $this->formatTimestamp($value, $format === null ? $this->dateFormat : $format); + } - /** - * Formats the value as a time. - * @param integer|string|DateTime $value the value to be formatted. The following - * types of value are supported: - * - * - an integer representing a UNIX timestamp - * - a string that can be parsed into a UNIX timestamp via `strtotime()` - * - a PHP DateTime object - * - * @param string $format the format used to convert the value into a date string. - * If null, [[timeFormat]] will be used. The format string should be one - * that can be recognized by the PHP `date()` function. - * @return string the formatted result - * @see timeFormat - */ - public function asTime($value, $format = null) - { - if ($value === null) { - return $this->nullDisplay; - } - $value = $this->normalizeDatetimeValue($value); - return $this->formatTimestamp($value, $format === null ? $this->timeFormat : $format); - } + /** + * Formats the value as a time. + * @param integer|string|DateTime $value the value to be formatted. The following + * types of value are supported: + * + * - an integer representing a UNIX timestamp + * - a string that can be parsed into a UNIX timestamp via `strtotime()` + * - a PHP DateTime object + * + * @param string $format the format used to convert the value into a date string. + * If null, [[timeFormat]] will be used. The format string should be one + * that can be recognized by the PHP `date()` function. + * @return string the formatted result + * @see timeFormat + */ + public function asTime($value, $format = null) + { + if ($value === null) { + return $this->nullDisplay; + } + $value = $this->normalizeDatetimeValue($value); + return $this->formatTimestamp($value, $format === null ? $this->timeFormat : $format); + } - /** - * Formats the value as a datetime. - * @param integer|string|DateTime $value the value to be formatted. The following - * types of value are supported: - * - * - an integer representing a UNIX timestamp - * - a string that can be parsed into a UNIX timestamp via `strtotime()` - * - a PHP DateTime object - * - * @param string $format the format used to convert the value into a date string. - * If null, [[datetimeFormat]] will be used. The format string should be one - * that can be recognized by the PHP `date()` function. - * @return string the formatted result - * @see datetimeFormat - */ - public function asDatetime($value, $format = null) - { - if ($value === null) { - return $this->nullDisplay; - } - $value = $this->normalizeDatetimeValue($value); - return $this->formatTimestamp($value, $format === null ? $this->datetimeFormat : $format); - } + /** + * Formats the value as a datetime. + * @param integer|string|DateTime $value the value to be formatted. The following + * types of value are supported: + * + * - an integer representing a UNIX timestamp + * - a string that can be parsed into a UNIX timestamp via `strtotime()` + * - a PHP DateTime object + * + * @param string $format the format used to convert the value into a date string. + * If null, [[datetimeFormat]] will be used. The format string should be one + * that can be recognized by the PHP `date()` function. + * @return string the formatted result + * @see datetimeFormat + */ + public function asDatetime($value, $format = null) + { + if ($value === null) { + return $this->nullDisplay; + } + $value = $this->normalizeDatetimeValue($value); + return $this->formatTimestamp($value, $format === null ? $this->datetimeFormat : $format); + } - /** - * Normalizes the given datetime value as one that can be taken by various date/time formatting methods. - * @param mixed $value the datetime value to be normalized. - * @return integer the normalized datetime value - */ - protected function normalizeDatetimeValue($value) - { - if (is_string($value)) { - return is_numeric($value) || $value === '' ? (int)$value : strtotime($value); - } elseif ($value instanceof DateTime) { - return $value->getTimestamp(); - } else { - return (int)$value; - } - } + /** + * Normalizes the given datetime value as one that can be taken by various date/time formatting methods. + * @param mixed $value the datetime value to be normalized. + * @return integer the normalized datetime value + */ + protected function normalizeDatetimeValue($value) + { + if (is_string($value)) { + return is_numeric($value) || $value === '' ? (int)$value : strtotime($value); + } elseif ($value instanceof DateTime) { + return $value->getTimestamp(); + } else { + return (int)$value; + } + } - /** - * @param integer $value normalized datetime value - * @param string $format the format used to convert the value into a date string. - * @return string the formatted result - */ - protected function formatTimestamp($value, $format) - { - $date = new DateTime(null, new \DateTimeZone($this->timeZone)); - $date->setTimestamp($value); - return $date->format($format); - } + /** + * @param integer $value normalized datetime value + * @param string $format the format used to convert the value into a date string. + * @return string the formatted result + */ + protected function formatTimestamp($value, $format) + { + $date = new DateTime(null, new \DateTimeZone($this->timeZone)); + $date->setTimestamp($value); + return $date->format($format); + } - /** - * Formats the value as an integer. - * @param mixed $value the value to be formatted - * @return string the formatting result. - */ - public function asInteger($value) - { - if ($value === null) { - return $this->nullDisplay; - } - if (is_string($value) && preg_match('/^(-?\d+)/', $value, $matches)) { - return $matches[1]; - } else { - $value = (int)$value; - return "$value"; - } - } + /** + * Formats the value as an integer. + * @param mixed $value the value to be formatted + * @return string the formatting result. + */ + public function asInteger($value) + { + if ($value === null) { + return $this->nullDisplay; + } + if (is_string($value) && preg_match('/^(-?\d+)/', $value, $matches)) { + return $matches[1]; + } else { + $value = (int)$value; + return "$value"; + } + } - /** - * Formats the value as a double number. - * Property [[decimalSeparator]] will be used to represent the decimal point. - * @param mixed $value the value to be formatted - * @param integer $decimals the number of digits after the decimal point - * @return string the formatting result. - * @see decimalSeparator - */ - public function asDouble($value, $decimals = 2) - { - if ($value === null) { - return $this->nullDisplay; - } - if ($this->decimalSeparator === null) { - return sprintf("%.{$decimals}f", $value); - } else { - return str_replace('.', $this->decimalSeparator, sprintf("%.{$decimals}f", $value)); - } - } + /** + * Formats the value as a double number. + * Property [[decimalSeparator]] will be used to represent the decimal point. + * @param mixed $value the value to be formatted + * @param integer $decimals the number of digits after the decimal point + * @return string the formatting result. + * @see decimalSeparator + */ + public function asDouble($value, $decimals = 2) + { + if ($value === null) { + return $this->nullDisplay; + } + if ($this->decimalSeparator === null) { + return sprintf("%.{$decimals}f", $value); + } else { + return str_replace('.', $this->decimalSeparator, sprintf("%.{$decimals}f", $value)); + } + } - /** - * Formats the value as a number with decimal and thousand separators. - * This method calls the PHP number_format() function to do the formatting. - * @param mixed $value the value to be formatted - * @param integer $decimals the number of digits after the decimal point - * @return string the formatted result - * @see decimalSeparator - * @see thousandSeparator - */ - public function asNumber($value, $decimals = 0) - { - if ($value === null) { - return $this->nullDisplay; - } - $ds = isset($this->decimalSeparator) ? $this->decimalSeparator: '.'; - $ts = isset($this->thousandSeparator) ? $this->thousandSeparator: ','; - return number_format($value, $decimals, $ds, $ts); - } + /** + * Formats the value as a number with decimal and thousand separators. + * This method calls the PHP number_format() function to do the formatting. + * @param mixed $value the value to be formatted + * @param integer $decimals the number of digits after the decimal point + * @return string the formatted result + * @see decimalSeparator + * @see thousandSeparator + */ + public function asNumber($value, $decimals = 0) + { + if ($value === null) { + return $this->nullDisplay; + } + $ds = isset($this->decimalSeparator) ? $this->decimalSeparator: '.'; + $ts = isset($this->thousandSeparator) ? $this->thousandSeparator: ','; + return number_format($value, $decimals, $ds, $ts); + } - /** - * Formats the value in bytes as a size in human readable form. - * @param integer $value value in bytes to be formatted - * @param boolean $verbose if full names should be used (e.g. bytes, kilobytes, ...). - * Defaults to false meaning that short names will be used (e.g. B, KB, ...). - * @return string the formatted result - * @see sizeFormat - */ - public function asSize($value, $verbose = false) - { - $position = 0; + /** + * Formats the value in bytes as a size in human readable form. + * @param integer $value value in bytes to be formatted + * @param boolean $verbose if full names should be used (e.g. bytes, kilobytes, ...). + * Defaults to false meaning that short names will be used (e.g. B, KB, ...). + * @return string the formatted result + * @see sizeFormat + */ + public function asSize($value, $verbose = false) + { + $position = 0; - do { - if ($value < $this->sizeFormat['base']) { - break; - } + do { + if ($value < $this->sizeFormat['base']) { + break; + } - $value = $value / $this->sizeFormat['base']; - $position++; - } while ($position < 6); + $value = $value / $this->sizeFormat['base']; + $position++; + } while ($position < 6); - $value = round($value, $this->sizeFormat['decimals']); - $formattedValue = isset($this->sizeFormat['decimalSeparator']) ? str_replace('.', $this->sizeFormat['decimalSeparator'], $value) : $value; - $params = ['n' => $formattedValue]; - - switch($position) { - case 0: - return $verbose ? Yii::t('yii', '{n, plural, =1{# byte} other{# bytes}}', $params) : Yii::t('yii', '{n} B', $params); - case 1: - return $verbose ? Yii::t('yii', '{n, plural, =1{# kilobyte} other{# kilobytes}}', $params) : Yii::t('yii', '{n} KB', $params); - case 2: - return $verbose ? Yii::t('yii', '{n, plural, =1{# megabyte} other{# megabytes}}', $params) : Yii::t('yii', '{n} MB', $params); - case 3: - return $verbose ? Yii::t('yii', '{n, plural, =1{# gigabyte} other{# gigabytes}}', $params) : Yii::t('yii', '{n} GB', $params); - case 4: - return $verbose ? Yii::t('yii', '{n, plural, =1{# terabyte} other{# terabytes}}', $params) : Yii::t('yii', '{n} TB', $params); - default: - return $verbose ? Yii::t('yii', '{n, plural, =1{# petabyte} other{# petabytes}}', $params) : Yii::t('yii', '{n} PB', $params); - } - } + $value = round($value, $this->sizeFormat['decimals']); + $formattedValue = isset($this->sizeFormat['decimalSeparator']) ? str_replace('.', $this->sizeFormat['decimalSeparator'], $value) : $value; + $params = ['n' => $formattedValue]; + + switch($position) { + case 0: + return $verbose ? Yii::t('yii', '{n, plural, =1{# byte} other{# bytes}}', $params) : Yii::t('yii', '{n} B', $params); + case 1: + return $verbose ? Yii::t('yii', '{n, plural, =1{# kilobyte} other{# kilobytes}}', $params) : Yii::t('yii', '{n} KB', $params); + case 2: + return $verbose ? Yii::t('yii', '{n, plural, =1{# megabyte} other{# megabytes}}', $params) : Yii::t('yii', '{n} MB', $params); + case 3: + return $verbose ? Yii::t('yii', '{n, plural, =1{# gigabyte} other{# gigabytes}}', $params) : Yii::t('yii', '{n} GB', $params); + case 4: + return $verbose ? Yii::t('yii', '{n, plural, =1{# terabyte} other{# terabytes}}', $params) : Yii::t('yii', '{n} TB', $params); + default: + return $verbose ? Yii::t('yii', '{n, plural, =1{# petabyte} other{# petabytes}}', $params) : Yii::t('yii', '{n} PB', $params); + } + } - /** - * Formats the value as the time interval between a date and now in human readable form. - * @param integer|string|DateTime|DateInterval $value the value to be formatted. The following - * types of value are supported: - * - * - an integer representing a UNIX timestamp - * - a string that can be parsed into a UNIX timestamp via `strtotime()` or that can be passed to a DateInterval constructor. - * - a PHP DateTime object - * - a PHP DateInterval object - * - * @return string the formatted result - */ - public function asRelativeTime($value, $referenceTime=null) - { - if ($value === null) { - return $this->nullDisplay; - } + /** + * Formats the value as the time interval between a date and now in human readable form. + * @param integer|string|DateTime|DateInterval $value the value to be formatted. The following + * types of value are supported: + * + * - an integer representing a UNIX timestamp + * - a string that can be parsed into a UNIX timestamp via `strtotime()` or that can be passed to a DateInterval constructor. + * - a PHP DateTime object + * - a PHP DateInterval object + * + * @return string the formatted result + */ + public function asRelativeTime($value, $referenceTime = null) + { + if ($value === null) { + return $this->nullDisplay; + } - if ($value instanceof \DateInterval) { - $interval = $value; - } else { - $timestamp = $this->normalizeDatetimeValue($value); + if ($value instanceof \DateInterval) { + $interval = $value; + } else { + $timestamp = $this->normalizeDatetimeValue($value); - if ($timestamp === false) { - // $value is not a valid date/time value, so we try - // to create a DateInterval with it - try { - $interval = new \DateInterval($value); - } catch (Exception $e) { - // invalid date/time and invalid interval - return $this->nullDisplay; - } - } else { - $timezone = new \DateTimeZone($this->timeZone); - - if ($referenceTime === null) { - $dateNow = new DateTime('now', $timezone); - } else { - $referenceTime = $this->normalizeDatetimeValue($referenceTime); - $dateNow = new DateTime(null, $timezone); - $dateNow->setTimestamp($referenceTime); - } + if ($timestamp === false) { + // $value is not a valid date/time value, so we try + // to create a DateInterval with it + try { + $interval = new \DateInterval($value); + } catch (Exception $e) { + // invalid date/time and invalid interval + return $this->nullDisplay; + } + } else { + $timezone = new \DateTimeZone($this->timeZone); + + if ($referenceTime === null) { + $dateNow = new DateTime('now', $timezone); + } else { + $referenceTime = $this->normalizeDatetimeValue($referenceTime); + $dateNow = new DateTime(null, $timezone); + $dateNow->setTimestamp($referenceTime); + } - $dateThen = new DateTime(null, $timezone); - $dateThen->setTimestamp($timestamp); + $dateThen = new DateTime(null, $timezone); + $dateThen->setTimestamp($timestamp); - $interval = $dateThen->diff($dateNow); - } - } + $interval = $dateThen->diff($dateNow); + } + } - if ($interval->invert) { - if ($interval->y >= 1) { - return Yii::t('yii', 'in {delta, plural, =1{a year} other{# years}}', ['delta' => $interval->y]); - } - if ($interval->m >= 1) { - return Yii::t('yii', 'in {delta, plural, =1{a month} other{# months}}', ['delta' => $interval->m]); - } - if ($interval->d >= 1) { - return Yii::t('yii', 'in {delta, plural, =1{a day} other{# days}}', ['delta' => $interval->d]); - } - if ($interval->h >= 1) { - return Yii::t('yii', 'in {delta, plural, =1{an hour} other{# hours}}', ['delta' => $interval->h]); - } - if ($interval->i >= 1) { - return Yii::t('yii', 'in {delta, plural, =1{a minute} other{# minutes}}', ['delta' => $interval->i]); - } + if ($interval->invert) { + if ($interval->y >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{a year} other{# years}}', ['delta' => $interval->y]); + } + if ($interval->m >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{a month} other{# months}}', ['delta' => $interval->m]); + } + if ($interval->d >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{a day} other{# days}}', ['delta' => $interval->d]); + } + if ($interval->h >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{an hour} other{# hours}}', ['delta' => $interval->h]); + } + if ($interval->i >= 1) { + return Yii::t('yii', 'in {delta, plural, =1{a minute} other{# minutes}}', ['delta' => $interval->i]); + } - return Yii::t('yii', 'in {delta, plural, =1{a second} other{# seconds}}', ['delta' => $interval->s]); - } else { - if ($interval->y >= 1) { - return Yii::t('yii', '{delta, plural, =1{a year} other{# years}} ago', ['delta' => $interval->y]); - } - if ($interval->m >= 1) { - return Yii::t('yii', '{delta, plural, =1{a month} other{# months}} ago', ['delta' => $interval->m]); - } - if ($interval->d >= 1) { - return Yii::t('yii', '{delta, plural, =1{a day} other{# days}} ago', ['delta' => $interval->d]); - } - if ($interval->h >= 1) { - return Yii::t('yii', '{delta, plural, =1{an hour} other{# hours}} ago', ['delta' => $interval->h]); - } - if ($interval->i >= 1) { - return Yii::t('yii', '{delta, plural, =1{a minute} other{# minutes}} ago', ['delta' => $interval->i]); - } + return Yii::t('yii', 'in {delta, plural, =1{a second} other{# seconds}}', ['delta' => $interval->s]); + } else { + if ($interval->y >= 1) { + return Yii::t('yii', '{delta, plural, =1{a year} other{# years}} ago', ['delta' => $interval->y]); + } + if ($interval->m >= 1) { + return Yii::t('yii', '{delta, plural, =1{a month} other{# months}} ago', ['delta' => $interval->m]); + } + if ($interval->d >= 1) { + return Yii::t('yii', '{delta, plural, =1{a day} other{# days}} ago', ['delta' => $interval->d]); + } + if ($interval->h >= 1) { + return Yii::t('yii', '{delta, plural, =1{an hour} other{# hours}} ago', ['delta' => $interval->h]); + } + if ($interval->i >= 1) { + return Yii::t('yii', '{delta, plural, =1{a minute} other{# minutes}} ago', ['delta' => $interval->i]); + } - return Yii::t('yii', '{delta, plural, =1{a second} other{# seconds}} ago', ['delta' => $interval->s]); - } - } + return Yii::t('yii', '{delta, plural, =1{a second} other{# seconds}} ago', ['delta' => $interval->s]); + } + } } diff --git a/tests/unit/framework/base/FormatterTest.php b/tests/unit/framework/base/FormatterTest.php index 97a87be694..83c510fe99 100644 --- a/tests/unit/framework/base/FormatterTest.php +++ b/tests/unit/framework/base/FormatterTest.php @@ -16,339 +16,339 @@ use DateInterval; */ class FormatterTest extends TestCase { - /** - * @var Formatter - */ - protected $formatter; + /** + * @var Formatter + */ + protected $formatter; - protected function setUp() - { - parent::setUp(); - $this->mockApplication(); - $this->formatter = new Formatter(); - } + protected function setUp() + { + parent::setUp(); + $this->mockApplication(); + $this->formatter = new Formatter(); + } - protected function tearDown() - { - parent::tearDown(); - $this->formatter = null; - } + protected function tearDown() + { + parent::tearDown(); + $this->formatter = null; + } - public function testAsRaw() - { - $value = '123'; - $this->assertSame($value, $this->formatter->asRaw($value)); - $value = 123; - $this->assertSame($value, $this->formatter->asRaw($value)); - $value = '<>'; - $this->assertSame($value, $this->formatter->asRaw($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asRaw(null)); - } + public function testAsRaw() + { + $value = '123'; + $this->assertSame($value, $this->formatter->asRaw($value)); + $value = 123; + $this->assertSame($value, $this->formatter->asRaw($value)); + $value = '<>'; + $this->assertSame($value, $this->formatter->asRaw($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asRaw(null)); + } - public function testAsText() - { - $value = '123'; - $this->assertSame($value, $this->formatter->asText($value)); - $value = 123; - $this->assertSame("$value", $this->formatter->asText($value)); - $value = '<>'; - $this->assertSame('<>', $this->formatter->asText($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asText(null)); - } + public function testAsText() + { + $value = '123'; + $this->assertSame($value, $this->formatter->asText($value)); + $value = 123; + $this->assertSame("$value", $this->formatter->asText($value)); + $value = '<>'; + $this->assertSame('<>', $this->formatter->asText($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asText(null)); + } - public function testAsNtext() - { - $value = '123'; - $this->assertSame($value, $this->formatter->asNtext($value)); - $value = 123; - $this->assertSame("$value", $this->formatter->asNtext($value)); - $value = '<>'; - $this->assertSame('<>', $this->formatter->asNtext($value)); - $value = "123\n456"; - $this->assertSame("123
\n456", $this->formatter->asNtext($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asNtext(null)); - } + public function testAsNtext() + { + $value = '123'; + $this->assertSame($value, $this->formatter->asNtext($value)); + $value = 123; + $this->assertSame("$value", $this->formatter->asNtext($value)); + $value = '<>'; + $this->assertSame('<>', $this->formatter->asNtext($value)); + $value = "123\n456"; + $this->assertSame("123
\n456", $this->formatter->asNtext($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asNtext(null)); + } - public function testAsParagraphs() - { - $value = '123'; - $this->assertSame("

$value

", $this->formatter->asParagraphs($value)); - $value = 123; - $this->assertSame("

$value

", $this->formatter->asParagraphs($value)); - $value = '<>'; - $this->assertSame('

<>

', $this->formatter->asParagraphs($value)); - $value = "123\n456"; - $this->assertSame("

123\n456

", $this->formatter->asParagraphs($value)); - $value = "123\n\n456"; - $this->assertSame("

123

\n

456

", $this->formatter->asParagraphs($value)); - $value = "123\n\n\n456"; - $this->assertSame("

123

\n

456

", $this->formatter->asParagraphs($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asParagraphs(null)); - } + public function testAsParagraphs() + { + $value = '123'; + $this->assertSame("

$value

", $this->formatter->asParagraphs($value)); + $value = 123; + $this->assertSame("

$value

", $this->formatter->asParagraphs($value)); + $value = '<>'; + $this->assertSame('

<>

', $this->formatter->asParagraphs($value)); + $value = "123\n456"; + $this->assertSame("

123\n456

", $this->formatter->asParagraphs($value)); + $value = "123\n\n456"; + $this->assertSame("

123

\n

456

", $this->formatter->asParagraphs($value)); + $value = "123\n\n\n456"; + $this->assertSame("

123

\n

456

", $this->formatter->asParagraphs($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asParagraphs(null)); + } - public function testAsHtml() - { - // todo: dependency on HtmlPurifier - } + public function testAsHtml() + { + // todo: dependency on HtmlPurifier + } - public function testAsEmail() - { - $value = 'test@sample.com'; - $this->assertSame("$value", $this->formatter->asEmail($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asEmail(null)); - } + public function testAsEmail() + { + $value = 'test@sample.com'; + $this->assertSame("$value", $this->formatter->asEmail($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asEmail(null)); + } - public function testAsImage() - { - $value = 'http://sample.com/img.jpg'; - $this->assertSame("\"\"", $this->formatter->asImage($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asImage(null)); - } + public function testAsImage() + { + $value = 'http://sample.com/img.jpg'; + $this->assertSame("\"\"", $this->formatter->asImage($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asImage(null)); + } - public function testAsBoolean() - { - $value = true; - $this->assertSame('Yes', $this->formatter->asBoolean($value)); - $value = false; - $this->assertSame('No', $this->formatter->asBoolean($value)); - $value = "111"; - $this->assertSame('Yes', $this->formatter->asBoolean($value)); - $value = ""; - $this->assertSame('No', $this->formatter->asBoolean($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asBoolean(null)); - } + public function testAsBoolean() + { + $value = true; + $this->assertSame('Yes', $this->formatter->asBoolean($value)); + $value = false; + $this->assertSame('No', $this->formatter->asBoolean($value)); + $value = "111"; + $this->assertSame('Yes', $this->formatter->asBoolean($value)); + $value = ""; + $this->assertSame('No', $this->formatter->asBoolean($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asBoolean(null)); + } - public function testAsDate() - { - $value = time(); - $this->assertSame(date('Y/m/d', $value), $this->formatter->asDate($value)); - $this->assertSame(date('Y-m-d', $value), $this->formatter->asDate($value, 'Y-m-d')); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asDate(null)); - } + public function testAsDate() + { + $value = time(); + $this->assertSame(date('Y/m/d', $value), $this->formatter->asDate($value)); + $this->assertSame(date('Y-m-d', $value), $this->formatter->asDate($value, 'Y-m-d')); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asDate(null)); + } - public function testAsTime() - { - $value = time(); - $this->assertSame(date('h:i:s A', $value), $this->formatter->asTime($value)); - $this->assertSame(date('h:i:s', $value), $this->formatter->asTime($value, 'h:i:s')); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asTime(null)); - } + public function testAsTime() + { + $value = time(); + $this->assertSame(date('h:i:s A', $value), $this->formatter->asTime($value)); + $this->assertSame(date('h:i:s', $value), $this->formatter->asTime($value, 'h:i:s')); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asTime(null)); + } - public function testAsDatetime() - { - $value = time(); - $this->assertSame(date('Y/m/d h:i:s A', $value), $this->formatter->asDatetime($value)); - $this->assertSame(date('Y-m-d h:i:s', $value), $this->formatter->asDatetime($value, 'Y-m-d h:i:s')); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asDatetime(null)); - } + public function testAsDatetime() + { + $value = time(); + $this->assertSame(date('Y/m/d h:i:s A', $value), $this->formatter->asDatetime($value)); + $this->assertSame(date('Y-m-d h:i:s', $value), $this->formatter->asDatetime($value, 'Y-m-d h:i:s')); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asDatetime(null)); + } - public function testAsInteger() - { - $value = 123; - $this->assertSame("$value", $this->formatter->asInteger($value)); - $value = 123.23; - $this->assertSame("123", $this->formatter->asInteger($value)); - $value = 'a'; - $this->assertSame("0", $this->formatter->asInteger($value)); - $value = -123.23; - $this->assertSame("-123", $this->formatter->asInteger($value)); - $value = "-123abc"; - $this->assertSame("-123", $this->formatter->asInteger($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asInteger(null)); - } + public function testAsInteger() + { + $value = 123; + $this->assertSame("$value", $this->formatter->asInteger($value)); + $value = 123.23; + $this->assertSame("123", $this->formatter->asInteger($value)); + $value = 'a'; + $this->assertSame("0", $this->formatter->asInteger($value)); + $value = -123.23; + $this->assertSame("-123", $this->formatter->asInteger($value)); + $value = "-123abc"; + $this->assertSame("-123", $this->formatter->asInteger($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asInteger(null)); + } - public function testAsDouble() - { - $value = 123.12; - $this->assertSame("123.12", $this->formatter->asDouble($value)); - $this->assertSame("123.1", $this->formatter->asDouble($value, 1)); - $this->assertSame("123", $this->formatter->asDouble($value, 0)); - $value = 123; - $this->assertSame("123.00", $this->formatter->asDouble($value)); - $this->formatter->decimalSeparator = ','; - $value = 123.12; - $this->assertSame("123,12", $this->formatter->asDouble($value)); - $this->assertSame("123,1", $this->formatter->asDouble($value, 1)); - $this->assertSame("123", $this->formatter->asDouble($value, 0)); - $value = 123123.123; - $this->assertSame("123123,12", $this->formatter->asDouble($value)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asDouble(null)); - } + public function testAsDouble() + { + $value = 123.12; + $this->assertSame("123.12", $this->formatter->asDouble($value)); + $this->assertSame("123.1", $this->formatter->asDouble($value, 1)); + $this->assertSame("123", $this->formatter->asDouble($value, 0)); + $value = 123; + $this->assertSame("123.00", $this->formatter->asDouble($value)); + $this->formatter->decimalSeparator = ','; + $value = 123.12; + $this->assertSame("123,12", $this->formatter->asDouble($value)); + $this->assertSame("123,1", $this->formatter->asDouble($value, 1)); + $this->assertSame("123", $this->formatter->asDouble($value, 0)); + $value = 123123.123; + $this->assertSame("123123,12", $this->formatter->asDouble($value)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asDouble(null)); + } - public function testAsNumber() - { - $value = 123123.123; - $this->assertSame("123,123", $this->formatter->asNumber($value)); - $this->assertSame("123,123.12", $this->formatter->asNumber($value, 2)); - $this->formatter->decimalSeparator = ','; - $this->formatter->thousandSeparator = ' '; - $this->assertSame("123 123", $this->formatter->asNumber($value)); - $this->assertSame("123 123,12", $this->formatter->asNumber($value, 2)); - $this->formatter->thousandSeparator = ''; - $this->assertSame("123123", $this->formatter->asNumber($value)); - $this->assertSame("123123,12", $this->formatter->asNumber($value, 2)); - $this->assertSame($this->formatter->nullDisplay, $this->formatter->asNumber(null)); - } + public function testAsNumber() + { + $value = 123123.123; + $this->assertSame("123,123", $this->formatter->asNumber($value)); + $this->assertSame("123,123.12", $this->formatter->asNumber($value, 2)); + $this->formatter->decimalSeparator = ','; + $this->formatter->thousandSeparator = ' '; + $this->assertSame("123 123", $this->formatter->asNumber($value)); + $this->assertSame("123 123,12", $this->formatter->asNumber($value, 2)); + $this->formatter->thousandSeparator = ''; + $this->assertSame("123123", $this->formatter->asNumber($value)); + $this->assertSame("123123,12", $this->formatter->asNumber($value, 2)); + $this->assertSame($this->formatter->nullDisplay, $this->formatter->asNumber(null)); + } - public function testFormat() - { - $value = time(); - $this->assertSame(date('Y/m/d', $value), $this->formatter->format($value, 'date')); - $this->assertSame(date('Y/m/d', $value), $this->formatter->format($value, 'DATE')); - $this->assertSame(date('Y-m-d', $value), $this->formatter->format($value, ['date', 'Y-m-d'])); - $this->setExpectedException('\yii\base\InvalidParamException'); - $this->assertSame(date('Y-m-d', $value), $this->formatter->format($value, 'data')); - } + public function testFormat() + { + $value = time(); + $this->assertSame(date('Y/m/d', $value), $this->formatter->format($value, 'date')); + $this->assertSame(date('Y/m/d', $value), $this->formatter->format($value, 'DATE')); + $this->assertSame(date('Y-m-d', $value), $this->formatter->format($value, ['date', 'Y-m-d'])); + $this->setExpectedException('\yii\base\InvalidParamException'); + $this->assertSame(date('Y-m-d', $value), $this->formatter->format($value, 'data')); + } - private function buildDateSubIntervals($referenceDate, $intervals) - { - $date = new DateTime($referenceDate); - foreach ($intervals as $interval) { - $date->sub($interval); - } - return $date; - } + private function buildDateSubIntervals($referenceDate, $intervals) + { + $date = new DateTime($referenceDate); + foreach ($intervals as $interval) { + $date->sub($interval); + } + return $date; + } - public function testAsRelativeTime() - { - $interval_1_second = new DateInterval("PT1S"); - $interval_244_seconds = new DateInterval("PT244S"); - $interval_1_minute = new DateInterval("PT1M"); - $interval_33_minutes = new DateInterval("PT33M"); - $interval_1_hour = new DateInterval("PT1H"); - $interval_6_hours = new DateInterval("PT6H"); - $interval_1_day = new DateInterval("P1D"); - $interval_89_days = new DateInterval("P89D"); - $interval_1_month = new DateInterval("P1M"); - $interval_5_months = new DateInterval("P5M"); - $interval_1_year = new DateInterval("P1Y"); - $interval_12_years = new DateInterval("P12Y"); + public function testAsRelativeTime() + { + $interval_1_second = new DateInterval("PT1S"); + $interval_244_seconds = new DateInterval("PT244S"); + $interval_1_minute = new DateInterval("PT1M"); + $interval_33_minutes = new DateInterval("PT33M"); + $interval_1_hour = new DateInterval("PT1H"); + $interval_6_hours = new DateInterval("PT6H"); + $interval_1_day = new DateInterval("P1D"); + $interval_89_days = new DateInterval("P89D"); + $interval_1_month = new DateInterval("P1M"); + $interval_5_months = new DateInterval("P5M"); + $interval_1_year = new DateInterval("P1Y"); + $interval_12_years = new DateInterval("P12Y"); - // Pass a DateInterval - $this->assertSame('a second ago', $this->formatter->asRelativeTime($interval_1_second)); - $this->assertSame('244 seconds ago', $this->formatter->asRelativeTime($interval_244_seconds)); - $this->assertSame('a minute ago', $this->formatter->asRelativeTime($interval_1_minute)); - $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($interval_33_minutes)); - $this->assertSame('an hour ago', $this->formatter->asRelativeTime($interval_1_hour)); - $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($interval_6_hours)); - $this->assertSame('a day ago', $this->formatter->asRelativeTime($interval_1_day)); - $this->assertSame('89 days ago', $this->formatter->asRelativeTime($interval_89_days)); - $this->assertSame('a month ago', $this->formatter->asRelativeTime($interval_1_month)); - $this->assertSame('5 months ago', $this->formatter->asRelativeTime($interval_5_months)); - $this->assertSame('a year ago', $this->formatter->asRelativeTime($interval_1_year)); - $this->assertSame('12 years ago', $this->formatter->asRelativeTime($interval_12_years)); + // Pass a DateInterval + $this->assertSame('a second ago', $this->formatter->asRelativeTime($interval_1_second)); + $this->assertSame('244 seconds ago', $this->formatter->asRelativeTime($interval_244_seconds)); + $this->assertSame('a minute ago', $this->formatter->asRelativeTime($interval_1_minute)); + $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($interval_33_minutes)); + $this->assertSame('an hour ago', $this->formatter->asRelativeTime($interval_1_hour)); + $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($interval_6_hours)); + $this->assertSame('a day ago', $this->formatter->asRelativeTime($interval_1_day)); + $this->assertSame('89 days ago', $this->formatter->asRelativeTime($interval_89_days)); + $this->assertSame('a month ago', $this->formatter->asRelativeTime($interval_1_month)); + $this->assertSame('5 months ago', $this->formatter->asRelativeTime($interval_5_months)); + $this->assertSame('a year ago', $this->formatter->asRelativeTime($interval_1_year)); + $this->assertSame('12 years ago', $this->formatter->asRelativeTime($interval_12_years)); - // Pass a DateInterval string - $this->assertSame('a year ago', $this->formatter->asRelativeTime('2007-03-01T13:00:00Z/2008-05-11T15:30:00Z')); - $this->assertSame('a year ago', $this->formatter->asRelativeTime('2007-03-01T13:00:00Z/P1Y2M10DT2H30M')); - $this->assertSame('a year ago', $this->formatter->asRelativeTime('P1Y2M10DT2H30M/2008-05-11T15:30:00Z')); - $this->assertSame('a year ago', $this->formatter->asRelativeTime('P1Y2M10DT2H30M')); - $this->assertSame('94 months ago', $this->formatter->asRelativeTime('P94M')); + // Pass a DateInterval string + $this->assertSame('a year ago', $this->formatter->asRelativeTime('2007-03-01T13:00:00Z/2008-05-11T15:30:00Z')); + $this->assertSame('a year ago', $this->formatter->asRelativeTime('2007-03-01T13:00:00Z/P1Y2M10DT2H30M')); + $this->assertSame('a year ago', $this->formatter->asRelativeTime('P1Y2M10DT2H30M/2008-05-11T15:30:00Z')); + $this->assertSame('a year ago', $this->formatter->asRelativeTime('P1Y2M10DT2H30M')); + $this->assertSame('94 months ago', $this->formatter->asRelativeTime('P94M')); - // Force the reference time and pass a past DateTime - $dateNow = new DateTime('2014-03-13'); - $this->assertSame('a second ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_second]), $dateNow)); - $this->assertSame('4 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_244_seconds]), $dateNow)); - $this->assertSame('a minute ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_minute]), $dateNow)); - $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_33_minutes]), $dateNow)); - $this->assertSame('an hour ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_hour]), $dateNow)); - $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_6_hours]), $dateNow)); - $this->assertSame('a day ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_day]), $dateNow)); - $this->assertSame('2 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_89_days]), $dateNow)); - $this->assertSame('a month ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_month]), $dateNow)); - $this->assertSame('5 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_5_months]), $dateNow)); - $this->assertSame('a year ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_year]), $dateNow)); - $this->assertSame('12 years ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_12_years]), $dateNow)); + // Force the reference time and pass a past DateTime + $dateNow = new DateTime('2014-03-13'); + $this->assertSame('a second ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_second]), $dateNow)); + $this->assertSame('4 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_244_seconds]), $dateNow)); + $this->assertSame('a minute ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_minute]), $dateNow)); + $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_33_minutes]), $dateNow)); + $this->assertSame('an hour ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_hour]), $dateNow)); + $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_6_hours]), $dateNow)); + $this->assertSame('a day ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_day]), $dateNow)); + $this->assertSame('2 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_89_days]), $dateNow)); + $this->assertSame('a month ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_month]), $dateNow)); + $this->assertSame('5 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_5_months]), $dateNow)); + $this->assertSame('a year ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_year]), $dateNow)); + $this->assertSame('12 years ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_12_years]), $dateNow)); - // Tricky 31-days month stuff - // See: http://www.gnu.org/software/tar/manual/html_section/Relative-items-in-date-strings.html - $dateNow = new DateTime('2014-03-31'); - $dateThen = new DateTime('2014-03-03'); - $this->assertSame('28 days ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-31', [$interval_1_month]), $dateNow)); - $this->assertSame('28 days ago', $this->formatter->asRelativeTime($dateThen, $dateNow)); - $dateThen = new DateTime('2014-02-28'); - $this->assertSame('a month ago', $this->formatter->asRelativeTime($dateThen, $dateNow)); + // Tricky 31-days month stuff + // See: http://www.gnu.org/software/tar/manual/html_section/Relative-items-in-date-strings.html + $dateNow = new DateTime('2014-03-31'); + $dateThen = new DateTime('2014-03-03'); + $this->assertSame('28 days ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-31', [$interval_1_month]), $dateNow)); + $this->assertSame('28 days ago', $this->formatter->asRelativeTime($dateThen, $dateNow)); + $dateThen = new DateTime('2014-02-28'); + $this->assertSame('a month ago', $this->formatter->asRelativeTime($dateThen, $dateNow)); - // Relative to current time tests (can't test with seconds though) - $this->assertSame('4 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_244_seconds]))); - $this->assertSame('a minute ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_minute]))); - $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_33_minutes]))); - $this->assertSame('an hour ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_hour]))); - $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_6_hours]))); - $this->assertSame('a day ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_day]))); - $this->assertSame('2 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_89_days]))); - $this->assertSame('a month ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_month]))); - $this->assertSame('5 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_5_months]))); - $this->assertSame('a year ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_year]))); - $this->assertSame('12 years ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_12_years]))); + // Relative to current time tests (can't test with seconds though due to the tests computation time) + $this->assertSame('4 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_244_seconds]))); + $this->assertSame('a minute ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_minute]))); + $this->assertSame('33 minutes ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_33_minutes]))); + $this->assertSame('an hour ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_hour]))); + $this->assertSame('6 hours ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_6_hours]))); + $this->assertSame('a day ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_day]))); + $this->assertSame('2 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_89_days]))); + $this->assertSame('a month ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_month]))); + $this->assertSame('5 months ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_5_months]))); + $this->assertSame('a year ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_year]))); + $this->assertSame('12 years ago', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_12_years]))); - // Invert all the DateIntervals - $interval_1_second->invert = true; - $interval_244_seconds->invert = true; - $interval_1_minute->invert = true; - $interval_33_minutes->invert = true; - $interval_1_hour->invert = true; - $interval_6_hours->invert = true; - $interval_1_day->invert = true; - $interval_89_days->invert = true; - $interval_1_month->invert = true; - $interval_5_months->invert = true; - $interval_1_year->invert = true; - $interval_12_years->invert = true; + // Invert all the DateIntervals + $interval_1_second->invert = true; + $interval_244_seconds->invert = true; + $interval_1_minute->invert = true; + $interval_33_minutes->invert = true; + $interval_1_hour->invert = true; + $interval_6_hours->invert = true; + $interval_1_day->invert = true; + $interval_89_days->invert = true; + $interval_1_month->invert = true; + $interval_5_months->invert = true; + $interval_1_year->invert = true; + $interval_12_years->invert = true; - // Pass a inverted DateInterval - $this->assertSame('in a second', $this->formatter->asRelativeTime($interval_1_second)); - $this->assertSame('in 244 seconds', $this->formatter->asRelativeTime($interval_244_seconds)); - $this->assertSame('in a minute', $this->formatter->asRelativeTime($interval_1_minute)); - $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($interval_33_minutes)); - $this->assertSame('in an hour', $this->formatter->asRelativeTime($interval_1_hour)); - $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($interval_6_hours)); - $this->assertSame('in a day', $this->formatter->asRelativeTime($interval_1_day)); - $this->assertSame('in 89 days', $this->formatter->asRelativeTime($interval_89_days)); - $this->assertSame('in a month', $this->formatter->asRelativeTime($interval_1_month)); - $this->assertSame('in 5 months', $this->formatter->asRelativeTime($interval_5_months)); - $this->assertSame('in a year', $this->formatter->asRelativeTime($interval_1_year)); - $this->assertSame('in 12 years', $this->formatter->asRelativeTime($interval_12_years)); + // Pass a inverted DateInterval + $this->assertSame('in a second', $this->formatter->asRelativeTime($interval_1_second)); + $this->assertSame('in 244 seconds', $this->formatter->asRelativeTime($interval_244_seconds)); + $this->assertSame('in a minute', $this->formatter->asRelativeTime($interval_1_minute)); + $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($interval_33_minutes)); + $this->assertSame('in an hour', $this->formatter->asRelativeTime($interval_1_hour)); + $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($interval_6_hours)); + $this->assertSame('in a day', $this->formatter->asRelativeTime($interval_1_day)); + $this->assertSame('in 89 days', $this->formatter->asRelativeTime($interval_89_days)); + $this->assertSame('in a month', $this->formatter->asRelativeTime($interval_1_month)); + $this->assertSame('in 5 months', $this->formatter->asRelativeTime($interval_5_months)); + $this->assertSame('in a year', $this->formatter->asRelativeTime($interval_1_year)); + $this->assertSame('in 12 years', $this->formatter->asRelativeTime($interval_12_years)); - // Pass a inverted DateInterval string - $this->assertSame('in a year', $this->formatter->asRelativeTime('2008-05-11T15:30:00Z/2007-03-01T13:00:00Z')); + // Pass a inverted DateInterval string + $this->assertSame('in a year', $this->formatter->asRelativeTime('2008-05-11T15:30:00Z/2007-03-01T13:00:00Z')); - // Force the reference time and pass a future DateTime - $dateNow = new DateTime('2014-03-13'); - $this->assertSame('in a second', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_second]), $dateNow)); - $this->assertSame('in 4 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_244_seconds]), $dateNow)); - $this->assertSame('in a minute', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_minute]), $dateNow)); - $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_33_minutes]), $dateNow)); - $this->assertSame('in an hour', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_hour]), $dateNow)); - $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_6_hours]), $dateNow)); - $this->assertSame('in a day', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_day]), $dateNow)); - $this->assertSame('in 2 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_89_days]), $dateNow)); - $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_month]), $dateNow)); - $this->assertSame('in 5 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_5_months]), $dateNow)); - $this->assertSame('in a year', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_year]), $dateNow)); - $this->assertSame('in 12 years', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_12_years]), $dateNow)); + // Force the reference time and pass a future DateTime + $dateNow = new DateTime('2014-03-13'); + $this->assertSame('in a second', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_second]), $dateNow)); + $this->assertSame('in 4 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_244_seconds]), $dateNow)); + $this->assertSame('in a minute', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_minute]), $dateNow)); + $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_33_minutes]), $dateNow)); + $this->assertSame('in an hour', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_hour]), $dateNow)); + $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_6_hours]), $dateNow)); + $this->assertSame('in a day', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_day]), $dateNow)); + $this->assertSame('in 2 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_89_days]), $dateNow)); + $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_month]), $dateNow)); + $this->assertSame('in 5 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_5_months]), $dateNow)); + $this->assertSame('in a year', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_1_year]), $dateNow)); + $this->assertSame('in 12 years', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-13', [$interval_12_years]), $dateNow)); - // Tricky 31-days month stuff - // See: http://www.gnu.org/software/tar/manual/html_section/Relative-items-in-date-strings.html - $dateNow = new DateTime('2014-03-03'); - $dateThen = new DateTime('2014-03-31'); - $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-03', [$interval_1_month]), $dateNow)); - $this->assertSame('in 28 days', $this->formatter->asRelativeTime($dateThen, $dateNow)); + // Tricky 31-days month stuff + // See: http://www.gnu.org/software/tar/manual/html_section/Relative-items-in-date-strings.html + $dateNow = new DateTime('2014-03-03'); + $dateThen = new DateTime('2014-03-31'); + $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('2014-03-03', [$interval_1_month]), $dateNow)); + $this->assertSame('in 28 days', $this->formatter->asRelativeTime($dateThen, $dateNow)); - // Relative to current time tests (can't test with seconds though) - // We add 5 seconds to compensate for tests computation time - $interval_5_seconds = new DateInterval('PT5S'); - $interval_5_seconds->invert = true; - $this->assertSame('in 4 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_244_seconds, $interval_5_seconds]))); - $this->assertSame('in a minute', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_minute, $interval_5_seconds]))); - $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_33_minutes, $interval_5_seconds]))); - $this->assertSame('in an hour', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_hour, $interval_5_seconds]))); - $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_6_hours, $interval_5_seconds]))); - $this->assertSame('in a day', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_day, $interval_5_seconds]))); - $this->assertSame('in 2 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_89_days, $interval_5_seconds]))); - $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_month, $interval_5_seconds]))); - $this->assertSame('in 5 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_5_months, $interval_5_seconds]))); - $this->assertSame('in a year', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_year, $interval_5_seconds]))); - $this->assertSame('in 12 years', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_12_years, $interval_5_seconds]))); - } + // Relative to current time tests (can't test with seconds though due to the tests computation time) + // We add 5 seconds to compensate for tests computation time + $interval_5_seconds = new DateInterval('PT5S'); + $interval_5_seconds->invert = true; + $this->assertSame('in 4 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_244_seconds, $interval_5_seconds]))); + $this->assertSame('in a minute', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_minute, $interval_5_seconds]))); + $this->assertSame('in 33 minutes', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_33_minutes, $interval_5_seconds]))); + $this->assertSame('in an hour', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_hour, $interval_5_seconds]))); + $this->assertSame('in 6 hours', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_6_hours, $interval_5_seconds]))); + $this->assertSame('in a day', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_day, $interval_5_seconds]))); + $this->assertSame('in 2 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_89_days, $interval_5_seconds]))); + $this->assertSame('in a month', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_month, $interval_5_seconds]))); + $this->assertSame('in 5 months', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_5_months, $interval_5_seconds]))); + $this->assertSame('in a year', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_1_year, $interval_5_seconds]))); + $this->assertSame('in 12 years', $this->formatter->asRelativeTime($this->buildDateSubIntervals('now', [$interval_12_years, $interval_5_seconds]))); + } } From ed70735b22e9667c1478655a44dc0cb1e3b68237 Mon Sep 17 00:00:00 2001 From: David Renty Date: Wed, 19 Mar 2014 10:48:20 +0100 Subject: [PATCH 11/11] Changelog and doc --- framework/CHANGELOG.md | 1 + framework/base/Formatter.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 7cb5f7c1cf..5c13470f40 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -145,6 +145,7 @@ Yii Framework 2 Change Log - Enh #2646: Added support for specifying hostinfo in the pattern of a URL rule (qiangxue) - Enh #2661: Added boolean column type support for SQLite (qiangxue) - Enh #2670: Changed `console\Controller::globalOptions()` to `options($actionId)` to (make it possible to) differentiate options per action (hqx) +- Enh #2714: Added support for formatting time intervals relative to the current time with `yii\base\Formatter` (drenty) - Enh #2729: Added `FilterValidator::skipOnArray` so that filters like `trim` will not fail for array inputs (qiangxue) - Enh #2735: Added support for `DateTimeInterface` in `Formatter` (ivokund) - Enh #2756: Added support for injecting custom `isEmpty` check for all validators (qiangxue) diff --git a/framework/base/Formatter.php b/framework/base/Formatter.php index a10e0b1840..1cc22f4406 100644 --- a/framework/base/Formatter.php +++ b/framework/base/Formatter.php @@ -479,7 +479,7 @@ class Formatter extends Component * - an integer representing a UNIX timestamp * - a string that can be parsed into a UNIX timestamp via `strtotime()` or that can be passed to a DateInterval constructor. * - a PHP DateTime object - * - a PHP DateInterval object + * - a PHP DateInterval object (a positive time interval will refer to the past, a negative one to the future) * * @return string the formatted result */