GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (423)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

system/helpers/date_helper.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 63 and the first side effect is on line 38.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
9
 * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	http://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
40
/**
41
 * CodeIgniter Date Helpers
42
 *
43
 * @package		CodeIgniter
44
 * @subpackage	Helpers
45
 * @category	Helpers
46
 * @author		EllisLab Dev Team
47
 * @link		http://codeigniter.com/user_guide/helpers/date_helper.html
48
 */
49
50
// ------------------------------------------------------------------------
51
52
if ( ! function_exists('now'))
53
{
54
	/**
55
	 * Get "now" time
56
	 *
57
	 * Returns time() based on the timezone parameter or on the
58
	 * "time_reference" setting
59
	 *
60
	 * @param	string
61
	 * @return	int
62
	 */
63
	function now($timezone = NULL)
64
	{
65
		if (empty($timezone))
66
		{
67
			$timezone = config_item('time_reference');
68
		}
69
70
		if ($timezone === 'local' OR $timezone === date_default_timezone_get())
71
		{
72
			return time();
73
		}
74
75
		$datetime = new DateTime('now', new DateTimeZone($timezone));
76
		sscanf($datetime->format('j-n-Y G:i:s'), '%d-%d-%d %d:%d:%d', $day, $month, $year, $hour, $minute, $second);
77
78
		return mktime($hour, $minute, $second, $month, $day, $year);
79
	}
80
}
81
82
// ------------------------------------------------------------------------
83
84
if ( ! function_exists('mdate'))
85
{
86
	/**
87
	 * Convert MySQL Style Datecodes
88
	 *
89
	 * This function is identical to PHPs date() function,
90
	 * except that it allows date codes to be formatted using
91
	 * the MySQL style, where each code letter is preceded
92
	 * with a percent sign:  %Y %m %d etc...
93
	 *
94
	 * The benefit of doing dates this way is that you don't
95
	 * have to worry about escaping your text letters that
96
	 * match the date codes.
97
	 *
98
	 * @param	string
99
	 * @param	int
100
	 * @return	int
101
	 */
102
	function mdate($datestr = '', $time = '')
103
	{
104
		if ($datestr === '')
105
		{
106
			return '';
107
		}
108
		elseif (empty($time))
109
		{
110
			$time = now();
111
		}
112
113
		$datestr = str_replace(
114
			'%\\',
115
			'',
116
			preg_replace('/([a-z]+?){1}/i', '\\\\\\1', $datestr)
117
		);
118
119
		return date($datestr, $time);
120
	}
121
}
122
123
// ------------------------------------------------------------------------
124
125
if ( ! function_exists('standard_date'))
126
{
127
	/**
128
	 * Standard Date
129
	 *
130
	 * Returns a date formatted according to the submitted standard.
131
	 *
132
	 * As of PHP 5.2, the DateTime extension provides constants that
133
	 * serve for the exact same purpose and are used with date().
134
	 *
135
	 * @todo	Remove in version 3.1+.
136
	 * @deprecated	3.0.0	Use PHP's native date() instead.
137
	 * @link	http://www.php.net/manual/en/class.datetime.php#datetime.constants.types
138
	 *
139
	 * @example	date(DATE_RFC822, now()); // default
140
	 * @example	date(DATE_W3C, $time); // a different format and time
141
	 *
142
	 * @param	string	$fmt = 'DATE_RFC822'	the chosen format
143
	 * @param	int	$time = NULL		Unix timestamp
144
	 * @return	string
145
	 */
146
	function standard_date($fmt = 'DATE_RFC822', $time = NULL)
147
	{
148
		if (empty($time))
149
		{
150
			$time = now();
151
		}
152
153
		// Procedural style pre-defined constants from the DateTime extension
154
		if (strpos($fmt, 'DATE_') !== 0 OR defined($fmt) === FALSE)
155
		{
156
			return FALSE;
157
		}
158
159
		return date(constant($fmt), $time);
160
	}
161
}
162
163
// ------------------------------------------------------------------------
164
165
if ( ! function_exists('timespan'))
166
{
167
	/**
168
	 * Timespan
169
	 *
170
	 * Returns a span of seconds in this format:
171
	 *	10 days 14 hours 36 minutes 47 seconds
172
	 *
173
	 * @param	int	a number of seconds
174
	 * @param	int	Unix timestamp
175
	 * @param	int	a number of display units
176
	 * @return	string
177
	 */
178
	function timespan($seconds = 1, $time = '', $units = 7)
179
	{
180
		$CI =& get_instance();
181
		$CI->lang->load('date');
182
183
		is_numeric($seconds) OR $seconds = 1;
184
		is_numeric($time) OR $time = time();
185
		is_numeric($units) OR $units = 7;
186
187
		$seconds = ($time <= $seconds) ? 1 : $time - $seconds;
188
189
		$str = array();
190
		$years = floor($seconds / 31557600);
191
192
		if ($years > 0)
193
		{
194
			$str[] = $years.' '.$CI->lang->line($years > 1 ? 'date_years' : 'date_year');
195
		}
196
197
		$seconds -= $years * 31557600;
198
		$months = floor($seconds / 2629743);
199
200 View Code Duplication
		if (count($str) < $units && ($years > 0 OR $months > 0))
201
		{
202
			if ($months > 0)
203
			{
204
				$str[] = $months.' '.$CI->lang->line($months > 1 ? 'date_months' : 'date_month');
205
			}
206
207
			$seconds -= $months * 2629743;
208
		}
209
210
		$weeks = floor($seconds / 604800);
211
212 View Code Duplication
		if (count($str) < $units && ($years > 0 OR $months > 0 OR $weeks > 0))
213
		{
214
			if ($weeks > 0)
215
			{
216
				$str[] = $weeks.' '.$CI->lang->line($weeks > 1 ? 'date_weeks' : 'date_week');
217
			}
218
219
			$seconds -= $weeks * 604800;
220
		}
221
222
		$days = floor($seconds / 86400);
223
224 View Code Duplication
		if (count($str) < $units && ($months > 0 OR $weeks > 0 OR $days > 0))
225
		{
226
			if ($days > 0)
227
			{
228
				$str[] = $days.' '.$CI->lang->line($days > 1 ? 'date_days' : 'date_day');
229
			}
230
231
			$seconds -= $days * 86400;
232
		}
233
234
		$hours = floor($seconds / 3600);
235
236 View Code Duplication
		if (count($str) < $units && ($days > 0 OR $hours > 0))
237
		{
238
			if ($hours > 0)
239
			{
240
				$str[] = $hours.' '.$CI->lang->line($hours > 1 ? 'date_hours' : 'date_hour');
241
			}
242
243
			$seconds -= $hours * 3600;
244
		}
245
246
		$minutes = floor($seconds / 60);
247
248 View Code Duplication
		if (count($str) < $units && ($days > 0 OR $hours > 0 OR $minutes > 0))
249
		{
250
			if ($minutes > 0)
251
			{
252
				$str[] = $minutes.' '.$CI->lang->line($minutes > 1 ? 'date_minutes' : 'date_minute');
253
			}
254
255
			$seconds -= $minutes * 60;
256
		}
257
258
		if (count($str) === 0)
259
		{
260
			$str[] = $seconds.' '.$CI->lang->line($seconds > 1 ? 'date_seconds' : 'date_second');
261
		}
262
263
		return implode(', ', $str);
264
	}
265
}
266
267
// ------------------------------------------------------------------------
268
269
if ( ! function_exists('days_in_month'))
270
{
271
	/**
272
	 * Number of days in a month
273
	 *
274
	 * Takes a month/year as input and returns the number of days
275
	 * for the given month/year. Takes leap years into consideration.
276
	 *
277
	 * @param	int	a numeric month
278
	 * @param	int	a numeric year
279
	 * @return	int
280
	 */
281
	function days_in_month($month = 0, $year = '')
282
	{
283
		if ($month < 1 OR $month > 12)
284
		{
285
			return 0;
286
		}
287
		elseif ( ! is_numeric($year) OR strlen($year) !== 4)
288
		{
289
			$year = date('Y');
290
		}
291
292
		if (defined('CAL_GREGORIAN'))
293
		{
294
			return cal_days_in_month(CAL_GREGORIAN, $month, $year);
295
		}
296
297
		if ($year >= 1970)
298
		{
299
			return (int) date('t', mktime(12, 0, 0, $month, 1, $year));
300
		}
301
302
		if ($month == 2)
303
		{
304
			if ($year % 400 === 0 OR ($year % 4 === 0 && $year % 100 !== 0))
305
			{
306
				return 29;
307
			}
308
		}
309
310
		$days_in_month	= array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
311
		return $days_in_month[$month - 1];
312
	}
313
}
314
315
// ------------------------------------------------------------------------
316
317
if ( ! function_exists('local_to_gmt'))
318
{
319
	/**
320
	 * Converts a local Unix timestamp to GMT
321
	 *
322
	 * @param	int	Unix timestamp
323
	 * @return	int
324
	 */
325
	function local_to_gmt($time = '')
326
	{
327
		if ($time === '')
328
		{
329
			$time = time();
330
		}
331
332
		return mktime(
333
			gmdate('G', $time),
334
			gmdate('i', $time),
335
			gmdate('s', $time),
336
			gmdate('n', $time),
337
			gmdate('j', $time),
338
			gmdate('Y', $time)
339
		);
340
	}
341
}
342
343
// ------------------------------------------------------------------------
344
345
if ( ! function_exists('gmt_to_local'))
346
{
347
	/**
348
	 * Converts GMT time to a localized value
349
	 *
350
	 * Takes a Unix timestamp (in GMT) as input, and returns
351
	 * at the local value based on the timezone and DST setting
352
	 * submitted
353
	 *
354
	 * @param	int	Unix timestamp
355
	 * @param	string	timezone
356
	 * @param	bool	whether DST is active
357
	 * @return	int
358
	 */
359
	function gmt_to_local($time = '', $timezone = 'UTC', $dst = FALSE)
360
	{
361
		if ($time === '')
362
		{
363
			return now();
364
		}
365
366
		$time += timezones($timezone) * 3600;
367
368
		return ($dst === TRUE) ? $time + 3600 : $time;
369
	}
370
}
371
372
// ------------------------------------------------------------------------
373
374
if ( ! function_exists('mysql_to_unix'))
375
{
376
	/**
377
	 * Converts a MySQL Timestamp to Unix
378
	 *
379
	 * @param	int	MySQL timestamp YYYY-MM-DD HH:MM:SS
380
	 * @return	int	Unix timstamp
381
	 */
382
	function mysql_to_unix($time = '')
383
	{
384
		// We'll remove certain characters for backward compatibility
385
		// since the formatting changed with MySQL 4.1
386
		// YYYY-MM-DD HH:MM:SS
387
388
		$time = str_replace(array('-', ':', ' '), '', $time);
389
390
		// YYYYMMDDHHMMSS
391
		return mktime(
392
			substr($time, 8, 2),
393
			substr($time, 10, 2),
394
			substr($time, 12, 2),
395
			substr($time, 4, 2),
396
			substr($time, 6, 2),
397
			substr($time, 0, 4)
398
		);
399
	}
400
}
401
402
// ------------------------------------------------------------------------
403
404
if ( ! function_exists('unix_to_human'))
405
{
406
	/**
407
	 * Unix to "Human"
408
	 *
409
	 * Formats Unix timestamp to the following prototype: 2006-08-21 11:35 PM
410
	 *
411
	 * @param	int	Unix timestamp
412
	 * @param	bool	whether to show seconds
413
	 * @param	string	format: us or euro
414
	 * @return	string
415
	 */
416
	function unix_to_human($time = '', $seconds = FALSE, $fmt = 'us')
417
	{
418
		$r = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' ';
419
420
		if ($fmt === 'us')
421
		{
422
			$r .= date('h', $time).':'.date('i', $time);
423
		}
424
		else
425
		{
426
			$r .= date('H', $time).':'.date('i', $time);
427
		}
428
429
		if ($seconds)
430
		{
431
			$r .= ':'.date('s', $time);
432
		}
433
434
		if ($fmt === 'us')
435
		{
436
			return $r.' '.date('A', $time);
437
		}
438
439
		return $r;
440
	}
441
}
442
443
// ------------------------------------------------------------------------
444
445
if ( ! function_exists('human_to_unix'))
446
{
447
	/**
448
	 * Convert "human" date to GMT
449
	 *
450
	 * Reverses the above process
451
	 *
452
	 * @param	string	format: us or euro
453
	 * @return	int
454
	 */
455
	function human_to_unix($datestr = '')
456
	{
457
		if ($datestr === '')
458
		{
459
			return FALSE;
460
		}
461
462
		$datestr = preg_replace('/\040+/', ' ', trim($datestr));
463
464
		if ( ! preg_match('/^(\d{2}|\d{4})\-[0-9]{1,2}\-[0-9]{1,2}\s[0-9]{1,2}:[0-9]{1,2}(?::[0-9]{1,2})?(?:\s[AP]M)?$/i', $datestr))
465
		{
466
			return FALSE;
467
		}
468
469
		sscanf($datestr, '%d-%d-%d %s %s', $year, $month, $day, $time, $ampm);
470
		sscanf($time, '%d:%d:%d', $hour, $min, $sec);
471
		isset($sec) OR $sec = 0;
472
473
		if (isset($ampm))
474
		{
475
			$ampm = strtolower($ampm);
476
477
			if ($ampm[0] === 'p' && $hour < 12)
478
			{
479
				$hour += 12;
480
			}
481
			elseif ($ampm[0] === 'a' && $hour === 12)
482
			{
483
				$hour = 0;
484
			}
485
		}
486
487
		return mktime($hour, $min, $sec, $month, $day, $year);
488
	}
489
}
490
491
// ------------------------------------------------------------------------
492
493
if ( ! function_exists('nice_date'))
494
{
495
	/**
496
	 * Turns many "reasonably-date-like" strings into something
497
	 * that is actually useful. This only works for dates after unix epoch.
498
	 *
499
	 * @param	string	The terribly formatted date-like string
500
	 * @param	string	Date format to return (same as php date function)
501
	 * @return	string
502
	 */
503
	function nice_date($bad_date = '', $format = FALSE)
504
	{
505
		if (empty($bad_date))
506
		{
507
			return 'Unknown';
508
		}
509
		elseif (empty($format))
510
		{
511
			$format = 'U';
512
		}
513
514
		// Date like: YYYYMM
515
		if (preg_match('/^\d{6}$/i', $bad_date))
516
		{
517
			if (in_array(substr($bad_date, 0, 2), array('19', '20')))
518
			{
519
				$year  = substr($bad_date, 0, 4);
520
				$month = substr($bad_date, 4, 2);
521
			}
522
			else
523
			{
524
				$month  = substr($bad_date, 0, 2);
525
				$year   = substr($bad_date, 2, 4);
526
			}
527
528
			return date($format, strtotime($year.'-'.$month.'-01'));
529
		}
530
531
		// Date Like: YYYYMMDD
532
		if (preg_match('/^(\d{2})\d{2}(\d{4})$/i', $bad_date, $matches))
533
		{
534
			return date($format, strtotime($matches[1].'/01/'.$matches[2]));
535
		}
536
537
		// Date Like: MM-DD-YYYY __or__ M-D-YYYY (or anything in between)
538
		if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/i', $bad_date, $matches))
539
		{
540
			return date($format, strtotime($matches[3].'-'.$matches[1].'-'.$matches[2]));
541
		}
542
543
		// Any other kind of string, when converted into UNIX time,
544
		// produces "0 seconds after epoc..." is probably bad...
545
		// return "Invalid Date".
546
		if (date('U', strtotime($bad_date)) === '0')
547
		{
548
			return 'Invalid Date';
549
		}
550
551
		// It's probably a valid-ish date format already
552
		return date($format, strtotime($bad_date));
553
	}
554
}
555
556
// ------------------------------------------------------------------------
557
558
if ( ! function_exists('timezone_menu'))
559
{
560
	/**
561
	 * Timezone Menu
562
	 *
563
	 * Generates a drop-down menu of timezones.
564
	 *
565
	 * @param	string	timezone
566
	 * @param	string	classname
567
	 * @param	string	menu name
568
	 * @param	mixed	attributes
569
	 * @return	string
570
	 */
571
	function timezone_menu($default = 'UTC', $class = '', $name = 'timezones', $attributes = '')
572
	{
573
		$CI =& get_instance();
574
		$CI->lang->load('date');
575
576
		$default = ($default === 'GMT') ? 'UTC' : $default;
577
578
		$menu = '<select name="'.$name.'"';
579
580
		if ($class !== '')
581
		{
582
			$menu .= ' class="'.$class.'"';
583
		}
584
585
		$menu .= _stringify_attributes($attributes).">\n";
586
587
		foreach (timezones() as $key => $val)
588
		{
589
			$selected = ($default === $key) ? ' selected="selected"' : '';
590
			$menu .= '<option value="'.$key.'"'.$selected.'>'.$CI->lang->line($key)."</option>\n";
591
		}
592
593
		return $menu.'</select>';
594
	}
595
}
596
597
// ------------------------------------------------------------------------
598
599
if ( ! function_exists('timezones'))
600
{
601
	/**
602
	 * Timezones
603
	 *
604
	 * Returns an array of timezones. This is a helper function
605
	 * for various other ones in this library
606
	 *
607
	 * @param	string	timezone
608
	 * @return	string
609
	 */
610
	function timezones($tz = '')
611
	{
612
		// Note: Don't change the order of these even though
613
		// some items appear to be in the wrong order
614
615
		$zones = array(
616
			'UM12'		=> -12,
617
			'UM11'		=> -11,
618
			'UM10'		=> -10,
619
			'UM95'		=> -9.5,
620
			'UM9'		=> -9,
621
			'UM8'		=> -8,
622
			'UM7'		=> -7,
623
			'UM6'		=> -6,
624
			'UM5'		=> -5,
625
			'UM45'		=> -4.5,
626
			'UM4'		=> -4,
627
			'UM35'		=> -3.5,
628
			'UM3'		=> -3,
629
			'UM2'		=> -2,
630
			'UM1'		=> -1,
631
			'UTC'		=> 0,
632
			'UP1'		=> +1,
633
			'UP2'		=> +2,
634
			'UP3'		=> +3,
635
			'UP35'		=> +3.5,
636
			'UP4'		=> +4,
637
			'UP45'		=> +4.5,
638
			'UP5'		=> +5,
639
			'UP55'		=> +5.5,
640
			'UP575'		=> +5.75,
641
			'UP6'		=> +6,
642
			'UP65'		=> +6.5,
643
			'UP7'		=> +7,
644
			'UP8'		=> +8,
645
			'UP875'		=> +8.75,
646
			'UP9'		=> +9,
647
			'UP95'		=> +9.5,
648
			'UP10'		=> +10,
649
			'UP105'		=> +10.5,
650
			'UP11'		=> +11,
651
			'UP115'		=> +11.5,
652
			'UP12'		=> +12,
653
			'UP1275'	=> +12.75,
654
			'UP13'		=> +13,
655
			'UP14'		=> +14
656
		);
657
658
		if ($tz === '')
659
		{
660
			return $zones;
661
		}
662
663
		return isset($zones[$tz]) ? $zones[$tz] : 0;
664
	}
665
}
666
667
// ------------------------------------------------------------------------
668
669
if ( ! function_exists('date_range'))
670
{
671
	/**
672
	 * Date range
673
	 *
674
	 * Returns a list of dates within a specified period.
675
	 *
676
	 * @param	int	unix_start	UNIX timestamp of period start date
677
	 * @param	int	unix_end|days	UNIX timestamp of period end date
678
	 *					or interval in days.
679
	 * @param	mixed	is_unix		Specifies whether the second parameter
680
	 *					is a UNIX timestamp or a day interval
681
	 *					 - TRUE or 'unix' for a timestamp
682
	 *					 - FALSE or 'days' for an interval
683
	 * @param	string  date_format	Output date format, same as in date()
684
	 * @return	array
685
	 */
686
	function date_range($unix_start = '', $mixed = '', $is_unix = TRUE, $format = 'Y-m-d')
687
	{
688
		if ($unix_start == '' OR $mixed == '' OR $format == '')
689
		{
690
			return FALSE;
691
		}
692
693
		$is_unix = ! ( ! $is_unix OR $is_unix === 'days');
694
695
		// Validate input and try strtotime() on invalid timestamps/intervals, just in case
696
		if ( ( ! ctype_digit((string) $unix_start) && ($unix_start = @strtotime($unix_start)) === FALSE)
697
			OR ( ! ctype_digit((string) $mixed) && ($is_unix === FALSE OR ($mixed = @strtotime($mixed)) === FALSE))
698
			OR ($is_unix === TRUE && $mixed < $unix_start))
699
		{
700
			return FALSE;
701
		}
702
703
		if ($is_unix && ($unix_start == $mixed OR date($format, $unix_start) === date($format, $mixed)))
704
		{
705
			return array(date($format, $unix_start));
706
		}
707
708
		$range = array();
709
710
		/* NOTE: Even though the DateTime object has many useful features, it appears that
711
		 *	 it doesn't always handle properly timezones, when timestamps are passed
712
		 *	 directly to its constructor. Neither of the following gave proper results:
713
		 *
714
		 *		new DateTime('<timestamp>')
715
		 *		new DateTime('<timestamp>', '<timezone>')
716
		 *
717
		 *	 --- available in PHP 5.3:
718
		 *
719
		 *		DateTime::createFromFormat('<format>', '<timestamp>')
720
		 *		DateTime::createFromFormat('<format>', '<timestamp>', '<timezone')
721
		 *
722
		 *	 ... so we'll have to set the timestamp after the object is instantiated.
723
		 *	 Furthermore, in PHP 5.3 we can use DateTime::setTimestamp() to do that and
724
		 *	 given that we have UNIX timestamps - we should use it.
725
		*/
726
		$from = new DateTime();
727
728
		if (is_php('5.3'))
729
		{
730
			$from->setTimestamp($unix_start);
731
			if ($is_unix)
732
			{
733
				$arg = new DateTime();
734
				$arg->setTimestamp($mixed);
735
			}
736
			else
737
			{
738
				$arg = (int) $mixed;
739
			}
740
741
			$period = new DatePeriod($from, new DateInterval('P1D'), $arg);
742
			foreach ($period as $date)
743
			{
744
				$range[] = $date->format($format);
745
			}
746
747
			/* If a period end date was passed to the DatePeriod constructor, it might not
748
			 * be in our results. Not sure if this is a bug or it's just possible because
749
			 * the end date might actually be less than 24 hours away from the previously
750
			 * generated DateTime object, but either way - we have to append it manually.
751
			 */
752
			if ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format))
753
			{
754
				$range[] = $arg->format($format);
755
			}
756
757
			return $range;
758
		}
