1: <?php
2: /**
3: * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4: * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5: *
6: * Licensed under The MIT License
7: * For full copyright and license information, please see the LICENSE.txt
8: * Redistributions of files must retain the above copyright notice.
9: *
10: * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11: * @link https://cakephp.org CakePHP(tm) Project
12: * @since 0.10.0
13: * @license https://opensource.org/licenses/mit-license.php MIT License
14: */
15: namespace Cake\View\Helper;
16:
17: use Cake\I18n\Time;
18: use Cake\View\Helper;
19: use Cake\View\StringTemplateTrait;
20: use Exception;
21:
22: /**
23: * Time Helper class for easy use of time data.
24: *
25: * Manipulation of time data.
26: *
27: * @link https://book.cakephp.org/3.0/en/views/helpers/time.html
28: * @see \Cake\I18n\Time
29: */
30: class TimeHelper extends Helper
31: {
32: use StringTemplateTrait;
33:
34: /**
35: * Config options
36: *
37: * @var array
38: */
39: protected $_defaultConfig = [
40: 'outputTimezone' => null
41: ];
42:
43: /**
44: * Get a timezone.
45: *
46: * Will use the provided timezone, or default output timezone if defined.
47: *
48: * @param \DateTimeZone|string|null $timezone The override timezone if applicable.
49: * @return \DateTimeZone|string|null The chosen timezone or null.
50: */
51: protected function _getTimezone($timezone)
52: {
53: if ($timezone) {
54: return $timezone;
55: }
56:
57: return $this->getConfig('outputTimezone');
58: }
59:
60: /**
61: * Returns a UNIX timestamp, given either a UNIX timestamp or a valid strtotime() date string.
62: *
63: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
64: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
65: * @return \Cake\I18n\Time
66: */
67: public function fromString($dateString, $timezone = null)
68: {
69: return (new Time($dateString))->timezone($timezone);
70: }
71:
72: /**
73: * Returns a nicely formatted date string for given Datetime string.
74: *
75: * @param int|string|\DateTime|null $dateString UNIX timestamp, strtotime() valid string or DateTime object
76: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
77: * @param string|null $locale Locale string.
78: * @return string Formatted date string
79: */
80: public function nice($dateString = null, $timezone = null, $locale = null)
81: {
82: $timezone = $this->_getTimezone($timezone);
83:
84: return (new Time($dateString))->nice($timezone, $locale);
85: }
86:
87: /**
88: * Returns true, if the given datetime string is today.
89: *
90: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
91: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
92: * @return bool True if the given datetime string is today.
93: */
94: public function isToday($dateString, $timezone = null)
95: {
96: return (new Time($dateString, $timezone))->isToday();
97: }
98:
99: /**
100: * Returns true, if the given datetime string is in the future.
101: *
102: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
103: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
104: * @return bool True if the given datetime string lies in the future.
105: */
106: public function isFuture($dateString, $timezone = null)
107: {
108: return (new Time($dateString, $timezone))->isFuture();
109: }
110:
111: /**
112: * Returns true, if the given datetime string is in the past.
113: *
114: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
115: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
116: * @return bool True if the given datetime string lies in the past.
117: */
118: public function isPast($dateString, $timezone = null)
119: {
120: return (new Time($dateString, $timezone))->isPast();
121: }
122:
123: /**
124: * Returns true if given datetime string is within this week.
125: *
126: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
127: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
128: * @return bool True if datetime string is within current week
129: */
130: public function isThisWeek($dateString, $timezone = null)
131: {
132: return (new Time($dateString, $timezone))->isThisWeek();
133: }
134:
135: /**
136: * Returns true if given datetime string is within this month
137: *
138: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
139: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
140: * @return bool True if datetime string is within the current month
141: */
142: public function isThisMonth($dateString, $timezone = null)
143: {
144: return (new Time($dateString, $timezone))->isThisMonth();
145: }
146:
147: /**
148: * Returns true if given datetime string is within the current year.
149: *
150: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
151: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
152: * @return bool True if datetime string is within current year
153: */
154: public function isThisYear($dateString, $timezone = null)
155: {
156: return (new Time($dateString, $timezone))->isThisYear();
157: }
158:
159: /**
160: * Returns true if given datetime string was yesterday.
161: *
162: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
163: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
164: * @return bool True if datetime string was yesterday
165: *
166: */
167: public function wasYesterday($dateString, $timezone = null)
168: {
169: return (new Time($dateString, $timezone))->isYesterday();
170: }
171:
172: /**
173: * Returns true if given datetime string is tomorrow.
174: *
175: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
176: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
177: * @return bool True if datetime string was yesterday
178: */
179: public function isTomorrow($dateString, $timezone = null)
180: {
181: return (new Time($dateString, $timezone))->isTomorrow();
182: }
183:
184: /**
185: * Returns the quarter
186: *
187: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
188: * @param bool $range if true returns a range in Y-m-d format
189: * @return int|array 1, 2, 3, or 4 quarter of year or array if $range true
190: * @see \Cake\I18n\Time::toQuarter()
191: */
192: public function toQuarter($dateString, $range = false)
193: {
194: return (new Time($dateString))->toQuarter($range);
195: }
196:
197: /**
198: * Returns a UNIX timestamp from a textual datetime description.
199: *
200: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
201: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
202: * @return string UNIX timestamp
203: * @see \Cake\I18n\Time::toUnix()
204: */
205: public function toUnix($dateString, $timezone = null)
206: {
207: return (new Time($dateString, $timezone))->toUnixString();
208: }
209:
210: /**
211: * Returns a date formatted for Atom RSS feeds.
212: *
213: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
214: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
215: * @return string Formatted date string
216: * @see \Cake\I18n\Time::toAtom()
217: */
218: public function toAtom($dateString, $timezone = null)
219: {
220: $timezone = $this->_getTimezone($timezone) ?: date_default_timezone_get();
221:
222: return (new Time($dateString))->timezone($timezone)->toAtomString();
223: }
224:
225: /**
226: * Formats date for RSS feeds
227: *
228: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
229: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
230: * @return string Formatted date string
231: */
232: public function toRss($dateString, $timezone = null)
233: {
234: $timezone = $this->_getTimezone($timezone) ?: date_default_timezone_get();
235:
236: return (new Time($dateString))->timezone($timezone)->toRssString();
237: }
238:
239: /**
240: * Formats a date into a phrase expressing the relative time.
241: *
242: * ### Additional options
243: *
244: * - `element` - The element to wrap the formatted time in.
245: * Has a few additional options:
246: * - `tag` - The tag to use, defaults to 'span'.
247: * - `class` - The class name to use, defaults to `time-ago-in-words`.
248: * - `title` - Defaults to the $dateTime input.
249: *
250: * @param int|string|\DateTime|\Cake\Chronos\ChronosInterface $dateTime UNIX timestamp, strtotime() valid string or DateTime object
251: * @param array $options Default format if timestamp is used in $dateString
252: * @return string Relative time string.
253: * @see \Cake\I18n\Time::timeAgoInWords()
254: */
255: public function timeAgoInWords($dateTime, array $options = [])
256: {
257: $element = null;
258: $options += [
259: 'element' => null,
260: 'timezone' => null
261: ];
262: $options['timezone'] = $this->_getTimezone($options['timezone']);
263: if ($options['timezone']) {
264: $dateTime = $dateTime->timezone($options['timezone']);
265: unset($options['timezone']);
266: }
267:
268: if (!empty($options['element'])) {
269: $element = [
270: 'tag' => 'span',
271: 'class' => 'time-ago-in-words',
272: 'title' => $dateTime
273: ];
274:
275: if (is_array($options['element'])) {
276: $element = $options['element'] + $element;
277: } else {
278: $element['tag'] = $options['element'];
279: }
280: unset($options['element']);
281: }
282: $relativeDate = (new Time($dateTime))->timeAgoInWords($options);
283:
284: if ($element) {
285: $relativeDate = sprintf(
286: '<%s%s>%s</%s>',
287: $element['tag'],
288: $this->templater()->formatAttributes($element, ['tag']),
289: $relativeDate,
290: $element['tag']
291: );
292: }
293:
294: return $relativeDate;
295: }
296:
297: /**
298: * Returns true if specified datetime was within the interval specified, else false.
299: *
300: * @param string|int $timeInterval the numeric value with space then time type.
301: * Example of valid types: 6 hours, 2 days, 1 minute.
302: * Integer input values are deprecated and support will be removed in 4.0.0
303: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
304: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
305: * @return bool
306: * @see \Cake\I18n\Time::wasWithinLast()
307: */
308: public function wasWithinLast($timeInterval, $dateString, $timezone = null)
309: {
310: return (new Time($dateString, $timezone))->wasWithinLast($timeInterval);
311: }
312:
313: /**
314: * Returns true if specified datetime is within the interval specified, else false.
315: *
316: * @param string|int $timeInterval the numeric value with space then time type.
317: * Example of valid types: 6 hours, 2 days, 1 minute.
318: * Integer input values are deprecated and support will be removed in 4.0.0
319: * @param int|string|\DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
320: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
321: * @return bool
322: * @see \Cake\I18n\Time::wasWithinLast()
323: */
324: public function isWithinNext($timeInterval, $dateString, $timezone = null)
325: {
326: return (new Time($dateString, $timezone))->isWithinNext($timeInterval);
327: }
328:
329: /**
330: * Returns gmt as a UNIX timestamp.
331: *
332: * @param int|string|\DateTime|null $string UNIX timestamp, strtotime() valid string or DateTime object
333: * @return string UNIX timestamp
334: * @see \Cake\I18n\Time::gmt()
335: */
336: public function gmt($string = null)
337: {
338: return (new Time($string))->toUnixString();
339: }
340:
341: /**
342: * Returns a formatted date string, given either a Time instance,
343: * UNIX timestamp or a valid strtotime() date string.
344: *
345: * This method is an alias for TimeHelper::i18nFormat().
346: *
347: * @param int|string|\DateTime $date UNIX timestamp, strtotime() valid string or DateTime object (or a date format string)
348: * @param int|string|null $format date format string (or a UNIX timestamp, strtotime() valid string or DateTime object)
349: * @param bool|string $invalid Default value to display on invalid dates
350: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
351: * @return string Formatted and translated date string
352: * @see \Cake\I18n\Time::i18nFormat()
353: */
354: public function format($date, $format = null, $invalid = false, $timezone = null)
355: {
356: return $this->i18nFormat($date, $format, $invalid, $timezone);
357: }
358:
359: /**
360: * Returns a formatted date string, given either a Datetime instance,
361: * UNIX timestamp or a valid strtotime() date string.
362: *
363: * @param int|string|\DateTime $date UNIX timestamp, strtotime() valid string or DateTime object
364: * @param string|null $format Intl compatible format string.
365: * @param bool|string $invalid Default value to display on invalid dates
366: * @param string|\DateTimeZone|null $timezone User's timezone string or DateTimeZone object
367: * @return string|false Formatted and translated date string or value for `$invalid` on failure.
368: * @throws \Exception When the date cannot be parsed
369: * @see \Cake\I18n\Time::i18nFormat()
370: */
371: public function i18nFormat($date, $format = null, $invalid = false, $timezone = null)
372: {
373: if ($date === null) {
374: return $invalid;
375: }
376: $timezone = $this->_getTimezone($timezone);
377:
378: try {
379: $time = new Time($date);
380:
381: return $time->i18nFormat($format, $timezone);
382: } catch (Exception $e) {
383: if ($invalid === false) {
384: throw $e;
385: }
386:
387: return $invalid;
388: }
389: }
390:
391: /**
392: * Event listeners.
393: *
394: * @return array
395: */
396: public function implementedEvents()
397: {
398: return [];
399: }
400: }
401: