tao-test/app/tao/helpers/class.Date.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;
}
}