mirror of
https://github.com/nextcloud/server.git
synced 2026-04-15 22:11:17 -04:00
Merge pull request #12485 from owncloud/jenkins-12383
New DateTimeFormatter class for dates in other timezones and languages
This commit is contained in:
commit
fd2599cfc2
11 changed files with 660 additions and 68 deletions
269
lib/private/datetimeformatter.php
Normal file
269
lib/private/datetimeformatter.php
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Joas Schilling
|
||||
* @copyright 2014 Joas Schilling nickvergessen@owncloud.com
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OC;
|
||||
|
||||
class DateTimeFormatter implements \OCP\IDateTimeFormatter {
|
||||
/** @var \DateTimeZone */
|
||||
protected $defaultTimeZone;
|
||||
|
||||
/** @var \OCP\IL10N */
|
||||
protected $defaultL10N;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \DateTimeZone $defaultTimeZone Set the timezone for the format
|
||||
* @param \OCP\IL10N $defaultL10N Set the language for the format
|
||||
*/
|
||||
public function __construct(\DateTimeZone $defaultTimeZone, \OCP\IL10N $defaultL10N) {
|
||||
$this->defaultTimeZone = $defaultTimeZone;
|
||||
$this->defaultL10N = $defaultL10N;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TimeZone to use
|
||||
*
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @return \DateTimeZone The timezone to use, falling back to the current user's timezone
|
||||
*/
|
||||
protected function getTimeZone($timeZone = null) {
|
||||
if ($timeZone === null) {
|
||||
$timeZone = $this->defaultTimeZone;
|
||||
}
|
||||
|
||||
return $timeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get \OCP\IL10N to use
|
||||
*
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return \OCP\IL10N The locale to use, falling back to the current user's locale
|
||||
*/
|
||||
protected function getLocale($l = null) {
|
||||
if ($l === null) {
|
||||
$l = $this->defaultL10N;
|
||||
}
|
||||
|
||||
return $l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a DateTime object with the given timestamp and TimeZone
|
||||
*
|
||||
* @param mixed $timestamp
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @return \DateTime
|
||||
*/
|
||||
protected function getDateTime($timestamp, \DateTimeZone $timeZone = null) {
|
||||
if ($timestamp === null) {
|
||||
return new \DateTime('now', $timeZone);
|
||||
} else if (!$timestamp instanceof \DateTime) {
|
||||
$dateTime = new \DateTime('now', $timeZone);
|
||||
$dateTime->setTimestamp($timestamp);
|
||||
return $dateTime;
|
||||
}
|
||||
if ($timeZone) {
|
||||
$timestamp->setTimezone($timeZone);
|
||||
}
|
||||
return $timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the date of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
|
||||
* @param string $format Either 'full', 'long', 'medium' or 'short'
|
||||
* full: e.g. 'EEEE, MMMM d, y' => 'Wednesday, August 20, 2014'
|
||||
* long: e.g. 'MMMM d, y' => 'August 20, 2014'
|
||||
* medium: e.g. 'MMM d, y' => 'Aug 20, 2014'
|
||||
* short: e.g. 'M/d/yy' => '8/20/14'
|
||||
* The exact format is dependent on the language
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted date string
|
||||
*/
|
||||
public function formatDate($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
|
||||
return $this->format($timestamp, 'date', $format, $timeZone, $l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the date of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
|
||||
* @param string $format Either 'full', 'long', 'medium' or 'short'
|
||||
* full: e.g. 'EEEE, MMMM d, y' => 'Wednesday, August 20, 2014'
|
||||
* long: e.g. 'MMMM d, y' => 'August 20, 2014'
|
||||
* medium: e.g. 'MMM d, y' => 'Aug 20, 2014'
|
||||
* short: e.g. 'M/d/yy' => '8/20/14'
|
||||
* The exact format is dependent on the language
|
||||
* Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted relative date string
|
||||
*/
|
||||
public function formatDateRelativeDay($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
|
||||
if (substr($format, -1) !== '*' && substr($format, -1) !== '*') {
|
||||
$format .= '^';
|
||||
}
|
||||
|
||||
return $this->format($timestamp, 'date', $format, $timeZone, $l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the relative date of the timestamp
|
||||
* Only works for past dates
|
||||
*
|
||||
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
|
||||
* @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time
|
||||
* @return string Dates returned are:
|
||||
* < 1 month => Today, Yesterday, n days ago
|
||||
* < 13 month => last month, n months ago
|
||||
* >= 13 month => last year, n years ago
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted date span
|
||||
*/
|
||||
public function formatDateSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) {
|
||||
$l = $this->getLocale($l);
|
||||
$timestamp = $this->getDateTime($timestamp);
|
||||
$timestamp->setTime(0, 0, 0);
|
||||
if ($baseTimestamp === null) {
|
||||
$baseTimestamp = time();
|
||||
}
|
||||
$baseTimestamp = $this->getDateTime($baseTimestamp);
|
||||
$baseTimestamp->setTime(0, 0, 0);
|
||||
$dateInterval = $timestamp->diff($baseTimestamp);
|
||||
|
||||
if ($dateInterval->y == 0 && $dateInterval->m == 0 && $dateInterval->d == 0) {
|
||||
return (string) $l->t('today');
|
||||
} else if ($dateInterval->y == 0 && $dateInterval->m == 0 && $dateInterval->d == 1) {
|
||||
return (string) $l->t('yesterday');
|
||||
} else if ($dateInterval->y == 0 && $dateInterval->m == 0) {
|
||||
return (string) $l->n('%n day ago', '%n days ago', $dateInterval->d);
|
||||
} else if ($dateInterval->y == 0 && $dateInterval->m == 1) {
|
||||
return (string) $l->t('last month');
|
||||
} else if ($dateInterval->y == 0) {
|
||||
return (string) $l->n('%n month ago', '%n months ago', $dateInterval->m);
|
||||
} else if ($dateInterval->y == 1) {
|
||||
return (string) $l->t('last year');
|
||||
}
|
||||
return (string) $l->n('%n year go', '%n years ago', $dateInterval->y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the time of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
|
||||
* @param string $format Either 'full', 'long', 'medium' or 'short'
|
||||
* full: e.g. 'h:mm:ss a zzzz' => '11:42:13 AM GMT+0:00'
|
||||
* long: e.g. 'h:mm:ss a z' => '11:42:13 AM GMT'
|
||||
* medium: e.g. 'h:mm:ss a' => '11:42:13 AM'
|
||||
* short: e.g. 'h:mm a' => '11:42 AM'
|
||||
* The exact format is dependent on the language
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted time string
|
||||
*/
|
||||
public function formatTime($timestamp, $format = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
|
||||
return $this->format($timestamp, 'time', $format, $timeZone, $l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the relative past time of the timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
|
||||
* @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time
|
||||
* @return string Dates returned are:
|
||||
* < 60 sec => seconds ago
|
||||
* < 1 hour => n minutes ago
|
||||
* < 1 day => n hours ago
|
||||
* < 1 month => Yesterday, n days ago
|
||||
* < 13 month => last month, n months ago
|
||||
* >= 13 month => last year, n years ago
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted time span
|
||||
*/
|
||||
public function formatTimeSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null) {
|
||||
$l = $this->getLocale($l);
|
||||
$timestamp = $this->getDateTime($timestamp);
|
||||
if ($baseTimestamp === null) {
|
||||
$baseTimestamp = time();
|
||||
}
|
||||
$baseTimestamp = $this->getDateTime($baseTimestamp);
|
||||
|
||||
$diff = $timestamp->diff($baseTimestamp);
|
||||
if ($diff->y > 0 || $diff->m > 0 || $diff->d > 0) {
|
||||
return (string) $this->formatDateSpan($timestamp, $baseTimestamp);
|
||||
}
|
||||
|
||||
if ($diff->h > 0) {
|
||||
return (string) $l->n('%n hour ago', '%n hours ago', $diff->h);
|
||||
} else if ($diff->i > 0) {
|
||||
return (string) $l->n('%n minute ago', '%n minutes ago', $diff->i);
|
||||
}
|
||||
return (string) $l->t('seconds ago');
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the date and time of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
|
||||
* @param string $formatDate See formatDate() for description
|
||||
* @param string $formatTime See formatTime() for description
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted date and time string
|
||||
*/
|
||||
public function formatDateTime($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
|
||||
return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the date and time of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
|
||||
* @param string $formatDate See formatDate() for description
|
||||
* Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable
|
||||
* @param string $formatTime See formatTime() for description
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted relative date and time string
|
||||
*/
|
||||
public function formatDateTimeRelativeDay($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
|
||||
if (substr($formatDate, -1) !== '^' && substr($formatDate, -1) !== '*') {
|
||||
$formatDate .= '^';
|
||||
}
|
||||
|
||||
return $this->format($timestamp, 'datetime', $formatDate . '|' . $formatTime, $timeZone, $l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the date and time of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp Either a Unix timestamp or DateTime object
|
||||
* @param string $type One of 'date', 'datetime' or 'time'
|
||||
* @param string $format Format string
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted date and time string
|
||||
*/
|
||||
protected function format($timestamp, $type, $format, \DateTimeZone $timeZone = null, \OCP\IL10N $l = null) {
|
||||
$l = $this->getLocale($l);
|
||||
$timeZone = $this->getTimeZone($timeZone);
|
||||
$timestamp = $this->getDateTime($timestamp, $timeZone);
|
||||
|
||||
return (string) $l->l($type, $timestamp, array(
|
||||
'width' => $format,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -311,7 +311,13 @@ class OC_L10N implements \OCP\IL10N {
|
|||
} else {
|
||||
$value->setTimestamp($data);
|
||||
}
|
||||
$locale = self::findLanguage();
|
||||
|
||||
// Use the language of the instance, before falling back to the current user's language
|
||||
$locale = $this->lang;
|
||||
if ($locale === null) {
|
||||
$locale = self::findLanguage();
|
||||
}
|
||||
|
||||
$options = array_merge(array('width' => 'long'), $options);
|
||||
$width = $options['width'];
|
||||
switch($type) {
|
||||
|
|
|
|||
|
|
@ -275,6 +275,12 @@ class Server extends SimpleContainer implements IServerContainer {
|
|||
$groupManager = $c->getGroupManager();
|
||||
return new \OC\App\AppManager($userSession, $appConfig, $groupManager);
|
||||
});
|
||||
$this->registerService('DateTimeFormatter', function(Server $c) {
|
||||
$timeZone = $c->getTimeZone();
|
||||
$language = $c->getConfig()->getUserValue($c->getSession()->get('user_id'), 'core', 'lang', null);
|
||||
|
||||
return new \OC\DateTimeFormatter($timeZone, $c->getL10N('lib', $language));
|
||||
});
|
||||
$this->registerService('MountConfigManager', function () {
|
||||
$loader = \OC\Files\Filesystem::getLoader();
|
||||
return new \OC\Files\Config\MountProviderCollection($loader);
|
||||
|
|
@ -686,6 +692,31 @@ class Server extends SimpleContainer implements IServerContainer {
|
|||
return $this->webRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the timezone of the current user, based on his session information and config data
|
||||
*
|
||||
* @return \DateTimeZone
|
||||
*/
|
||||
public function getTimeZone() {
|
||||
$timeZone = $this->getConfig()->getUserValue($this->getSession()->get('user_id'), 'core', 'timezone', null);
|
||||
if ($timeZone === null) {
|
||||
if ($this->getSession()->exists('timezone')) {
|
||||
$offsetHours = $this->getSession()->get('timezone');
|
||||
// Note: the timeZone name is the inverse to the offset,
|
||||
// so a positive offset means negative timeZone
|
||||
// and the other way around.
|
||||
if ($offsetHours > 0) {
|
||||
return new \DateTimeZone('Etc/GMT-' . $offsetHours);
|
||||
} else {
|
||||
return new \DateTimeZone('Etc/GMT+' . abs($offsetHours));
|
||||
}
|
||||
} else {
|
||||
return new \DateTimeZone('UTC');
|
||||
}
|
||||
}
|
||||
return new \DateTimeZone($timeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \OCP\Files\Config\IMountProviderCollection
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -205,36 +205,16 @@ function strip_time($timestamp){
|
|||
* @param int $timestamp timestamp to format
|
||||
* @param int $fromTime timestamp to compare from, defaults to current time
|
||||
* @param bool $dateOnly whether to strip time information
|
||||
* @return OC_L10N_String timestamp
|
||||
* @return string timestamp
|
||||
*/
|
||||
function relative_modified_date($timestamp, $fromTime = null, $dateOnly = false) {
|
||||
$l = \OC::$server->getL10N('lib');
|
||||
if (!isset($fromTime) || $fromTime === null){
|
||||
$fromTime = time();
|
||||
}
|
||||
if ($dateOnly){
|
||||
$fromTime = strip_time($fromTime);
|
||||
$timestamp = strip_time($timestamp);
|
||||
}
|
||||
$timediff = $fromTime - $timestamp;
|
||||
$diffminutes = round($timediff/60);
|
||||
$diffhours = round($diffminutes/60);
|
||||
$diffdays = round($diffhours/24);
|
||||
$diffmonths = round($diffdays/31);
|
||||
/** @var \OC\DateTimeFormatter $formatter */
|
||||
$formatter = \OC::$server->query('DateTimeFormatter');
|
||||
|
||||
if(!$dateOnly && $timediff < 60) { return $l->t('seconds ago'); }
|
||||
else if(!$dateOnly && $timediff < 3600) { return $l->n('%n minute ago', '%n minutes ago', $diffminutes); }
|
||||
else if(!$dateOnly && $timediff < 86400) { return $l->n('%n hour ago', '%n hours ago', $diffhours); }
|
||||
else if((date('G', $fromTime)-$diffhours) >= 0) { return $l->t('today'); }
|
||||
else if((date('G', $fromTime)-$diffhours) >= -24) { return $l->t('yesterday'); }
|
||||
// 86400 * 31 days = 2678400
|
||||
else if($timediff < 2678400) { return $l->n('%n day go', '%n days ago', $diffdays); }
|
||||
// 86400 * 60 days = 518400
|
||||
else if($timediff < 5184000) { return $l->t('last month'); }
|
||||
else if((date('n', $fromTime)-$diffmonths) > 0) { return $l->n('%n month ago', '%n months ago', $diffmonths); }
|
||||
// 86400 * 365.25 days * 2 = 63113852
|
||||
else if($timediff < 63113852) { return $l->t('last year'); }
|
||||
else { return $l->t('years ago'); }
|
||||
if ($dateOnly){
|
||||
return $formatter->formatDateSpan($timestamp, $fromTime);
|
||||
}
|
||||
return $formatter->formatTimeSpan($timestamp, $fromTime);
|
||||
}
|
||||
|
||||
function html_select_options($options, $selected, $params=array()) {
|
||||
|
|
|
|||
|
|
@ -435,27 +435,20 @@ class OC_Util {
|
|||
* @param bool $dateOnly option to omit time from the result
|
||||
* @param DateTimeZone|string $timeZone where the given timestamp shall be converted to
|
||||
* @return string timestamp
|
||||
* @description adjust to clients timezone if we know it
|
||||
*
|
||||
* @deprecated Use \OC::$server->query('DateTimeFormatter') instead
|
||||
*/
|
||||
public static function formatDate($timestamp, $dateOnly = false, $timeZone = null) {
|
||||
if (is_null($timeZone)) {
|
||||
if (\OC::$server->getSession()->exists('timezone')) {
|
||||
$systemTimeZone = intval(date('O'));
|
||||
$systemTimeZone = (round($systemTimeZone / 100, 0) * 60) + ($systemTimeZone % 100);
|
||||
$clientTimeZone = \OC::$server->getSession()->get('timezone') * 60;
|
||||
$offset = $clientTimeZone - $systemTimeZone;
|
||||
$timestamp = $timestamp + $offset * 60;
|
||||
}
|
||||
} else {
|
||||
if (!$timeZone instanceof DateTimeZone) {
|
||||
$timeZone = new DateTimeZone($timeZone);
|
||||
}
|
||||
$dt = new DateTime("@$timestamp");
|
||||
$offset = $timeZone->getOffset($dt);
|
||||
$timestamp += $offset;
|
||||
if ($timeZone !== null && !$timeZone instanceof \DateTimeZone) {
|
||||
$timeZone = new \DateTimeZone($timeZone);
|
||||
}
|
||||
$l = \OC::$server->getL10N('lib');
|
||||
return $l->l($dateOnly ? 'date' : 'datetime', $timestamp);
|
||||
|
||||
/** @var \OC\DateTimeFormatter $formatter */
|
||||
$formatter = \OC::$server->query('DateTimeFormatter');
|
||||
if ($dateOnly) {
|
||||
return $formatter->formatDate($timestamp, 'long', $timeZone);
|
||||
}
|
||||
return $formatter->formatDateTime($timestamp, 'long', 'long', $timeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
121
lib/public/idatetimeformatter.php
Normal file
121
lib/public/idatetimeformatter.php
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
<?php
|
||||
/**
|
||||
* ownCloud
|
||||
*
|
||||
* @author Joas Schilling
|
||||
* @copyright 2014 Joas Schilling nickvergessen@owncloud.com
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCP;
|
||||
|
||||
interface IDateTimeFormatter {
|
||||
/**
|
||||
* Formats the date of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp
|
||||
* @param string $format Either 'full', 'long', 'medium' or 'short'
|
||||
* full: e.g. 'EEEE, MMMM d, y' => 'Wednesday, August 20, 2014'
|
||||
* long: e.g. 'MMMM d, y' => 'August 20, 2014'
|
||||
* medium: e.g. 'MMM d, y' => 'Aug 20, 2014'
|
||||
* short: e.g. 'M/d/yy' => '8/20/14'
|
||||
* The exact format is dependent on the language
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted date string
|
||||
*/
|
||||
public function formatDate($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null);
|
||||
|
||||
/**
|
||||
* Formats the date of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp
|
||||
* @param string $format Either 'full', 'long', 'medium' or 'short'
|
||||
* full: e.g. 'EEEE, MMMM d, y' => 'Wednesday, August 20, 2014'
|
||||
* long: e.g. 'MMMM d, y' => 'August 20, 2014'
|
||||
* medium: e.g. 'MMM d, y' => 'Aug 20, 2014'
|
||||
* short: e.g. 'M/d/yy' => '8/20/14'
|
||||
* The exact format is dependent on the language
|
||||
* Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted relative date string
|
||||
*/
|
||||
public function formatDateRelativeDay($timestamp, $format = 'long', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null);
|
||||
|
||||
/**
|
||||
* Gives the relative date of the timestamp
|
||||
* Only works for past dates
|
||||
*
|
||||
* @param int|\DateTime $timestamp
|
||||
* @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time
|
||||
* @return string Dates returned are:
|
||||
* < 1 month => Today, Yesterday, n days ago
|
||||
* < 13 month => last month, n months ago
|
||||
* >= 13 month => last year, n years ago
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted date span
|
||||
*/
|
||||
public function formatDateSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null);
|
||||
|
||||
/**
|
||||
* Formats the time of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp
|
||||
* @param string $format Either 'full', 'long', 'medium' or 'short'
|
||||
* full: e.g. 'h:mm:ss a zzzz' => '11:42:13 AM GMT+0:00'
|
||||
* long: e.g. 'h:mm:ss a z' => '11:42:13 AM GMT'
|
||||
* medium: e.g. 'h:mm:ss a' => '11:42:13 AM'
|
||||
* short: e.g. 'h:mm a' => '11:42 AM'
|
||||
* The exact format is dependent on the language
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted time string
|
||||
*/
|
||||
public function formatTime($timestamp, $format = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null);
|
||||
|
||||
/**
|
||||
* Gives the relative past time of the timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp
|
||||
* @param int|\DateTime $baseTimestamp Timestamp to compare $timestamp against, defaults to current time
|
||||
* @return string Dates returned are:
|
||||
* < 60 sec => seconds ago
|
||||
* < 1 hour => n minutes ago
|
||||
* < 1 day => n hours ago
|
||||
* < 1 month => Yesterday, n days ago
|
||||
* < 13 month => last month, n months ago
|
||||
* >= 13 month => last year, n years ago
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted time span
|
||||
*/
|
||||
public function formatTimeSpan($timestamp, $baseTimestamp = null, \OCP\IL10N $l = null);
|
||||
|
||||
/**
|
||||
* Formats the date and time of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp
|
||||
* @param string $formatDate See formatDate() for description
|
||||
* @param string $formatTime See formatTime() for description
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted date and time string
|
||||
*/
|
||||
public function formatDateTime($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null);
|
||||
|
||||
/**
|
||||
* Formats the date and time of the given timestamp
|
||||
*
|
||||
* @param int|\DateTime $timestamp
|
||||
* @param string $formatDate See formatDate() for description
|
||||
* Uses 'Today', 'Yesterday' and 'Tomorrow' when applicable
|
||||
* @param string $formatTime See formatTime() for description
|
||||
* @param \DateTimeZone $timeZone The timezone to use
|
||||
* @param \OCP\IL10N $l The locale to use
|
||||
* @return string Formatted relative date and time string
|
||||
*/
|
||||
public function formatDateTimeRelativeDay($timestamp, $formatDate = 'long', $formatTime = 'medium', \DateTimeZone $timeZone = null, \OCP\IL10N $l = null);
|
||||
}
|
||||
|
|
@ -94,6 +94,7 @@ function human_file_size( $bytes ) {
|
|||
* @param int $timestamp unix timestamp
|
||||
* @param boolean $dateOnly
|
||||
* @return \OC_L10N_String human readable interpretation of the timestamp
|
||||
*
|
||||
* @deprecated Use \OCP\Template::relative_modified_date() instead
|
||||
*/
|
||||
function relative_modified_date( $timestamp, $dateOnly = false ) {
|
||||
|
|
@ -188,12 +189,12 @@ class Template extends \OC_Template {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return the relative date in relation to today. Returns something like "last hour" or "two month ago"
|
||||
*
|
||||
* @param int $timestamp unix timestamp
|
||||
* @param boolean $dateOnly
|
||||
* @return \OC_L10N_String human readable interpretation of the timestamp
|
||||
*/
|
||||
* Return the relative date in relation to today. Returns something like "last hour" or "two month ago"
|
||||
*
|
||||
* @param int $timestamp unix timestamp
|
||||
* @param boolean $dateOnly
|
||||
* @return string human readable interpretation of the timestamp
|
||||
*/
|
||||
public static function relative_modified_date($timestamp, $dateOnly = false) {
|
||||
return \relative_modified_date($timestamp, null, $dateOnly);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,6 +163,8 @@ class Util {
|
|||
* @param bool $dateOnly option to omit time from the result
|
||||
* @param DateTimeZone|string $timeZone where the given timestamp shall be converted to
|
||||
* @return string timestamp
|
||||
*
|
||||
* @deprecated Use \OC::$server->query('DateTimeFormatter') instead
|
||||
*/
|
||||
public static function formatDate($timestamp, $dateOnly=false, $timeZone = null) {
|
||||
return(\OC_Util::formatDate($timestamp, $dateOnly, $timeZone));
|
||||
|
|
|
|||
177
tests/lib/datetimeformatter.php
Normal file
177
tests/lib/datetimeformatter.php
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright (c) 2014 Joas Schilling nickvergessen@owncloud.com
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace Test;
|
||||
|
||||
class DateTimeFormatter extends TestCase {
|
||||
/** @var \OC\DateTimeFormatter */
|
||||
protected $formatter;
|
||||
static protected $oneMinute = 60;
|
||||
static protected $oneHour = 3600;
|
||||
static protected $oneDay;
|
||||
static protected $oneYear;
|
||||
|
||||
static protected $defaultTimeZone;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
parent::setUpBeforeClass();
|
||||
self::$defaultTimeZone = date_default_timezone_get();
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
self::$oneDay = self::$oneHour * 24;
|
||||
self::$oneYear = self::$oneDay * 365;
|
||||
}
|
||||
|
||||
public static function tearDownAfterClass() {
|
||||
date_default_timezone_set(self::$defaultTimeZone);
|
||||
parent::tearDownAfterClass();
|
||||
}
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->formatter = new \OC\DateTimeFormatter(new \DateTimeZone('UTC'), new \OC_L10N('lib', 'en'));
|
||||
}
|
||||
|
||||
protected function getTimestampAgo($time, $seconds = 0, $minutes = 0, $hours = 0, $days = 0, $years = 0) {
|
||||
return $time - $seconds - $minutes * 60 - $hours * 3600 - $days * 24*3600 - $years * 365*24*3600;
|
||||
}
|
||||
|
||||
public function formatTimeSpanData() {
|
||||
// use the same time all the time, so the tests are reliable when time would switch
|
||||
$time = time();
|
||||
$deL10N = new \OC_L10N('lib', 'de');
|
||||
return array(
|
||||
array('seconds ago', $time, $time),
|
||||
array('1 minute ago', $this->getTimestampAgo($time, 30, 1), $time),
|
||||
array('15 minutes ago', $this->getTimestampAgo($time, 30, 15), $time),
|
||||
array('1 hour ago', $this->getTimestampAgo($time, 30, 15, 1), $time),
|
||||
array('3 hours ago', $this->getTimestampAgo($time, 30, 15, 3), $time),
|
||||
array('4 days ago', $this->getTimestampAgo($time, 30, 15, 3, 4), $time),
|
||||
|
||||
array('seconds ago', new \DateTime('Wed, 02 Oct 2013 23:59:58 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('seconds ago', new \DateTime('Wed, 02 Oct 2013 23:59:00 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('1 minute ago', new \DateTime('Wed, 02 Oct 2013 23:58:30 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('3 minutes ago', new \DateTime('Wed, 02 Oct 2013 23:56:30 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('59 minutes ago', new \DateTime('Wed, 02 Oct 2013 23:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('1 hour ago', new \DateTime('Wed, 02 Oct 2013 22:59:59 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('3 hours ago', new \DateTime('Wed, 02 Oct 2013 20:39:59 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('yesterday', new \DateTime('Tue, 01 Oct 2013 20:39:59 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('2 days ago', new \DateTime('Mon, 30 Sep 2013 20:39:59 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
|
||||
array($deL10N->t('seconds ago'), new \DateTime('Wed, 02 Oct 2013 23:59:58 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000'), $deL10N),
|
||||
array($deL10N->n('%n minute ago', '%n minutes ago', 1), new \DateTime('Wed, 02 Oct 2013 23:58:30 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000'), $deL10N),
|
||||
array($deL10N->n('%n minute ago', '%n minutes ago', 3), new \DateTime('Wed, 02 Oct 2013 23:56:30 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000'), $deL10N),
|
||||
array($deL10N->n('%n hour ago', '%n hours ago', 1), new \DateTime('Wed, 02 Oct 2013 22:59:59 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000'), $deL10N),
|
||||
array($deL10N->n('%n hour ago', '%n hours ago', 3), new \DateTime('Wed, 02 Oct 2013 20:39:59 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000'), $deL10N),
|
||||
array($deL10N->n('%n day ago', '%n days ago', 2), new \DateTime('Mon, 30 Sep 2013 20:39:59 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000'), $deL10N),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider formatTimeSpanData
|
||||
*/
|
||||
public function testFormatTimeSpan($expected, $timestamp, $compare, $locale = null) {
|
||||
$this->assertEquals((string) $expected, (string) $this->formatter->formatTimeSpan($timestamp, $compare, $locale));
|
||||
}
|
||||
|
||||
public function formatDateSpanData() {
|
||||
// use the same time all the time, so the tests are reliable when time would switch
|
||||
$time = time();
|
||||
$deL10N = new \OC_L10N('lib', 'de');
|
||||
return array(
|
||||
// Normal testing
|
||||
array('today', $this->getTimestampAgo($time, 30, 15), $time),
|
||||
array('yesterday', $this->getTimestampAgo($time, 0, 0, 0, 1), $time),
|
||||
array('4 days ago', $this->getTimestampAgo($time, 0, 0, 0, 4), $time),
|
||||
array('5 months ago', $this->getTimestampAgo($time, 0, 0, 0, 155), $time),
|
||||
array('2 years ago', $this->getTimestampAgo($time, 0, 0, 0, 0, 2), $time),
|
||||
|
||||
// Test with compare timestamp
|
||||
array('today', $this->getTimestampAgo($time, 0, 0, 0, 0, 1), $this->getTimestampAgo($time, 0, 0, 0, 0, 1)),
|
||||
array('yesterday', $this->getTimestampAgo($time, 30, 15, 3, 1, 1), $this->getTimestampAgo($time, 0, 0, 0, 0, 1)),
|
||||
array('4 days ago', $this->getTimestampAgo($time, 30, 15, 3, 4, 1), $this->getTimestampAgo($time, 0, 0, 0, 0, 1)),
|
||||
array('5 months ago', $this->getTimestampAgo($time, 30, 15, 3, 155, 1), $this->getTimestampAgo($time, 0, 0, 0, 0, 1)),
|
||||
array('2 years ago', $this->getTimestampAgo($time, 30, 15, 3, 35, 3), $this->getTimestampAgo($time, 0, 0, 0, 0, 1)),
|
||||
|
||||
// Test translations
|
||||
array($deL10N->t('today'), new \DateTime('Wed, 02 Oct 2013 12:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000'), $deL10N),
|
||||
array($deL10N->t('yesterday'), new \DateTime('Tue, 01 Oct 2013 00:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 00:00:00 +0000'), $deL10N),
|
||||
array($deL10N->n('%n day ago', '%n days ago', 2), new \DateTime('Mon, 30 Sep 2013 00:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 00:00:00 +0000'), $deL10N),
|
||||
array($deL10N->n('%n month ago', '%n months ago', 9), new \DateTime('Tue, 31 Dec 2013 00:00:00 +0000'), new \DateTime('Thu, 02 Oct 2014 00:00:00 +0000'), $deL10N),
|
||||
array($deL10N->n('%n year ago', '%n years ago', 2), new \DateTime('Sun, 01 Jan 2012 00:00:00 +0000'), new \DateTime('Thu, 02 Oct 2014 00:00:00 +0000'), $deL10N),
|
||||
|
||||
// Test time
|
||||
array('today', new \DateTime('Wed, 02 Oct 2013 00:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('today', new \DateTime('Wed, 02 Oct 2013 12:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('today', new \DateTime('Wed, 02 Oct 2013 23:59:58 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
|
||||
// Test some special yesterdays
|
||||
array('yesterday', new \DateTime('Tue, 01 Oct 2013 00:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 00:00:00 +0000')),
|
||||
array('yesterday', new \DateTime('Tue, 01 Oct 2013 00:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('yesterday', new \DateTime('Tue, 01 Oct 2013 23:59:58 +0000'), new \DateTime('Wed, 02 Oct 2013 00:00:00 +0000')),
|
||||
array('yesterday', new \DateTime('Tue, 01 Oct 2013 23:59:58 +0000'), new \DateTime('Wed, 02 Oct 2013 23:59:59 +0000')),
|
||||
array('yesterday', new \DateTime('Mon, 30 Sep 2013 00:00:00 +0000'), new \DateTime('Tue, 01 Oct 2013 00:00:00 +0000')),
|
||||
array('yesterday', new \DateTime('Mon, 31 Dec 2012 00:00:00 +0000'), new \DateTime('Tue, 01 Jan 2013 00:00:00 +0000')),
|
||||
|
||||
// Test last month
|
||||
array('2 days ago', new \DateTime('Mon, 30 Sep 2013 00:00:00 +0000'), new \DateTime('Wed, 02 Oct 2013 00:00:00 +0000')),
|
||||
array('last month', new \DateTime('Mon, 30 Sep 2013 00:00:00 +0000'), new \DateTime('Tue, 31 Oct 2013 00:00:00 +0000')),
|
||||
array('last month', new \DateTime('Sun, 01 Sep 2013 00:00:00 +0000'), new \DateTime('Tue, 01 Oct 2013 00:00:00 +0000')),
|
||||
array('last month', new \DateTime('Sun, 01 Sep 2013 00:00:00 +0000'), new \DateTime('Thu, 31 Oct 2013 00:00:00 +0000')),
|
||||
|
||||
// Test last year
|
||||
array('9 months ago', new \DateTime('Tue, 31 Dec 2013 00:00:00 +0000'), new \DateTime('Thu, 02 Oct 2014 00:00:00 +0000')),
|
||||
array('11 months ago', new \DateTime('Thu, 03 Oct 2013 00:00:00 +0000'), new \DateTime('Thu, 02 Oct 2014 00:00:00 +0000')),
|
||||
array('last year', new \DateTime('Wed, 02 Oct 2013 00:00:00 +0000'), new \DateTime('Thu, 02 Oct 2014 00:00:00 +0000')),
|
||||
array('last year', new \DateTime('Tue, 01 Jan 2013 00:00:00 +0000'), new \DateTime('Thu, 02 Oct 2014 00:00:00 +0000')),
|
||||
array('2 years ago', new \DateTime('Sun, 01 Jan 2012 00:00:00 +0000'), new \DateTime('Thu, 02 Oct 2014 00:00:00 +0000')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider formatDateSpanData
|
||||
*/
|
||||
public function testFormatDateSpan($expected, $timestamp, $compare = null, $locale = null) {
|
||||
$this->assertEquals((string) $expected, (string) $this->formatter->formatDateSpan($timestamp, $compare, $locale));
|
||||
}
|
||||
|
||||
public function formatDateData() {
|
||||
return array(
|
||||
array(1102831200, 'December 12, 2004'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider formatDateData
|
||||
*/
|
||||
public function testFormatDate($timestamp, $expected) {
|
||||
$this->assertEquals($expected, (string) $this->formatter->formatDate($timestamp));
|
||||
}
|
||||
|
||||
public function formatDateTimeData() {
|
||||
return array(
|
||||
array(1350129205, null, 'October 13, 2012 at 11:53:25 AM GMT+0'),
|
||||
array(1350129205, new \DateTimeZone('Europe/Berlin'), 'October 13, 2012 at 1:53:25 PM GMT+2'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider formatDateTimeData
|
||||
*/
|
||||
public function testFormatDateTime($timestamp, $timeZone, $expected) {
|
||||
$this->assertEquals($expected, (string) $this->formatter->formatDateTime($timestamp, 'long', 'long', $timeZone));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Exception
|
||||
*/
|
||||
function testFormatDateWithInvalidTZ() {
|
||||
$this->formatter->formatDate(1350129205, 'long', new \DateTimeZone('Mordor/Barad-dûr'));
|
||||
}
|
||||
}
|
||||
|
|
@ -117,15 +117,15 @@ class Test_TemplateFunctions extends \Test\TestCase {
|
|||
|
||||
public function testRelativeDateMonthsAgo(){
|
||||
$currentTime = 1380703592;
|
||||
$elementTime = $currentTime - 86400 * 60;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, true);
|
||||
|
||||
$this->assertEquals('2 months ago', $result);
|
||||
|
||||
$elementTime = $currentTime - 86400 * 65;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, true);
|
||||
|
||||
$this->assertEquals('2 months ago', $result);
|
||||
|
||||
$elementTime = $currentTime - 86400 * 130;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, true);
|
||||
|
||||
$this->assertEquals('4 months ago', $result);
|
||||
}
|
||||
|
||||
public function testRelativeDateLastYear(){
|
||||
|
|
@ -146,12 +146,12 @@ class Test_TemplateFunctions extends \Test\TestCase {
|
|||
$elementTime = $currentTime - 86400 * 365.25 * 2;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, true);
|
||||
|
||||
$this->assertEquals('years ago', $result);
|
||||
$this->assertEquals('2 years ago', $result);
|
||||
|
||||
$elementTime = $currentTime - 86400 * 365.25 * 3;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, true);
|
||||
|
||||
$this->assertEquals('years ago', $result);
|
||||
$this->assertEquals('3 years ago', $result);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -211,15 +211,15 @@ class Test_TemplateFunctions extends \Test\TestCase {
|
|||
|
||||
public function testRelativeTimeMonthsAgo(){
|
||||
$currentTime = 1380703592;
|
||||
$elementTime = $currentTime - 86400 * 60;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, false);
|
||||
|
||||
$this->assertEquals('2 months ago', $result);
|
||||
|
||||
$elementTime = $currentTime - 86400 * 65;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, false);
|
||||
|
||||
$this->assertEquals('2 months ago', $result);
|
||||
|
||||
$elementTime = $currentTime - 86400 * 130;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, false);
|
||||
|
||||
$this->assertEquals('4 months ago', $result);
|
||||
}
|
||||
|
||||
public function testRelativeTimeLastYear(){
|
||||
|
|
@ -240,11 +240,11 @@ class Test_TemplateFunctions extends \Test\TestCase {
|
|||
$elementTime = $currentTime - 86400 * 365.25 * 2;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, false);
|
||||
|
||||
$this->assertEquals('years ago', $result);
|
||||
$this->assertEquals('2 years ago', $result);
|
||||
|
||||
$elementTime = $currentTime - 86400 * 365.25 * 3;
|
||||
$result = (string)relative_modified_date($elementTime, $currentTime, false);
|
||||
|
||||
$this->assertEquals('years ago', $result);
|
||||
$this->assertEquals('3 years ago', $result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class Test_Util extends \Test\TestCase {
|
|||
date_default_timezone_set("UTC");
|
||||
|
||||
$result = OC_Util::formatDate(1350129205, false, 'Europe/Berlin');
|
||||
$expected = 'October 13, 2012 at 1:53:25 PM GMT+0';
|
||||
$expected = 'October 13, 2012 at 1:53:25 PM GMT+2';
|
||||
$this->assertEquals($expected, $result);
|
||||
}
|
||||
|
||||
|
|
@ -55,10 +55,22 @@ class Test_Util extends \Test\TestCase {
|
|||
function testFormatDateWithTZFromSession() {
|
||||
date_default_timezone_set("UTC");
|
||||
|
||||
$oldDateTimeFormatter = \OC::$server->query('DateTimeFormatter');
|
||||
\OC::$server->getSession()->set('timezone', 3);
|
||||
$newDateTimeFormatter = new \OC\DateTimeFormatter(\OC::$server->getTimeZone(), new \OC_L10N('lib', 'en'));
|
||||
$this->setDateFormatter($newDateTimeFormatter);
|
||||
|
||||
$result = OC_Util::formatDate(1350129205, false);
|
||||
$expected = 'October 13, 2012 at 2:53:25 PM GMT+0';
|
||||
$expected = 'October 13, 2012 at 2:53:25 PM GMT+3';
|
||||
$this->assertEquals($expected, $result);
|
||||
|
||||
$this->setDateFormatter($oldDateTimeFormatter);
|
||||
}
|
||||
|
||||
protected function setDateFormatter($formatter) {
|
||||
\OC::$server->registerService('DateTimeFormatter', function ($c) use ($formatter) {
|
||||
return $formatter;
|
||||
});
|
||||
}
|
||||
|
||||
function testCallRegister() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue