CakeTime::toQuarter()   B
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 19
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 15
c 0
b 0
f 0
nc 6
nop 2
dl 0
loc 19
rs 8.8571
1
<?php
2
/**
3
 * CakeTime utility class file.
4
 *
5
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://cakephp.org CakePHP(tm) Project
14
 * @package       Cake.Utility
15
 * @since         CakePHP(tm) v 0.10.0.1076
16
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
17
 */
18
19
App::uses('Multibyte', 'I18n');
20
21
/**
22
 * Time Helper class for easy use of time data.
23
 *
24
 * Manipulation of time data.
25
 *
26
 * @package       Cake.Utility
27
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html
28
 */
29
class CakeTime {
30
31
/**
32
 * The format to use when formatting a time using `CakeTime::nice()`
33
 *
34
 * The format should use the locale strings as defined in the PHP docs under
35
 * `strftime` (http://php.net/manual/en/function.strftime.php)
36
 *
37
 * @var string
38
 * @see CakeTime::format()
39
 */
40
	public static $niceFormat = '%a, %b %eS %Y, %H:%M';
41
42
/**
43
 * The format to use when formatting a time using `CakeTime::timeAgoInWords()`
44
 * and the difference is more than `CakeTime::$wordEnd`
45
 *
46
 * @var string
47
 * @see CakeTime::timeAgoInWords()
48
 */
49
	public static $wordFormat = 'j/n/y';
50
51
/**
52
 * The format to use when formatting a time using `CakeTime::niceShort()`
53
 * and the difference is between 3 and 7 days
54
 *
55
 * @var string
56
 * @see CakeTime::niceShort()
57
 */
58
	public static $niceShortFormat = '%B %d, %H:%M';
59
60
/**
61
 * The format to use when formatting a time using `CakeTime::timeAgoInWords()`
62
 * and the difference is less than `CakeTime::$wordEnd`
63
 *
64
 * @var array
65
 * @see CakeTime::timeAgoInWords()
66
 */
67
	public static $wordAccuracy = array(
68
		'year' => "day",
69
		'month' => "day",
70
		'week' => "day",
71
		'day' => "hour",
72
		'hour' => "minute",
73
		'minute' => "minute",
74
		'second' => "second",
75
	);
76
77
/**
78
 * The end of relative time telling
79
 *
80
 * @var string
81
 * @see CakeTime::timeAgoInWords()
82
 */
83
	public static $wordEnd = '+1 month';
84
85
/**
86
 * Temporary variable containing the timestamp value, used internally in convertSpecifiers()
87
 *
88
 * @var integer
89
 */
90
	protected static $_time = null;
91
92
/**
93
 * Magic set method for backwards compatibility.
94
 * Used by TimeHelper to modify static variables in CakeTime
95
 *
96
 * @param string $name Variable name
97
 * @param mixes $value Variable value
98
 * @return void
99
 */
100
	public function __set($name, $value) {
101
		switch ($name) {
102
			case 'niceFormat':
103
				self::${$name} = $value;
104
				break;
105
		}
106
	}
107
108
/**
109
 * Magic set method for backwards compatibility.
110
 * Used by TimeHelper to get static variables in CakeTime
111
 *
112
 * @param string $name Variable name
113
 * @return mixed
114
 */
115
	public function __get($name) {
116
		switch ($name) {
117
			case 'niceFormat':
118
				return self::${$name};
119
			default:
120
				return null;
121
		}
122
	}
123
124
/**
125
 * Converts a string representing the format for the function strftime and returns a
126
 * windows safe and i18n aware format.
127
 *
128
 * @param string $format Format with specifiers for strftime function.
129
 *    Accepts the special specifier %S which mimics the modifier S for date()
130
 * @param string $time UNIX timestamp
131
 * @return string windows safe and date() function compatible format for strftime
132
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::convertSpecifiers
133
 */
134
	public static function convertSpecifiers($format, $time = null) {
135
		if (!$time) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $time of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
136
			$time = time();
137
		}
138
		self::$_time = $time;
0 ignored issues
show
Documentation Bug introduced by
It seems like $time can also be of type string. However, the property $_time is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
139
		return preg_replace_callback('/\%(\w+)/', array('CakeTime', '_translateSpecifier'), $format);
140
	}
141
142
/**
143
 * Auxiliary function to translate a matched specifier element from a regular expression into
144
 * a windows safe and i18n aware specifier
145
 *
146
 * @param array $specifier match from regular expression
147
 * @return string converted element
148
 */
