From e96ac0ba7a0d6eeadf7b5cd633e819e31d3663bf Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 26 May 2016 16:41:20 +0900 Subject: [PATCH] Add function to get relative timestamp up to many years, with unit tests --- common/framework/datetime.php | 71 +++++++++++++++++++++++++++ common/lang/en.php | 9 ++++ common/lang/ko.php | 9 ++++ common/legacy.php | 28 +++-------- tests/unit/framework/DateTimeTest.php | 29 ++++++++++- 5 files changed, 123 insertions(+), 23 deletions(-) diff --git a/common/framework/datetime.php b/common/framework/datetime.php index 5e76428cd..e5deac5c2 100644 --- a/common/framework/datetime.php +++ b/common/framework/datetime.php @@ -21,6 +21,11 @@ class DateTime */ public static function formatTimestamp($format, $timestamp = null) { + if ($format === 'relative') + { + return self::getRelativeTimestamp($timestamp ?: time()); + } + $offset = Config::get('locale.internal_timezone') ?: date('Z', $timestamp); return gmdate($format, ($timestamp ?: time()) + $offset); } @@ -34,6 +39,11 @@ class DateTime */ public static function formatTimestampForCurrentUser($format, $timestamp = null) { + if ($format === 'relative') + { + return self::getRelativeTimestamp($timestamp ?: time()); + } + $timezone = self::getTimezoneForCurrentUser(); if (!isset(self::$_timezones[$timezone])) { @@ -164,4 +174,65 @@ class DateTime default: return 'Etc/GMT' . ($offset > 0 ? '-' : '+') . intval(abs($offset / 3600)); } } + + /** + * Get a relative timestamp (3 hours ago, etc.) + * + * @param int $timestamp + * @return string + */ + public static function getRelativeTimestamp($timestamp) + { + $diff = \RX_TIME - $timestamp; + $langs = lang('common.time_gap'); + + if ($diff < 3) + { + return $langs['now']; + } + if ($diff < 60) + { + return sprintf($langs['secs'], $diff); + } + if ($diff < 60 * 2) + { + return sprintf($langs['min'], 1); + } + if ($diff < 3600) + { + return sprintf($langs['mins'], $diff / 60); + } + if ($diff < 3600 * 2) + { + return sprintf($langs['hour'], 1); + } + if ($diff < 86400) + { + return sprintf($langs['hours'], $diff / 3600); + } + if ($diff < 86400 * 2) + { + return sprintf($langs['day'], 1); + } + if ($diff < 86400 * 32) + { + return sprintf($langs['days'], $diff / 86400); + } + if ($diff < 86400 * 60) + { + return sprintf($langs['month'], 1); + } + if ($diff < 86400 * 366) + { + return sprintf($langs['months'], $diff / (86400 * 30.5)); + } + if ($diff < 86400 * 732) + { + return sprintf($langs['year'], 1); + } + else + { + return sprintf($langs['years'], $diff / (86400 * 365.25)); + } + } } diff --git a/common/lang/en.php b/common/lang/en.php index 99322d564..2de49032b 100644 --- a/common/lang/en.php +++ b/common/lang/en.php @@ -198,10 +198,19 @@ $lang->unit_meridiem['am'] = 'am'; $lang->unit_meridiem['pm'] = 'pm'; $lang->unit_meridiem['AM'] = 'AM'; $lang->unit_meridiem['PM'] = 'PM'; +$lang->time_gap['now'] = 'just now'; +$lang->time_gap['sec'] = '%d second ago'; +$lang->time_gap['secs'] = '%d seconds ago'; $lang->time_gap['min'] = '%d minute ago'; $lang->time_gap['mins'] = '%d minutes ago'; $lang->time_gap['hour'] = '%d hour ago'; $lang->time_gap['hours'] = '%d hours ago'; +$lang->time_gap['day'] = '%d day ago'; +$lang->time_gap['days'] = '%d days ago'; +$lang->time_gap['month'] = '%d month ago'; +$lang->time_gap['months'] = '%d months ago'; +$lang->time_gap['year'] = '%d year ago'; +$lang->time_gap['years'] = '%d years ago'; $lang->about_tag = 'You may submit multiple tags by inserting commas(,) between tags.'; $lang->about_layout = 'Layouts decorate the appearance of your content. You can configure them from the Layout menu on the top.'; $lang->about_ipaddress_input = 'IP address input format
You can use wildcard(*) (ex: 192.168.0.*)
You can use hyphen(*) for ip range (you can\'t use wild card with hyphen, ex: 192.168.0.1-192.168.0.254)
'; diff --git a/common/lang/ko.php b/common/lang/ko.php index 843924420..b601277d2 100644 --- a/common/lang/ko.php +++ b/common/lang/ko.php @@ -198,10 +198,19 @@ $lang->unit_meridiem['am'] = '오전'; $lang->unit_meridiem['pm'] = '오후'; $lang->unit_meridiem['AM'] = '오전'; $lang->unit_meridiem['PM'] = '오후'; +$lang->time_gap['now'] = '방금'; +$lang->time_gap['sec'] = '%d초 전'; +$lang->time_gap['secs'] = '%d초 전'; $lang->time_gap['min'] = '%d분 전'; $lang->time_gap['mins'] = '%d분 전'; $lang->time_gap['hour'] = '%d시간 전'; $lang->time_gap['hours'] = '%d시간 전'; +$lang->time_gap['day'] = '%d일 전'; +$lang->time_gap['days'] = '%d일 전'; +$lang->time_gap['month'] = '%d개월 전'; +$lang->time_gap['months'] = '%d개월 전'; +$lang->time_gap['year'] = '%d년 전'; +$lang->time_gap['years'] = '%d년 전'; $lang->about_tag = '쉼표(,)를 이용하여 복수 등록'; $lang->about_layout = '레이아웃은 콘텐츠의 겉모습을 꾸며줍니다. 상단 레이아웃 메뉴에서 관리할 수 있습니다.'; $lang->about_ipaddress_input = 'IP주소 입력형식
1. 와일드카드(*) 사용가능(예: 192.168.0.*)
2. 하이픈(-)을 사용하여 대역으로 입력가능
(단, 대역폭으로 입력할 경우 와일드카드 사용불가. 예: 192.168.0.1-192.168.0.254)
3.여러개의 항목은 줄을 바꾸어 입력하세요'; diff --git a/common/legacy.php b/common/legacy.php index eec558fd9..9db3dc473 100644 --- a/common/legacy.php +++ b/common/legacy.php @@ -553,7 +553,7 @@ function zdate($str, $format = 'Y-m-d H:i:s', $conversion = false) } // convert the date format according to the language - if($conversion) + if($conversion && $format !== 'relative') { static $convtable = array( 'en' => array( @@ -638,31 +638,17 @@ function getDisplayDateTime($timestamp = null, $format = 'YmdHis') */ function getTimeGap($date, $format = 'Y.m.d') { - $gap = RX_TIME - ztime($date); - - $lang_time_gap = lang('time_gap'); - if($gap < 60 * 1.5) + $timestamp = ztime($date); + $gap = RX_TIME - $timestamp; + + if ($gap < 60 * 60 * 24) { - $buff = sprintf($lang_time_gap['min'], round($gap / 60)); - } - elseif($gap < 60 * 60) - { - $buff = sprintf($lang_time_gap['mins'], round($gap / 60)); - } - elseif($gap < 60 * 60 * 1.5) - { - $buff = sprintf($lang_time_gap['hour'], round($gap / 60 / 60)); - } - elseif($gap < 60 * 60 * 24) - { - $buff = sprintf($lang_time_gap['hours'], round($gap / 60 / 60)); + return Rhymix\Framework\DateTime::getRelativeTimestamp(($gap >= 60) ? $timestamp : (RX_TIME - 60)); } else { - $buff = zdate($date, $format); + return zdate($date, $format); } - - return $buff; } /** diff --git a/tests/unit/framework/DateTimeTest.php b/tests/unit/framework/DateTimeTest.php index d5adc1105..ac0bb6dbc 100644 --- a/tests/unit/framework/DateTimeTest.php +++ b/tests/unit/framework/DateTimeTest.php @@ -95,13 +95,15 @@ class DateTimeTest extends \Codeception\TestCase\Test // Test getTimeGap() when the internal time zone is different from the default time zone. Rhymix\Framework\Config::set('locale.internal_timezone', 10800); + $this->assertEquals('1 minute ago', getTimeGap(getInternalDateTime(RX_TIME - 30))); $this->assertEquals('30 minutes ago', getTimeGap(getInternalDateTime(RX_TIME - 1800))); - $this->assertEquals('2 hours ago', getTimeGap(getInternalDateTime(RX_TIME - 6000))); + $this->assertEquals('2 hours ago', getTimeGap(getInternalDateTime(RX_TIME - 8000))); // Test getTimeGap() when the internal time zone is the same as the default time zone. Rhymix\Framework\Config::set('locale.internal_timezone', 32400); $this->assertEquals('30 minutes ago', getTimeGap(getInternalDateTime(RX_TIME - 1800))); - $this->assertEquals('2 hours ago', getTimeGap(getInternalDateTime(RX_TIME - 6000))); + $this->assertEquals('2 hours ago', getTimeGap(getInternalDateTime(RX_TIME - 8000))); + $this->assertEquals(getInternalDateTime(RX_TIME - 240000, 'Y.m.d'), getTimeGap(getInternalDateTime(RX_TIME - 240000))); } public function testGetTimezoneForCurrentUser() @@ -180,4 +182,27 @@ class DateTimeTest extends \Codeception\TestCase\Test $this->assertEquals('Asia/Kolkata', Rhymix\Framework\DateTime::getTimezoneNameByOffset(19800)); $this->assertEquals('Australia/Eucla', Rhymix\Framework\DateTime::getTimezoneNameByOffset(31500)); } + + public function testGetRelativeTimestamp() + { + $GLOBALS['lang'] = Rhymix\Framework\Lang::getInstance('ko'); + $GLOBALS['lang']->loadPlugin('common'); + + $this->assertEquals('방금', Rhymix\Framework\DateTime::getRelativeTimestamp(RX_TIME)); + $this->assertEquals('20초 전', Rhymix\Framework\DateTime::getRelativeTimestamp(RX_TIME - 20)); + $this->assertEquals('1분 전', Rhymix\Framework\DateTime::getRelativeTimestamp(RX_TIME - 60)); + $this->assertEquals('30분 전', Rhymix\Framework\DateTime::getRelativeTimestamp(RX_TIME - 1800)); + $this->assertEquals('10일 전', Rhymix\Framework\DateTime::getRelativeTimestamp(RX_TIME - 86400 * 10)); + $this->assertEquals('6개월 전', Rhymix\Framework\DateTime::getRelativeTimestamp(RX_TIME - 86400 * 190)); + + $GLOBALS['lang'] = Rhymix\Framework\Lang::getInstance('en'); + $GLOBALS['lang']->loadPlugin('common'); + + $this->assertEquals('just now', getInternalDateTime(RX_TIME + 3600, 'relative')); + $this->assertEquals('5 days ago', getDisplayDateTime(RX_TIME - 86400 * 5.4, 'relative')); + $this->assertEquals('3 months ago', zdate(date('YmdHis', RX_TIME - 86400 * 100), 'relative')); + $this->assertEquals('1 year ago', Rhymix\Framework\DateTime::formatTimestamp('relative', RX_TIME - 86400 * 420)); + $this->assertEquals('2000 years ago', Rhymix\Framework\DateTime::formatTimestampForCurrentUser('relative', RX_TIME - 86400 * 365.25 * 2000)); + $this->assertEquals('just now', Rhymix\Framework\DateTime::formatTimestampForCurrentUser('relative', RX_TIME + pow(2, 31))); + } }