NEW Date->Ago() with "less than a minute" support

This commit is contained in:
Ingo Schommer 2012-12-13 19:01:27 +01:00
parent c0a122613e
commit 7e4629073a
3 changed files with 145 additions and 33 deletions

View File

@ -197,58 +197,68 @@ class Date extends DBField {
}
/**
* Returns the number of seconds/minutes/hours/days or months since the timestamp
* Returns the number of seconds/minutes/hours/days or months since the timestamp.
*
* @param boolean $includeSeconds Show seconds, or just round to "less than a minute".
* @return String
*/
public function Ago() {
public function Ago($includeSeconds = true) {
if($this->value) {
if(strtotime($this->value) == time() || time() > strtotime($this->value)) {
$time = SS_Datetime::now()->Format('U');
if(strtotime($this->value) == $time || $time > strtotime($this->value)) {
return _t(
'Date.TIMEDIFFAGO',
"{difference} ago",
'Natural language time difference, e.g. 2 hours ago',
array('difference' => $this->TimeDiff())
array('difference' => $this->TimeDiff($includeSeconds))
);
} else {
return _t(
'Date.TIMEDIFFIN',
"in {difference}",
'Natural language time difference, e.g. in 2 hours',
array('difference' => $this->TimeDiff())
array('difference' => $this->TimeDiff($includeSeconds))
);
}
}
}
public function TimeDiff() {
/**
* @param boolean $includeSeconds Show seconds, or just round to "less than a minute".
* @return String
*/
public function TimeDiff($includeSeconds = true) {
if(!$this->value) return false;
if($this->value) {
$ago = abs(time() - strtotime($this->value));
if($ago < 60) {
$span = $ago;
return ($span != 1) ? "{$span} "._t("Date.SECS", " secs") : "{$span} "._t("Date.SEC", " sec");
}
if($ago < 3600) {
$span = round($ago/60);
return ($span != 1) ? "{$span} "._t("Date.MINS", " mins") : "{$span} "._t("Date.MIN", " min");
}
if($ago < 86400) {
$span = round($ago/3600);
return ($span != 1) ? "{$span} "._t("Date.HOURS", " hours") : "{$span} "._t("Date.HOUR", " hour");
}
if($ago < 86400*30) {
$span = round($ago/86400);
return ($span != 1) ? "{$span} "._t("Date.DAYS", " days") : "{$span} "._t("Date.DAY", " day");
}
if($ago < 86400*365) {
$span = round($ago/86400/30);
return ($span != 1) ? "{$span} "._t("Date.MONTHS", " months") : "{$span} "._t("Date.MONTH", " month");
}
if($ago > 86400*365) {
$span = round($ago/86400/365);
return ($span != 1) ? "{$span} "._t("Date.YEARS", " years") : "{$span} "._t("Date.YEAR", " year");
}
$time = SS_Datetime::now()->Format('U');
$ago = abs($time - strtotime($this->value));
if($ago < 60 && $includeSeconds) {
$span = $ago;
$result = ($span != 1) ? "{$span} "._t("Date.SECS", "secs") : "{$span} "._t("Date.SEC", "sec");
} elseif($ago < 60) {
$result = _t('Date.LessThanMinuteAgo', 'less than a minute');
} elseif($ago < 3600) {
$span = round($ago/60);
$result = ($span != 1) ? "{$span} "._t("Date.MINS", "mins") : "{$span} "._t("Date.MIN", "min");
} elseif($ago < 86400) {
$span = round($ago/3600);
$result = ($span != 1) ? "{$span} "._t("Date.HOURS", "hours") : "{$span} "._t("Date.HOUR", "hour");
} elseif($ago < 86400*30) {
$span = round($ago/86400);
$result = ($span != 1) ? "{$span} "._t("Date.DAYS", "days") : "{$span} "._t("Date.DAY", "day");
} elseif($ago < 86400*365) {
$span = round($ago/86400/30);
$result = ($span != 1) ? "{$span} "._t("Date.MONTHS", "months") : "{$span} "._t("Date.MONTH", "month");
} elseif($ago > 86400*365) {
$span = round($ago/86400/365);
$result = ($span != 1) ? "{$span} "._t("Date.YEARS", "years") : "{$span} "._t("Date.YEAR", "year");
}
// Replace duplicate spaces, backwards compat with existing translations
$result = preg_replace('/\s+/', ' ', $result);
return $result;
}
/**

View File

@ -160,4 +160,46 @@ class DateTest extends SapphireTest {
$this->assertEquals('03 Apr 3000', $date->Format('d M Y'));
}
public function testAgoInPast() {
SS_Datetime::set_mock_now('2000-12-31 12:00:00');
$this->assertEquals(
'10 years ago',
DBField::create_field('Date', '1990-12-31')->Ago(),
'Exact past match on years'
);
$this->assertEquals(
'10 years ago',
DBField::create_field('Date', '1990-12-30')->Ago(),
'Approximate past match on years'
);
$this->assertEquals(
'1 year ago',
DBField::create_field('Date', '1999-12-30')->Ago(),
'Approximate past match in singular'
);
SS_Datetime::clear_mock_now();
}
public function testAgoInFuture() {
SS_Datetime::set_mock_now('2000-12-31 00:00:00');
$this->assertEquals(
'in 100 years',
DBField::create_field('Date', '2100-12-31')->Ago(),
'Exact past match on years'
);
$this->assertEquals(
'in 1 day',
DBField::create_field('Date', '2001-01-01')->Ago(),
'Approximate past match on minutes'
);
SS_Datetime::clear_mock_now();
}
}

View File

@ -89,4 +89,64 @@ class SS_DatetimeTest extends SapphireTest {
$this->assertEquals('2001-12-31%2022:10:59', $date->URLDateTime());
}
public function testAgoInPast() {
SS_Datetime::set_mock_now('2000-12-31 12:00:00');
$this->assertEquals(
'10 years ago',
DBField::create_field('SS_Datetime', '1990-12-31 12:00:00')->Ago(),
'Exact past match on years'
);
$this->assertEquals(
'10 years ago',
DBField::create_field('SS_Datetime', '1990-12-30 12:00:00')->Ago(),
'Approximate past match on years'
);
$this->assertEquals(
'1 year ago',
DBField::create_field('SS_Datetime', '1999-12-30 12:00:12')->Ago(),
'Approximate past match in singular'
);
$this->assertEquals(
'50 mins ago',
DBField::create_field('SS_Datetime', '2000-12-31 11:10:11')->Ago(),
'Approximate past match on minutes'
);
$this->assertEquals(
'59 secs ago',
DBField::create_field('SS_Datetime', '2000-12-31 11:59:01')->Ago(),
'Approximate past match on seconds'
);
$this->assertEquals(
'less than a minute ago',
DBField::create_field('SS_Datetime', '2000-12-31 11:59:01')->Ago(false),
'Approximate past match on seconds with $includeSeconds=false'
);
SS_Datetime::clear_mock_now();
}
public function testAgoInFuture() {
SS_Datetime::set_mock_now('2000-12-31 00:00:00');
$this->assertEquals(
'in 100 years',
DBField::create_field('SS_Datetime', '2100-12-31 12:00:00')->Ago(),
'Exact past match on years'
);
$this->assertEquals(
'in 1 hour',
DBField::create_field('SS_Datetime', '2000-12-31 1:01:05')->Ago(),
'Approximate past match on minutes'
);
SS_Datetime::clear_mock_now();
}
}