149
	protected static function _translateSpecifier($specifier) {
150
		switch ($specifier[1]) {
151 View Code Duplication
			case 'a':
152
				$abday = __dc('cake', 'abday', 5);
153
				if (is_array($abday)) {
154
					return $abday[date('w', self::$_time)];
155
				}
156
				break;
157 View Code Duplication
			case 'A':
158
				$day = __dc('cake', 'day', 5);
159
				if (is_array($day)) {
160
					return $day[date('w', self::$_time)];
161
				}
162
				break;
163
			case 'c':
164
				$format = __dc('cake', 'd_t_fmt', 5);
165
				if ($format !== 'd_t_fmt') {
166
					return self::convertSpecifiers($format, self::$_time);
167
				}
168
				break;
169
			case 'C':
170
				return sprintf("%02d", date('Y', self::$_time) / 100);
171
			case 'D':
172
				return '%m/%d/%y';
173
			case 'e':
174
				if (DS === '/') {
175
					return '%e';
176
				}
177
				$day = date('j', self::$_time);
178
				if ($day < 10) {
179
					$day = ' ' . $day;
180
				}
181
				return $day;
182
			case 'eS' :
183
				return date('jS', self::$_time);
184
			case 'b':
185 View Code Duplication
			case 'h':
186
				$months = __dc('cake', 'abmon', 5);
187
				if (is_array($months)) {
188
					return $months[date('n', self::$_time) - 1];
189
				}
190
				return '%b';
191 View Code Duplication
			case 'B':
192
				$months = __dc('cake', 'mon', 5);
193
				if (is_array($months)) {
194
					return $months[date('n', self::$_time) - 1];
195
				}
196
				break;
197
			case 'n':
198
				return "\n";
199
			case 'p':
200
			case 'P':
201
				$default = array('am' => 0, 'pm' => 1);
202
				$meridiem = $default[date('a', self::$_time)];
203
				$format = __dc('cake', 'am_pm', 5);
204
				if (is_array($format)) {
205
					$meridiem = $format[$meridiem];
206
					return ($specifier[1] === 'P') ? strtolower($meridiem) : strtoupper($meridiem);
207
				}
208
				break;
209
			case 'r':
210
				$complete = __dc('cake', 't_fmt_ampm', 5);
211
				if ($complete !== 't_fmt_ampm') {
212
					return str_replace('%p', self::_translateSpecifier(array('%p', 'p')), $complete);
213
				}
214
				break;
215
			case 'R':
216
				return date('H:i', self::$_time);
217
			case 't':
218
				return "\t";
219
			case 'T':
220
				return '%H:%M:%S';
221
			case 'u':
222
				return ($weekDay = date('w', self::$_time)) ? $weekDay : 7;
223
			case 'x':
224
				$format = __dc('cake', 'd_fmt', 5);
225
				if ($format !== 'd_fmt') {
226
					return self::convertSpecifiers($format, self::$_time);
227
				}
228
				break;
229
			case 'X':
230
				$format = __dc('cake', 't_fmt', 5);
231
				if ($format !== 't_fmt') {
232
					return self::convertSpecifiers($format, self::$_time);
233
				}
234
				break;
235
		}
236
		return $specifier[0];
237
	}
238
239
/**
240
 * Converts given time (in server's time zone) to user's local time, given his/her timezone.
241
 *
242
 * @param string $serverTime UNIX timestamp
243
 * @param string|DateTimeZone $timezone User's timezone string or DateTimeZone object
244
 * @return integer UNIX timestamp
245
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::convert
246
 */
