[TASK] Remove TCA building aspect and move code to bootstrap
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / DateTimeUtility.php
1 <?php
2 namespace TYPO3\CMS\Core\Utility;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2014 Alexander Opitz <opitz.alexander@googlemail.com>
8 * (c) 2014 Markus Klein <klein.t3@mfc-linz.at>
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the textfile GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30
31 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
32 use TYPO3\CMS\Lang\LanguageService;
33
34 /**
35 * This class has functions for handling date and time. Especially differences between two dates as readable string.
36 *
37 * @author Alexander Opitz <opitz@pluspol.info>
38 * @author Markus Klein <klein.t3@mfc-linz.at>
39 */
40 class DateTimeUtility {
41
42 /**
43 * @var int for usage with the getSimpleAgeString or round function
44 */
45 const CEIL = 10;
46
47 /**
48 * @var int for usage with the getSimpleAgeString or round function
49 */
50 const FLOOR = 11;
51
52 /**
53 * Returns the given microtime as milliseconds.
54 *
55 * @param string $microtime Microtime as "msec sec" string given by php function microtime
56 * @return int Microtime input string converted to an int (milliseconds)
57 */
58 static public function convertMicrotime($microtime) {
59 $parts = explode(' ', $microtime);
60 return (int)round(($parts[0] + $parts[1]) * 1000);
61 }
62
63 /**
64 * Gets the unixtime as milliseconds.
65 *
66 * @return int The unixtime as milliseconds
67 */
68 static public function milliseconds() {
69 return (int)round(microtime(TRUE) * 1000);
70 }
71
72 /**
73 * Returns a string representation of the difference between timestamps in minutes / hours / days / months / years
74 * with a given label.
75 *
76 * @param int $startTime Unix timestamp for calculating difference of
77 * @param int $endTime Unix timestamp for calculating difference to
78 * @param string|array|NULL $labels Labels should be something like ' mins| hrs| days| months| yrs| min| hour| day| month| year'
79 * This value is typically delivered by this function call:
80 * $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysMonthsYears')
81 * Or using the array returned by splitTimeUnitsFromLabel()
82 * @return string Formatted time difference
83 */
84 static public function getTimeDiffStringUnix($startTime, $endTime, $labels = NULL) {
85 return static::getTimeDiffString(
86 new \DateTime('@' . $startTime),
87 new \DateTime('@' . $endTime),
88 $labels
89 );
90 }
91
92 /**
93 * Returns a string representation of the difference between DateTimes in minutes / hours / days / months / years
94 * with a given label.
95 *
96 * @param \DateTime $startDateTime Unix timestamp for calculating difference of
97 * @param \DateTime $endDateTime Unix timestamp for calculating difference to
98 * @param string|array|NULL $labels Labels should be something like ' mins| hrs| days| months| yrs| min| hour| day| month| year'
99 * This value is typically delivered by this function call:
100 * $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysMonthsYears')
101 * Or using the array returned by splitTimeUnitsFromLabel()
102 * @return string Formatted time difference
103 */
104 static public function getTimeDiffString(\DateTime $startDateTime, \DateTime $endDateTime, $labels = NULL) {
105 if (!is_array($labels) || empty($labels)) {
106 $labels = static::splitTimeUnitsFromLabel($labels);
107 }
108
109 $dateDiff = $startDateTime->diff($endDateTime);
110
111 if ($dateDiff->y > 0) {
112 $value = $dateDiff->y;
113 $label = 'year';
114 } elseif ($dateDiff->m > 0 && isset($labels['months'])) {
115 $value = $dateDiff->m;
116 $label = 'month';
117 } elseif ($dateDiff->days > 0) {
118 $value = $dateDiff->days;
119 $label = 'day';
120 } elseif ($dateDiff->h > 0) {
121 $value = $dateDiff->h;
122 $label = 'hour';
123 } else {
124 $value = $dateDiff->i;
125 $label = 'min';
126 }
127
128 // Get real label depending on singular/plural
129 $label = $labels[$label . ($value === 1 ? '' : 's')];
130
131 if ($dateDiff->invert === 1) {
132 $value *= -1;
133 }
134
135 return $value . $label;
136 }
137
138 /**
139 * Converts the old plural, old singular/plural and the new singular/plural pipe split string
140 * into an array with known unit names as keys.
141 *
142 * @param string|NULL $labels Labels should be something like ' min| hrs| days| months| yrs| min| hour| day| month| year'
143 * This value is typically delivered by this function call:
144 * $GLOBALS['LANG']->sL("LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysMonthsYears")
145 * @return array String split array
146 */
147 static public function splitTimeUnitsFromLabel($labels = NULL) {
148 if (NULL === $labels) {
149 $lang = self::getLanguageService();
150 $tsfe = self::getTypoScriptFrontendController();
151 if ($lang) {
152 $labels = $lang->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysMonthsYears');
153 } elseif ($tsfe) {
154 $labels = $tsfe->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysMonthsYears');
155 }
156 // Couldn't determine from local config so take default value.
157 if (empty($labels)) {
158 $labels = ' min| hrs| days| months| yrs| min| hour| day| month| year';
159 }
160 } else {
161 $labels = str_replace('"', '', $labels);
162 }
163
164 $labelArr = explode('|', $labels);
165 $resultArr = array();
166
167 if (count($labelArr) === 4) {
168 // Old plural labels string, add plural as singular
169 $labelArr = array_merge($labelArr, $labelArr);
170 }
171
172 switch (count($labelArr)) {
173 case 8:
174 // Old singular and plural labels string
175 $resultArr['min'] = $labelArr[4];
176 $resultArr['mins'] = $labelArr[0];
177 $resultArr['hour'] = $labelArr[5];
178 $resultArr['hours'] = $labelArr[1];
179 $resultArr['day'] = $labelArr[6];
180 $resultArr['days'] = $labelArr[2];
181 $resultArr['year'] = $labelArr[7];
182 $resultArr['years'] = $labelArr[3];
183 break;
184 case 10:
185 // New singular and plural labels string (with month)
186 $resultArr['min'] = $labelArr[5];
187 $resultArr['mins'] = $labelArr[0];
188 $resultArr['hour'] = $labelArr[6];
189 $resultArr['hours'] = $labelArr[1];
190 $resultArr['day'] = $labelArr[7];
191 $resultArr['days'] = $labelArr[2];
192 $resultArr['month'] = $labelArr[8];
193 $resultArr['months'] = $labelArr[3];
194 $resultArr['year'] = $labelArr[9];
195 $resultArr['years'] = $labelArr[4];
196 break;
197 default:
198 static::splitTimeUnitsFromLabel(NULL);
199 }
200
201 return $resultArr;
202 }
203
204 /**
205 * Returns the "age" in minutes / hours / days / months / years depending of the number of $seconds inputted.
206 *
207 * @param int $seconds Seconds could be the difference of a certain timestamp and time()
208 * @param string|array|NULL $labels Labels should be something like ' min| hrs| days| months| yrs| min| hour| day| month| year'
209 * This value is typically delivered by this function call:
210 * $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysMonthsYears')
211 * Or using the array returned by splitTimeUnitsFromLabel()
212 * @param int $method Method to use to round the result (PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN,
213 * PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD - round, 10 - ceil, 11 - floor)
214 * @return string Formatted time
215 */
216 static public function getSimpleAgeString($seconds, $labels = NULL, $method = PHP_ROUND_HALF_UP) {
217 if (!is_array($labels) || empty($labels)) {
218 $labels = static::splitTimeUnitsFromLabel($labels);
219 }
220
221 $sign = $seconds < 0 ? -1 : 1;
222 $seconds = abs($seconds);
223 if ($seconds < 3600) {
224 $roundedResult = static::round($seconds / 60, $method);
225 $seconds = $sign * $roundedResult . ($roundedResult == 1 ? $labels['mins'] : $labels['min']);
226 } elseif ($seconds < 24 * 3600) {
227 $roundedResult = static::round($seconds / 3600, $method);
228 $seconds = $sign * $roundedResult . ($roundedResult == 1 ? $labels['hour'] : $labels['hours']);
229 } elseif ($seconds < 30 * 24 * 3600 || (!isset($labels['month']) && $seconds < 365 * 24 * 3600)) {
230 $roundedResult = static::round($seconds / (24 * 3600), $method);
231 $seconds = $sign * $roundedResult . ($roundedResult == 1 ? $labels['day'] : $labels['days']);
232 } elseif (isset($labels['month']) && $seconds < 365 * 24 * 3600) {
233 $roundedResult = static::round($seconds / (30 * 24 * 3600), $method);
234 $seconds = $sign * $roundedResult . ($roundedResult == 1 ? $labels['month'] : $labels['months']);
235 } else {
236 $roundedResult = static::round($seconds / (365 * 24 * 3600), $method);
237 $seconds = $sign * $roundedResult . ($roundedResult == 1 ? $labels['year'] : $labels['years']);
238 }
239
240 return $seconds;
241 }
242
243 /**
244 * Returns a string representation of the age of a timestamps in minutes / hours / days / months / years
245 * with a given label. $GLOBALS['EXEC_TIME'] is taken as "now".
246 *
247 * @param int $time Unix timestamp for calculating age of
248 * @param string|array|NULL $labels Labels should be something like ' min| hrs| days| months| yrs| min| hour| day| month| year'
249 * This value is typically delivered by this function call:
250 * $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysMonthsYears')
251 * Or using the array returned by splitTimeUnitsFromLabel()
252 * @return string Formatted time age
253 */
254 static public function getAgeStringUnix($time, $labels = NULL) {
255 return static::getTimeDiffStringUnix($time, $GLOBALS['EXEC_TIME'], $labels);
256 }
257
258 /**
259 * Returns a string representation of the age of a DateTime in minutes / hours / days / months / years
260 * with a given label. $GLOBALS['EXEC_TIME'] is taken as "now".
261 *
262 * @param \DateTime|$time DateTime for calculating age of
263 * @param string|array|NULL $labels Labels should be something like ' min| hrs| days| months| yrs| min| hour| day| month| year'
264 * This value is typically delivered by this function call:
265 * $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysMonthsYears')
266 * Or using the array returned by splitTimeUnitsFromLabel()
267 * @return string Formatted time age
268 */
269 static public function getAgeString(\DateTime $time, $labels = NULL) {
270 return static::getTimeDiffString(
271 $time,
272 new \DateTime('@' . $GLOBALS['EXEC_TIME']),
273 $labels
274 );
275 }
276
277 /**
278 * Rounds the $value in the mathematical way of the choosen method.
279 *
280 * @param mixed $value The value to round
281 * @param int $method Method to use to round the result (PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN,
282 * PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD, DateTimeUtility::CEIL, DateTimeUtility::FLOOR)
283 * @return int
284 */
285 static public function round($value, $method = PHP_ROUND_HALF_UP) {
286 switch ($method) {
287 case DateTimeUtility::CEIL:
288 $value = ceil($value);
289 break;
290
291 case DateTimeUtility::FLOOR:
292 $value = floor($value);
293 break;
294
295 default:
296 $value = round($value, 0, $method);
297 }
298
299 return (int)$value;
300 }
301
302 /**
303 * @return LanguageService|NULL
304 */
305 static protected function getLanguageService() {
306 return isset($GLOBALS['LANG']) ? $GLOBALS['LANG'] : NULL;
307 }
308
309 /**
310 * @return TypoScriptFrontendController|NULL
311 */
312 static protected function getTypoScriptFrontendController() {
313 return isset($GLOBALS['TSFE']) ? $GLOBALS['TSFE'] : NULL;
314 }
315 }