281 lines
9.6 KiB
PHP
281 lines
9.6 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; under version 2
|
|
* of the License (non-upgradable).
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Copyright (c) 2008-2010 (original work) Deutsche Institut für Internationale Pädagogische Forschung (under the project TAO-TRANSFER);
|
|
* 2009-2012 (update and modification) Public Research Centre Henri Tudor (under the project TAO-SUSTAIN & TAO-DEV);
|
|
*
|
|
*/
|
|
|
|
use oat\tao\helpers\dateFormatter\EuropeanFormatter;
|
|
use oat\tao\helpers\dateFormatter\DateFormatterInterface;
|
|
|
|
/**
|
|
* Utility to display dates.
|
|
*
|
|
* @author Joel Bout, <joel@taotesting.com>
|
|
* @package tao
|
|
*
|
|
*/
|
|
class tao_helpers_Date
|
|
{
|
|
const CONFIG_KEY = 'dateService';
|
|
|
|
const FORMAT_LONG = 0;
|
|
|
|
const FORMAT_VERBOSE = 1;
|
|
|
|
const FORMAT_DATEPICKER = 2;
|
|
|
|
const FORMAT_ISO8601 = 3;
|
|
|
|
const FORMAT_LONG_MICROSECONDS = 4;
|
|
|
|
const FORMAT_INTERVAL_LONG = 100;
|
|
|
|
const FORMAT_INTERVAL_SHORT = 101;
|
|
|
|
const FORMAT_FALLBACK = -1;
|
|
|
|
private static $service;
|
|
|
|
/**
|
|
* Returns configured date formatter.
|
|
*
|
|
* @return DateFormatterInterface
|
|
*/
|
|
public static function getDateFormatter()
|
|
{
|
|
if (is_null(self::$service)) {
|
|
$ext = common_ext_ExtensionsManager::singleton()->getExtensionById('tao');
|
|
$service = $ext->getConfig(self::CONFIG_KEY);
|
|
self::$service = $service instanceof DateFormatterInterface
|
|
? $service
|
|
: new EuropeanFormatter();
|
|
}
|
|
|
|
return self::$service;
|
|
}
|
|
|
|
/**
|
|
* Displays a date/time
|
|
* Should in theory be dependant on the users locale and timezone
|
|
* @param mixed $timestamp
|
|
* @param int $format The date format. See tao_helpers_Date's constants.
|
|
* @param DateTimeZone $timeZone user timezone
|
|
* @return string The formatted date.
|
|
* @throws common_Exception when timestamp is not recognized
|
|
*/
|
|
public static function displayeDate($timestamp, $format = self::FORMAT_LONG, DateTimeZone $timeZone = null)
|
|
{
|
|
if (is_object($timestamp) && $timestamp instanceof core_kernel_classes_Literal) {
|
|
$ts = $timestamp->__toString();
|
|
} elseif (is_object($timestamp) && $timestamp instanceof DateTimeInterface) {
|
|
$ts = self::getTimeStampWithMicroseconds($timestamp);
|
|
} elseif (is_numeric($timestamp)) {
|
|
$ts = $timestamp;
|
|
} elseif (is_string($timestamp) && preg_match('/.\+0000$/', $timestamp)) {
|
|
$ts = self::getTimeStampWithMicroseconds(new DateTime($timestamp, new DateTimeZone('UTC')));
|
|
} elseif (is_string($timestamp) && preg_match('/0\.[\d]+\s[\d]+/', $timestamp)) {
|
|
$ts = self::getTimeStamp($timestamp, true);
|
|
} else {
|
|
throw new common_Exception('Unexpected timestamp');
|
|
}
|
|
|
|
return self::getDateFormatter()->format($ts, $format, $timeZone);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @author Lionel Lecaque, lionel@taotesting.com
|
|
* @param unknown $interval
|
|
* @param integer $format
|
|
* @return string|Ambigous <string, string>
|
|
*/
|
|
public static function displayInterval($interval, $format = self::FORMAT_INTERVAL_LONG)
|
|
{
|
|
if (is_object($interval)) {
|
|
$intervalObj = $interval;
|
|
} else {
|
|
$intervalObj = new DateTime();
|
|
$intervalObj->setTimestamp($interval);
|
|
}
|
|
$newDate = new \DateTime();
|
|
$intervalObj = $intervalObj instanceof DateTimeInterface ? $newDate->diff($intervalObj, true) : $intervalObj;
|
|
if (! $intervalObj instanceof DateInterval) {
|
|
common_Logger::w('Unknown interval format ' . get_class($interval) . ' for ' . __FUNCTION__);
|
|
return '';
|
|
}
|
|
|
|
$formatStrings = self::getNonNullIntervalFormats($intervalObj);
|
|
if (empty($formatStrings)) {
|
|
$returnValue = __("less than a minute");
|
|
} else {
|
|
$returnValue = '';
|
|
switch ($format) {
|
|
case self::FORMAT_INTERVAL_SHORT:
|
|
$returnValue = $intervalObj->format(array_shift($formatStrings));
|
|
break;
|
|
case self::FORMAT_INTERVAL_LONG:
|
|
$returnValue = self::formatElapsed($intervalObj, $formatStrings);
|
|
break;
|
|
default:
|
|
common_Logger::w('Unknown date format ' . $format . ' for ' . __FUNCTION__);
|
|
}
|
|
}
|
|
return $returnValue;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @author Lionel Lecaque, lionel@taotesting.com
|
|
* @param DateInterval $interval
|
|
* @param unknown $formatStrings
|
|
* @return string
|
|
*/
|
|
protected static function formatElapsed(DateInterval $interval, $formatStrings)
|
|
{
|
|
$string = '';
|
|
while (! empty($formatStrings)) {
|
|
$string .= $interval->format(array_shift($formatStrings)) . (count($formatStrings) == 0 ? '' : (count($formatStrings) == 1 ? __(' and ') : ' '));
|
|
}
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @author Lionel Lecaque, lionel@taotesting.com
|
|
* @param DateInterval $interval
|
|
* @return multitype:string Ambigous <string, string>
|
|
*/
|
|
private static function getNonNullIntervalFormats(DateInterval $interval)
|
|
{
|
|
$formats = [];
|
|
if ($interval->y > 0) {
|
|
$formats[] = $interval->y == 1 ? __("%y year") : __("%y years");
|
|
}
|
|
if ($interval->m > 0) {
|
|
$formats[] = $interval->m == 1 ? __("%m month") : __("%m months");
|
|
}
|
|
if ($interval->d > 0) {
|
|
$formats[] = $interval->d == 1 ? __("%d day") : __("%d days");
|
|
}
|
|
if ($interval->h > 0) {
|
|
$formats[] = $interval->h == 1 ? __("%h hour") : __("%h hours");
|
|
}
|
|
if ($interval->i > 0) {
|
|
$formats[] = $interval->i == 1 ? __("%i minute") : __("%i minutes");
|
|
}
|
|
return $formats;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @author Lionel Lecaque, lionel@taotesting.com
|
|
* @param unknown $microtime
|
|
* @return number
|
|
*/
|
|
static function getTimeStamp($microtime, $microseconds = false)
|
|
{
|
|
$parts = array_reverse(explode(" ", $microtime));
|
|
|
|
if ($microseconds && isset($parts[1])) {
|
|
$round = sprintf('%0.6f', $parts[1]);
|
|
if ($round === '1.000000') {
|
|
// Edge case -> rounded up to the second.
|
|
$timestamp = '' . (intval($parts[0]) + 1) . '.000000';
|
|
} else {
|
|
$timestamp = $parts[0] . '.' . str_replace('0.', '', $round);
|
|
}
|
|
} else {
|
|
$timestamp = $parts[0];
|
|
}
|
|
|
|
return $timestamp;
|
|
}
|
|
|
|
static function getTimeStampWithMicroseconds(DateTime $dt)
|
|
{
|
|
return join('.', [$dt->getTimestamp(), $dt->format('u')]);
|
|
}
|
|
|
|
/**
|
|
* Get array of DateTime objects build from $date (or current time if not given) $amount times back with given interval
|
|
* Example:
|
|
* $timeKeys = $service->getTimeKeys(new \DateInterval('PT1H'), new \DateTime('now'), 24);
|
|
*
|
|
* array (
|
|
* 0 =>
|
|
* DateTime::__set_state(array(
|
|
* 'date' => '2017-04-24 08:00:00.000000',
|
|
* 'timezone_type' => 1,
|
|
* 'timezone' => '+00:00',
|
|
* )),
|
|
* 1 =>
|
|
* DateTime::__set_state(array(
|
|
* 'date' => '2017-04-24 07:00:00.000000',
|
|
* 'timezone_type' => 1,
|
|
* 'timezone' => '+00:00',
|
|
* )),
|
|
* 2 =>
|
|
* DateTime::__set_state(array(
|
|
* 'date' => '2017-04-24 06:00:00.000000',
|
|
* 'timezone_type' => 1,
|
|
* 'timezone' => '+00:00',
|
|
* )),
|
|
* ...
|
|
* )
|
|
*
|
|
* @param \DateInterval $interval
|
|
* @param \DateTimeInterface|null $date
|
|
* @param null $amount
|
|
* @return \DateTime[]
|
|
*/
|
|
public static function getTimeKeys(\DateInterval $interval, \DateTimeInterface $date = null, $amount = null)
|
|
{
|
|
$timeKeys = [];
|
|
if ($date === null) {
|
|
$date = new \DateTime('now', new \DateTimeZone('UTC'));
|
|
}
|
|
|
|
if ($interval->format('%i') > 0) {
|
|
$date->setTime($date->format('H'), $date->format('i') + 1, 0);
|
|
$amount = $amount === null ? 60 : $amount;
|
|
}
|
|
if ($interval->format('%h') > 0) {
|
|
$date->setTime($date->format('H') + 1, 0, 0);
|
|
$amount = $amount === null ? 24 : $amount;
|
|
}
|
|
if ($interval->format('%d') > 0) {
|
|
$date->setTime(0, 0, 0);
|
|
$date->setDate($date->format('Y'), $date->format('m'), $date->format('d') + 1);
|
|
$amount = $amount === null ? cal_days_in_month(CAL_GREGORIAN, $date->format('m'), $date->format('Y')) : $amount;
|
|
}
|
|
if ($interval->format('%m') > 0) {
|
|
$date->setTime(0, 0, 0);
|
|
$date->setDate($date->format('Y'), $date->format('m') + 1, 1);
|
|
$amount = $amount === null ? 12 : $amount;
|
|
}
|
|
|
|
while ($amount > 0) {
|
|
$timeKeys[] = new \DateTime($date->format(\DateTime::ISO8601), new \DateTimeZone('UTC'));
|
|
$date->sub($interval);
|
|
$amount--;
|
|
}
|
|
return $timeKeys;
|
|
}
|
|
}
|