247
	public static function convert($serverTime, $timezone) {
248
		static $serverTimezone = null;
249
		if ($serverTimezone === null || (date_default_timezone_get() !== $serverTimezone->getName())) {
0 ignored issues
show
Bug introduced by
The method getName cannot be called on $serverTimezone (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
250
			$serverTimezone = new DateTimeZone(date_default_timezone_get());
251
		}
252
		$serverOffset = $serverTimezone->getOffset(new DateTime('@' . $serverTime));
253
		$gmtTime = $serverTime - $serverOffset;
254
		if (is_numeric($timezone)) {
255
			$userOffset = $timezone * (60 * 60);
256
		} else {
257
			$timezone = self::timezone($timezone);
258
			$userOffset = $timezone->getOffset(new DateTime('@' . $gmtTime));
259
		}
260
		$userTime = $gmtTime + $userOffset;
261
		return (int)$userTime;
262
	}
263
264
/**
265
 * Returns a timezone object from a string or the user's timezone object
266
 *
267
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
268
 * 	If null it tries to get timezone from 'Config.timezone' config var
269
 * @return DateTimeZone Timezone object
270
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::timezone
271
 */
272
	public static function timezone($timezone = null) {
273
		static $tz = null;
274
275
		if (is_object($timezone)) {
276
			if ($tz === null || $tz->getName() !== $timezone->getName()) {
0 ignored issues
show
Bug introduced by
The method getName cannot be called on $tz (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
277
				$tz = $timezone;
278
			}
279
		} else {
280
			if ($timezone === null) {
281
				$timezone = Configure::read('Config.timezone');
282
				if ($timezone === null) {
283
					$timezone = date_default_timezone_get();
284
				}
285
			}
286
287
			if ($tz === null || $tz->getName() !== $timezone) {
0 ignored issues
show
Bug introduced by
The method getName cannot be called on $tz (of type null).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
288
				$tz = new DateTimeZone($timezone);
289
			}
290
		}
291
292
		return $tz;
293
	}
294
295
/**
296
 * Returns server's offset from GMT in seconds.
297
 *
298
 * @return integer Offset
299
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::serverOffset
300
 */
301
	public static function serverOffset() {
302
		return date('Z', time());
303
	}
304
305
/**
306
 * Returns a UNIX timestamp, given either a UNIX timestamp or a valid strtotime() date string.
307
 *
308
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
309
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
310
 * @return string Parsed timestamp
311
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::fromString
312
 */
313
	public static function fromString($dateString, $timezone = null) {
314
		if (empty($dateString)) {
315
			return false;
316
		}
317
318
		$containsDummyDate = (is_string($dateString) && substr($dateString, 0, 10) === '0000-00-00');
319
		if ($containsDummyDate) {
320
			return false;
321
		}
322
323
		if (is_int($dateString) || is_numeric($dateString)) {
324
			$date = intval($dateString);
325
		} elseif (
326
			$dateString instanceof DateTime &&
327
			$dateString->getTimezone()->getName() != date_default_timezone_get()
328
		) {
329
			$clone = clone $dateString;
330
			$clone->setTimezone(new DateTimeZone(date_default_timezone_get()));
331
			$date = (int)$clone->format('U') + $clone->getOffset();
332
		} elseif ($dateString instanceof DateTime) {
333
			$date = (int)$dateString->format('U');
334
		} else {
335
			$date = strtotime($dateString);
336
		}
337
338
		if ($date === -1 || empty($date)) {
339
			return false;
340
		}
341
342
		if ($timezone === null) {
343
			$timezone = Configure::read('Config.timezone');
344
		}
345
346
		if ($timezone !== null) {
347
			return self::convert($date, $timezone);
348
		}
349
		return $date;
350
	}
351
352
/**
353
 * Returns a nicely formatted date string for given Datetime string.
354
 *
355
 * See http://php.net/manual/en/function.strftime.php for information on formatting
356
 * using locale strings.
357
 *
358
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
359
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
360
 * @param string $format The format to use. If null, `TimeHelper::$niceFormat` is used
361
 * @return string Formatted date string
362
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::nice
363
 */
364
	public static function nice($dateString = null, $timezone = null, $format = null) {
365
		if (!$dateString) {
366
			$dateString = time();
367
		}
368
		$date = self::fromString($dateString, $timezone);
369
370
		if (!$format) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $format of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
371
			$format = self::$niceFormat;
372
		}
373
		return self::_strftime(self::convertSpecifiers($format, $date), $date);
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 368 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
374
	}
375
376
/**
377
 * Returns a formatted descriptive date string for given datetime string.
378
 *
379
 * If the given date is today, the returned string could be "Today, 16:54".
380
 * If the given date is tomorrow, the returned string could be "Tomorrow, 16:54".
381
 * If the given date was yesterday, the returned string could be "Yesterday, 16:54".
382
 * If the given date is within next or last week, the returned string could be "On Thursday, 16:54".
383
 * If $dateString's year is the current year, the returned string does not
384
 * include mention of the year.
385
 *
386
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
387
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
388
 * @return string Described, relative date string
389
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::niceShort
390
 */
391
	public static function niceShort($dateString = null, $timezone = null) {
392
		if (!$dateString) {
393
			$dateString = time();
394
		}
395
		$date = self::fromString($dateString, $timezone);
396
397
		if (self::isToday($dateString, $timezone)) {
398
			return __d('cake', 'Today, %s', self::_strftime("%H:%M", $date));
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 395 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
399
		}
400
		if (self::wasYesterday($dateString, $timezone)) {
401
			return __d('cake', 'Yesterday, %s', self::_strftime("%H:%M", $date));
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 395 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
402
		}
403
		if (self::isTomorrow($dateString, $timezone)) {
404
			return __d('cake', 'Tomorrow, %s', self::_strftime("%H:%M", $date));
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 395 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
405
		}
406
407
		$d = self::_strftime("%w", $date);
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 395 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
408
		$day = array(
409
			__d('cake', 'Sunday'),
410
			__d('cake', 'Monday'),
411
			__d('cake', 'Tuesday'),
412
			__d('cake', 'Wednesday'),
413
			__d('cake', 'Thursday'),
414
			__d('cake', 'Friday'),
415
			__d('cake', 'Saturday')
416
		);
417 View Code Duplication
		if (self::wasWithinLast('7 days', $dateString, $timezone)) {
418
			return sprintf('%s %s', $day[$d], self::_strftime(self::$niceShortFormat, $date));
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 395 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
419
		}
420 View Code Duplication
		if (self::isWithinNext('7 days', $dateString, $timezone)) {
421
			return __d('cake', 'On %s %s', $day[$d], self::_strftime(self::$niceShortFormat, $date));
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 395 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
422
		}
423
424
		$y = '';
425
		if (!self::isThisYear($date)) {
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 395 can also be of type false; however, CakeTime::isThisYear() does only seem to accept integer|string|object<DateTime>, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
426
			$y = ' %Y';
427
		}
428
		return self::_strftime(self::convertSpecifiers("%b %eS{$y}, %H:%M", $date), $date);
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($dateString, $timezone) on line 395 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
429
	}
430
431
/**
432
 * Returns a partial SQL string to search for all records between two dates.
433
 *
434
 * @param integer|string|DateTime $begin UNIX timestamp, strtotime() valid string or DateTime object
435
 * @param integer|string|DateTime $end UNIX timestamp, strtotime() valid string or DateTime object
436
 * @param string $fieldName Name of database field to compare with
437
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
438
 * @return string Partial SQL string.
439
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::daysAsSql
440
 */
441
	public static function daysAsSql($begin, $end, $fieldName, $timezone = null) {
442
		$begin = self::fromString($begin, $timezone);
443
		$end = self::fromString($end, $timezone);
444
		$begin = date('Y-m-d', $begin) . ' 00:00:00';
445
		$end = date('Y-m-d', $end) . ' 23:59:59';
446
447
		return "($fieldName >= '$begin') AND ($fieldName <= '$end')";
448
	}
449
450
/**
451
 * Returns a partial SQL string to search for all records between two times
452
 * occurring on the same day.
453
 *
454
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
455
 * @param string $fieldName Name of database field to compare with
456
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
457
 * @return string Partial SQL string.
458
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::dayAsSql
459
 */
460
	public static function dayAsSql($dateString, $fieldName, $timezone = null) {
461
		return self::daysAsSql($dateString, $dateString, $fieldName, $timezone);
462
	}
463
464
/**
465
 * Returns true if given datetime string is today.
466
 *
467
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
468
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
469
 * @return boolean True if datetime string is today
470
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::isToday
471
 */
472
	public static function isToday($dateString, $timezone = null) {
473
		$timestamp = self::fromString($dateString, $timezone);
474
		$now = self::fromString('now', $timezone);
475
		return date('Y-m-d', $timestamp) === date('Y-m-d', $now);
476
	}
477
478
/**
479
 * Returns true if given datetime string is in the future.
480
 *
481
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
482
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
483
 * @return boolean True if datetime string is in the future
484
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::isFuture
485
 */
486
	public static function isFuture($dateString, $timezone = null) {
487
		$timestamp = self::fromString($dateString, $timezone);
488
		return $timestamp > time();
489
	}
490
491
/**
492
 * Returns true if given datetime string is in the past.
493
 *
494
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
495
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
496
 * @return boolean True if datetime string is in the past
497
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::isPast
498
 */
499
	public static function isPast($dateString, $timezone = null) {
500
		$timestamp = self::fromString($dateString, $timezone);
501
		return $timestamp < time();
502
	}
503
504
/**
505
 * Returns true if given datetime string is within this week.
506
 *
507
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
508
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
509
 * @return boolean True if datetime string is within current week
510
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::isThisWeek
511
 */
512
	public static function isThisWeek($dateString, $timezone = null) {
513
		$timestamp = self::fromString($dateString, $timezone);
514
		$now = self::fromString('now', $timezone);
515
		return date('W o', $timestamp) === date('W o', $now);
516
	}
517
518
/**
519
 * Returns true if given datetime string is within this month
520
 *
521
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
522
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
523
 * @return boolean True if datetime string is within current month
524
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::isThisMonth
525
 */
526
	public static function isThisMonth($dateString, $timezone = null) {
527
		$timestamp = self::fromString($dateString, $timezone);
528
		$now = self::fromString('now', $timezone);
529
		return date('m Y', $timestamp) === date('m Y', $now);
530
	}
531
532
/**
533
 * Returns true if given datetime string is within current year.
534
 *
535
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
536
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
537
 * @return boolean True if datetime string is within current year
538
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::isThisYear
539
 */
540
	public static function isThisYear($dateString, $timezone = null) {
541
		$timestamp = self::fromString($dateString, $timezone);
542
		$now = self::fromString('now', $timezone);
543
		return date('Y', $timestamp) === date('Y', $now);
544
	}
545
546
/**
547
 * Returns true if given datetime string was yesterday.
548
 *
549
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
550
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
551
 * @return boolean True if datetime string was yesterday
552
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::wasYesterday
553
 */
554
	public static function wasYesterday($dateString, $timezone = null) {
555
		$timestamp = self::fromString($dateString, $timezone);
556
		$yesterday = self::fromString('yesterday', $timezone);
557
		return date('Y-m-d', $timestamp) === date('Y-m-d', $yesterday);
558
	}
559
560
/**
561
 * Returns true if given datetime string is tomorrow.
562
 *
563
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
564
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
565
 * @return boolean True if datetime string was yesterday
566
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::isTomorrow
567
 */
568
	public static function isTomorrow($dateString, $timezone = null) {
569
		$timestamp = self::fromString($dateString, $timezone);
570
		$tomorrow = self::fromString('tomorrow', $timezone);
571
		return date('Y-m-d', $timestamp) === date('Y-m-d', $tomorrow);
572
	}
573
574
/**
575
 * Returns the quarter
576
 *
577
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
578
 * @param boolean $range if true returns a range in Y-m-d format
579
 * @return mixed 1, 2, 3, or 4 quarter of year or array if $range true
580
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::toQuarter
581
 */
582
	public static function toQuarter($dateString, $range = false) {
583
		$time = self::fromString($dateString);
584
		$date = ceil(date('m', $time) / 3);
585
		if ($range === false) {
586
			return $date;
587
		}
588
589
		$year = date('Y', $time);
590
		switch ($date) {
591
			case 1:
592
				return array($year . '-01-01', $year . '-03-31');
593
			case 2:
594
				return array($year . '-04-01', $year . '-06-30');
595
			case 3:
596
				return array($year . '-07-01', $year . '-09-30');
597
			case 4:
598
				return array($year . '-10-01', $year . '-12-31');
599
		}
600
	}
601
602
/**
603
 * Returns a UNIX timestamp from a textual datetime description. Wrapper for PHP function strtotime().
604
 *
605
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
606
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
607
 * @return integer Unix timestamp
608
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::toUnix
609
 */
610
	public static function toUnix($dateString, $timezone = null) {
611
		return self::fromString($dateString, $timezone);
612
	}
613
614
/**
615
 * Returns a formatted date in server's timezone.
616
 *
617
 * If a DateTime object is given or the dateString has a timezone
618
 * segment, the timezone parameter will be ignored.
619
 *
620
 * If no timezone parameter is given and no DateTime object, the passed $dateString will be
621
 * considered to be in the UTC timezone.
622
 *
623
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
624
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
625
 * @param string $format date format string
626
 * @return mixed Formatted date
627
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::toServer
628
 */
629
	public static function toServer($dateString, $timezone = null, $format = 'Y-m-d H:i:s') {
630
		if ($timezone === null) {
631
			$timezone = new DateTimeZone('UTC');
632
		} elseif (is_string($timezone)) {
633
			$timezone = new DateTimeZone($timezone);
634
		} elseif (!($timezone instanceof DateTimeZone)) {
635
			return false;
636
		}
637
638
		if ($dateString instanceof DateTime) {
639
			$date = $dateString;
640
		} elseif (is_int($dateString) || is_numeric($dateString)) {
641
			$dateString = (int)$dateString;
642
643
			$date = new DateTime('@' . $dateString);
644
			$date->setTimezone($timezone);
645
		} else {
646
			$date = new DateTime($dateString, $timezone);
647
		}
648
649
		$date->setTimezone(new DateTimeZone(date_default_timezone_get()));
650
		return $date->format($format);
651
	}
652
653
/**
654
 * Returns a date formatted for Atom RSS feeds.
655
 *
656
 * @param string $dateString Datetime string or Unix timestamp
657
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
658
 * @return string Formatted date string
659
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::toAtom
660
 */
661
	public static function toAtom($dateString, $timezone = null) {
662
		return date('Y-m-d\TH:i:s\Z', self::fromString($dateString, $timezone));
663
	}
664
665
/**
666
 * Formats date for RSS feeds
667
 *
668
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
669
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
670
 * @return string Formatted date string
671
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::toRSS
672
 */
673
	public static function toRSS($dateString, $timezone = null) {
674
		$date = self::fromString($dateString, $timezone);
675
676
		if ($timezone === null) {
677
			return date("r", $date);
678
		}
679
680
		$userOffset = $timezone;
681
		if (!is_numeric($timezone)) {
682
			if (!is_object($timezone)) {
683
				$timezone = new DateTimeZone($timezone);
684
			}
685
			$currentDate = new DateTime('@' . $date);
686
			$currentDate->setTimezone($timezone);
687
			$userOffset = $timezone->getOffset($currentDate) / 60 / 60;
688
		}
689
690
		$timezone = '+0000';
691
		if ($userOffset != 0) {
692
			$hours = (int)floor(abs($userOffset));
693
			$minutes = (int)(fmod(abs($userOffset), $hours) * 60);
694
			$timezone = ($userOffset < 0 ? '-' : '+') . str_pad($hours, 2, '0', STR_PAD_LEFT) . str_pad($minutes, 2, '0', STR_PAD_LEFT);
695
		}
696
		return date('D, d M Y H:i:s', $date) . ' ' . $timezone;
697
	}
698
699
/**
700
 * Returns either a relative or a formatted absolute date depending
701
 * on the difference between the current time and given datetime.
702
 * $datetime should be in a *strtotime* - parsable format, like MySQL's datetime datatype.
703
 *
704
 * ### Options:
705
 *
706
 * - `format` => a fall back format if the relative time is longer than the duration specified by end
707
 * - `accuracy` => Specifies how accurate the date should be described (array)
708
 *    - year =>   The format if years > 0   (default "day")
709
 *    - month =>  The format if months > 0  (default "day")
710
 *    - week =>   The format if weeks > 0   (default "day")
711
 *    - day =>    The format if weeks > 0   (default "hour")
712
 *    - hour =>   The format if hours > 0   (default "minute")
713
 *    - minute => The format if minutes > 0 (default "minute")
714
 *    - second => The format if seconds > 0 (default "second")
715
 * - `end` => The end of relative time telling
716
 * - `relativeString` => The printf compatible string when outputting relative time
717
 * - `absoluteString` => The printf compatible string when outputting absolute time
718
 * - `userOffset` => Users offset from GMT (in hours) *Deprecated* use timezone intead.
719
 * - `timezone` => The user timezone the timestamp should be formatted in.
720
 *
721
 * Relative dates look something like this:
722
 *
723
 * - 3 weeks, 4 days ago
724
 * - 15 seconds ago
725
 *
726
 * Default date formatting is d/m/yy e.g: on 18/2/09
727
 *
728
 * The returned string includes 'ago' or 'on' and assumes you'll properly add a word
729
 * like 'Posted ' before the function output.
730
 *
731
 * NOTE: If the difference is one week or more, the lowest level of accuracy is day
732
 *
733
 * @param integer|string|DateTime $dateTime Datetime UNIX timestamp, strtotime() valid string or DateTime object
734
 * @param array $options Default format if timestamp is used in $dateString
735
 * @return string Relative time string.
736
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::timeAgoInWords
737
 */
738
	public static function timeAgoInWords($dateTime, $options = array()) {
739
		$timezone = null;
740
		$format = self::$wordFormat;
741
		$end = self::$wordEnd;
742
		$relativeString = __d('cake', '%s ago');
743
		$absoluteString = __d('cake', 'on %s');
744
		$accuracy = self::$wordAccuracy;
745
746
		if (is_array($options)) {
747
			if (isset($options['timezone'])) {
748
				$timezone = $options['timezone'];
749
			} elseif (isset($options['userOffset'])) {
750
				$timezone = $options['userOffset'];
751
			}
752
753
			if (isset($options['accuracy'])) {
754
				if (is_array($options['accuracy'])) {
755
					$accuracy = array_merge($accuracy, $options['accuracy']);
756
				} else {
757
					foreach ($accuracy as $key => $level) {
758
						$accuracy[$key] = $options['accuracy'];
759
					}
760
				}
761
			}
762
763
			if (isset($options['format'])) {
764
				$format = $options['format'];
765
			}
766
			if (isset($options['end'])) {
767
				$end = $options['end'];
768
			}
769
			if (isset($options['relativeString'])) {
770
				$relativeString = $options['relativeString'];
771
				unset($options['relativeString']);
772
			}
773
			if (isset($options['absoluteString'])) {
774
				$absoluteString = $options['absoluteString'];
775
				unset($options['absoluteString']);
776
			}
777
			unset($options['end'], $options['format']);
778
		} else {
779
			$format = $options;
780
		}
781
782
		$now = self::fromString(time(), $timezone);
783
		$inSeconds = self::fromString($dateTime, $timezone);
784
		$backwards = ($inSeconds > $now);
785
786
		$futureTime = $now;
787
		$pastTime = $inSeconds;
788
		if ($backwards) {
789
			$futureTime = $inSeconds;
790
			$pastTime = $now;
791
		}
792
		$diff = $futureTime - $pastTime;
793
794
		if (!$diff) {
795
			return __d('cake', 'just now', 'just now');
796
		}
797
798
		if ($diff > abs($now - self::fromString($end))) {
0 ignored issues
show
Bug introduced by
It seems like $end defined by $options['end'] on line 767 can also be of type array; however, CakeTime::fromString() does only seem to accept integer|string|object<DateTime>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
799
			return sprintf($absoluteString, date($format, $inSeconds));
800
		}
801
802
		// If more than a week, then take into account the length of months
803
		if ($diff >= 604800) {
804
			list($future['H'], $future['i'], $future['s'], $future['d'], $future['m'], $future['Y']) = explode('/', date('H/i/s/d/m/Y', $futureTime));
805
806
			list($past['H'], $past['i'], $past['s'], $past['d'], $past['m'], $past['Y']) = explode('/', date('H/i/s/d/m/Y', $pastTime));
807
			$years = $months = $weeks = $days = $hours = $minutes = $seconds = 0;
808
809
			$years = $future['Y'] - $past['Y'];
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
Bug introduced by
The variable $past does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
810
			$months = $future['m'] + ((12 * $years) - $past['m']);
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
811
812
			if ($months >= 12) {
813
				$years = floor($months / 12);
814
				$months = $months - ($years * 12);
815
			}
816
			if ($future['m'] < $past['m'] && $future['Y'] - $past['Y'] === 1) {
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
817
				$years--;
818
			}
819
820
			if ($future['d'] >= $past['d']) {
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
821
				$days = $future['d'] - $past['d'];
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
822
			} else {
823
				$daysInPastMonth = date('t', $pastTime);
824
				$daysInFutureMonth = date('t', mktime(0, 0, 0, $future['m'] - 1, 1, $future['Y']));
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
825
826
				if (!$backwards) {
827
					$days = ($daysInPastMonth - $past['d']) + $future['d'];
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
828
				} else {
829
					$days = ($daysInFutureMonth - $past['d']) + $future['d'];
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
830
				}
831
832
				if ($future['m'] != $past['m']) {
0 ignored issues
show
Bug introduced by
The variable $future does not exist. Did you mean $futureTime?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
833
					$months--;
834
				}
835
			}
836
837
			if (!$months && $years >= 1 && $diff < ($years * 31536000)) {
838
				$months = 11;
839
				$years--;
840
			}
841
842
			if ($months >= 12) {
843
				$years = $years + 1;
844
				$months = $months - 12;
845
			}
846
847
			if ($days >= 7) {
848
				$weeks = floor($days / 7);
849
				$days = $days - ($weeks * 7);
850
			}
851
		} else {
852
			$years = $months = $weeks = 0;
853
			$days = floor($diff / 86400);
854
855
			$diff = $diff - ($days * 86400);
856
857
			$hours = floor($diff / 3600);
858
			$diff = $diff - ($hours * 3600);
859
860
			$minutes = floor($diff / 60);
861
			$diff = $diff - ($minutes * 60);
862
			$seconds = $diff;
863
		}
864
865
		$fWord = $accuracy['second'];
866
		if ($years > 0) {
867
			$fWord = $accuracy['year'];
868
		} elseif (abs($months) > 0) {
869
			$fWord = $accuracy['month'];
870
		} elseif (abs($weeks) > 0) {
871
			$fWord = $accuracy['week'];
872
		} elseif (abs($days) > 0) {
873
			$fWord = $accuracy['day'];
874
		} elseif (abs($hours) > 0) {
875
			$fWord = $accuracy['hour'];
876
		} elseif (abs($minutes) > 0) {
877
			$fWord = $accuracy['minute'];
878
		}
879
880
		$fNum = str_replace(array('year', 'month', 'week', 'day', 'hour', 'minute', 'second'), array(1, 2, 3, 4, 5, 6, 7), $fWord);
881
882
		$relativeDate = '';
883
		if ($fNum >= 1 && $years > 0) {
884
			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d year', '%d years', $years, $years);
885
		}
886
		if ($fNum >= 2 && $months > 0) {
887
			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d month', '%d months', $months, $months);
888
		}
889
		if ($fNum >= 3 && $weeks > 0) {
890
			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d week', '%d weeks', $weeks, $weeks);
891
		}
892 View Code Duplication
		if ($fNum >= 4 && $days > 0) {
893
			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d day', '%d days', $days, $days);
894
		}
895
		if ($fNum >= 5 && $hours > 0) {
896
			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d hour', '%d hours', $hours, $hours);
897
		}
898
		if ($fNum >= 6 && $minutes > 0) {
899
			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d minute', '%d minutes', $minutes, $minutes);
900
		}
901 View Code Duplication
		if ($fNum >= 7 && $seconds > 0) {
902
			$relativeDate .= ($relativeDate ? ', ' : '') . __dn('cake', '%d second', '%d seconds', $seconds, $seconds);
903
		}
904
905
		// When time has passed
906
		if (!$backwards && $relativeDate) {
907
			return sprintf($relativeString, $relativeDate);
908
		}
909 View Code Duplication
		if (!$backwards) {
910
			$aboutAgo = array(
911
				'second' => __d('cake', 'about a second ago'),
912
				'minute' => __d('cake', 'about a minute ago'),
913
				'hour' => __d('cake', 'about an hour ago'),
914
				'day' => __d('cake', 'about a day ago'),
915
				'week' => __d('cake', 'about a week ago'),
916
				'year' => __d('cake', 'about a year ago')
917
			);
918
919
			return $aboutAgo[$fWord];
920
		}
921
922
		// When time is to come
923 View Code Duplication
		if (!$relativeDate) {
924
			$aboutIn = array(
925
				'second' => __d('cake', 'in about a second'),
926
				'minute' => __d('cake', 'in about a minute'),
927
				'hour' => __d('cake', 'in about an hour'),
928
				'day' => __d('cake', 'in about a day'),
929
				'week' => __d('cake', 'in about a week'),
930
				'year' => __d('cake', 'in about a year')
931
			);
932
933
			return $aboutIn[$fWord];
934
		}
935
936
		return $relativeDate;
937
	}
938
939
/**
940
 * Returns true if specified datetime was within the interval specified, else false.
941
 *
942
 * @param string|integer $timeInterval the numeric value with space then time type.
943
 *    Example of valid types: 6 hours, 2 days, 1 minute.
944
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
945
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
946
 * @return boolean
947
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::wasWithinLast
948
 */
949 View Code Duplication
	public static function wasWithinLast($timeInterval, $dateString, $timezone = null) {
950
		$tmp = str_replace(' ', '', $timeInterval);
951
		if (is_numeric($tmp)) {
952
			$timeInterval = $tmp . ' ' . __d('cake', 'days');
953
		}
954
955
		$date = self::fromString($dateString, $timezone);
956
		$interval = self::fromString('-' . $timeInterval);
957
		$now = self::fromString('now', $timezone);
958
959
		return $date >= $interval && $date <= $now;
960
	}
961
962
/**
963
 * Returns true if specified datetime is within the interval specified, else false.
964
 *
965
 * @param string|integer $timeInterval the numeric value with space then time type.
966
 *    Example of valid types: 6 hours, 2 days, 1 minute.
967
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
968
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
969
 * @return boolean
970
 */
971 View Code Duplication
	public static function isWithinNext($timeInterval, $dateString, $timezone = null) {
972
		$tmp = str_replace(' ', '', $timeInterval);
973
		if (is_numeric($tmp)) {
974
			$timeInterval = $tmp . ' ' . __d('cake', 'days');
975
		}
976
977
		$date = self::fromString($dateString, $timezone);
978
		$interval = self::fromString('+' . $timeInterval);
979
		$now = self::fromString('now', $timezone);
980
981
		return $date <= $interval && $date >= $now;
982
	}
983
984
/**
985
 * Returns gmt as a UNIX timestamp.
986
 *
987
 * @param integer|string|DateTime $dateString UNIX timestamp, strtotime() valid string or DateTime object
988
 * @return integer UNIX timestamp
989
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::gmt
990
 */
991
	public static function gmt($dateString = null) {
992
		$time = time();
993
		if ($dateString) {
994
			$time = self::fromString($dateString);
995
		}
996
		return gmmktime(
997
			intval(date('G', $time)),
998
			intval(date('i', $time)),
999
			intval(date('s', $time)),
1000
			intval(date('n', $time)),
1001
			intval(date('j', $time)),
1002
			intval(date('Y', $time))
1003
		);
1004
	}
1005
1006
/**
1007
 * Returns a formatted date string, given either a UNIX timestamp or a valid strtotime() date string.
1008
 * This function also accepts a time string and a format string as first and second parameters.
1009
 * In that case this function behaves as a wrapper for TimeHelper::i18nFormat()
1010
 *
1011
 * ## Examples
1012
 *
1013
 * Create localized & formatted time:
1014
 *
1015
 * {{{
1016
 *   CakeTime::format('2012-02-15', '%m-%d-%Y'); // returns 02-15-2012
1017
 *   CakeTime::format('2012-02-15 23:01:01', '%c'); // returns preferred date and time based on configured locale
1018
 *   CakeTime::format('0000-00-00', '%d-%m-%Y', 'N/A'); // return N/A becuase an invalid date was passed
1019
 *   CakeTime::format('2012-02-15 23:01:01', '%c', 'N/A', 'America/New_York'); // converts passed date to timezone
1020
 * }}}
1021
 *
1022
 * @param integer|string|DateTime $date UNIX timestamp, strtotime() valid string or DateTime object (or a date format string)
1023
 * @param integer|string|DateTime $format date format string (or UNIX timestamp, strtotime() valid string or DateTime object)
1024
 * @param boolean|string $default if an invalid date is passed it will output supplied default value. Pass false if you want raw conversion value
1025
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
1026
 * @return string Formatted date string
1027
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::format
1028
 * @see CakeTime::i18nFormat()
1029
 */
1030
	public static function format($date, $format = null, $default = false, $timezone = null) {
1031
		//Backwards compatible params re-order test
1032
		$time = self::fromString($format, $timezone);
1033
1034
		if ($time === false) {
1035
			return self::i18nFormat($date, $format, $default, $timezone);
1036
		}
1037
		return date($date, $time);
1038
	}
1039
1040
/**
1041
 * Returns a formatted date string, given either a UNIX timestamp or a valid strtotime() date string.
1042
 * It takes into account the default date format for the current language if a LC_TIME file is used.
1043
 *
1044
 * @param integer|string|DateTime $date UNIX timestamp, strtotime() valid string or DateTime object
1045
 * @param string $format strftime format string.
1046
 * @param boolean|string $default if an invalid date is passed it will output supplied default value. Pass false if you want raw conversion value
1047
 * @param string|DateTimeZone $timezone Timezone string or DateTimeZone object
1048
 * @return string Formatted and translated date string
1049
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::i18nFormat
1050
 */
1051
	public static function i18nFormat($date, $format = null, $default = false, $timezone = null) {
1052
		$date = self::fromString($date, $timezone);
1053
		if ($date === false && $default !== false) {
1054
			return $default;
1055
		}
1056
		if (empty($format)) {
1057
			$format = '%x';
1058
		}
1059
		return self::_strftime(self::convertSpecifiers($format, $date), $date);
0 ignored issues
show
Security Bug introduced by
It seems like $date defined by self::fromString($date, $timezone) on line 1052 can also be of type false; however, CakeTime::_strftime() does only seem to accept integer, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
1060
	}
1061
1062
/**
1063
 * Get list of timezone identifiers
1064
 *
1065
 * @param integer|string $filter A regex to filter identifer
1066
 * 	Or one of DateTimeZone class constants (PHP 5.3 and above)
1067
 * @param string $country A two-letter ISO 3166-1 compatible country code.
1068
 * 	This option is only used when $filter is set to DateTimeZone::PER_COUNTRY (available only in PHP 5.3 and above)
1069
 * @param boolean $group If true (default value) groups the identifiers list by primary region
1070
 * @return array List of timezone identifiers
1071
 * @since 2.2
1072
 * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/time.html#TimeHelper::listTimezones
1073
 */
1074
	public static function listTimezones($filter = null, $country = null, $group = true) {
1075
		$regex = null;
1076
		if (is_string($filter)) {
1077
			$regex = $filter;
1078
			$filter = null;
1079
		}
1080
		if (version_compare(PHP_VERSION, '5.3.0', '<')) {
1081
			if ($regex === null) {
1082
				$regex = '#^((Africa|America|Antartica|Arctic|Asia|Atlantic|Australia|Europe|Indian|Pacific)/|UTC)#';
1083
			}
1084
			$identifiers = DateTimeZone::listIdentifiers();
1085
		} else {
1086
			if ($filter === null) {
1087
				$filter = DateTimeZone::ALL;
1088
			}
1089
			$identifiers = DateTimeZone::listIdentifiers($filter, $country);
1090
		}
1091
1092
		if ($regex) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $regex of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1093
			foreach ($identifiers as $key => $tz) {
1094
				if (!preg_match($regex, $tz)) {
1095
					unset($identifiers[$key]);
1096
				}
1097
			}
1098
		}
1099
1100
		if ($group) {
1101
			$return = array();
1102
			foreach ($identifiers as $key => $tz) {
1103
				$item = explode('/', $tz, 2);
1104
				if (isset($item[1])) {
1105
					$return[$item[0]][$tz] = $item[1];
1106
				} else {
1107
					$return[$item[0]] = array($tz => $item[0]);
1108
				}
1109
			}
1110
			return $return;
1111
		}
1112
		return array_combine($identifiers, $identifiers);
1113
	}
1114
1115
/**
1116
 * Multibyte wrapper for strftime.
1117
 *
1118
 * Handles utf8_encoding the result of strftime when necessary.
1119
 *
1120
 * @param string $format Format string.
1121
 * @param integer $date Timestamp to format.
1122
 * @return string formatted string with correct encoding.
1123
 */
1124
	protected static function _strftime($format, $date) {
1125
		$format = strftime($format, $date);
1126
		$encoding = Configure::read('App.encoding');
1127
1128
		if (!empty($encoding) && $encoding === 'UTF-8') {
1129
			if (function_exists('mb_check_encoding')) {
1130
				$valid = mb_check_encoding($format, $encoding);
1131
			} else {
1132
				$valid = !Multibyte::checkMultibyte($format);
1133
			}
1134
			if (!$valid) {
1135
				$format = utf8_encode($format);
1136
			}
1137
		}
1138
		return $format;
1139
	}
1140
1141
}
1142