Add function to get relative timestamp up to many years, with unit tests

This commit is contained in:
Kijin Sung 2016-05-26 16:41:20 +09:00
parent 3c72258521
commit e96ac0ba7a
5 changed files with 123 additions and 23 deletions

View file

@ -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));
}
}
}

View file

@ -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<br />You can use wildcard(*) (ex: 192.168.0.*)<br />You can use hyphen(*) for ip range (you can\'t use wild card with hyphen, ex: 192.168.0.1-192.168.0.254)<br />';

View file

@ -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주소 입력형식<br />1. 와일드카드(*) 사용가능(예: 192.168.0.*)<br />2. 하이픈(-)을 사용하여 대역으로 입력가능<br />(단, 대역폭으로 입력할 경우 와일드카드 사용불가. 예: 192.168.0.1-192.168.0.254)<br />3.여러개의 항목은 줄을 바꾸어 입력하세요';

View file

@ -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;
}
/**

View file

@ -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)));
}
}