759
760
		$from->setDate(date('Y', $unix_start), date('n', $unix_start), date('j', $unix_start));
761
		$from->setTime(date('G', $unix_start), date('i', $unix_start), date('s', $unix_start));
762
		if ($is_unix)
763
		{
764
			$arg = new DateTime();
765
			$arg->setDate(date('Y', $mixed), date('n', $mixed), date('j', $mixed));
766
			$arg->setTime(date('G', $mixed), date('i', $mixed), date('s', $mixed));
767
		}
768
		else
769
		{
770
			$arg = (int) $mixed;
771
		}
772
		$range[] = $from->format($format);
773
774
		if (is_int($arg)) // Day intervals
775
		{
776
			do
777
			{
778
				$from->modify('+1 day');
779
				$range[] = $from->format($format);
780
			}
781
			while (--$arg > 0);
782
		}
783
		else // end date UNIX timestamp
784
		{
785
			for ($from->modify('+1 day'), $end_check = $arg->format('Ymd'); $from->format('Ymd') < $end_check; $from->modify('+1 day'))
786
			{
787
				$range[] = $from->format($format);
788
			}
789
790
			// Our loop only appended dates prior to our end date
791
			$range[] = $arg->format($format);
792
		}
793
794
		return $range;
795
	}
796
}
797