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