From 2139ecdbe882dee32f60de5aec74ec2b8a509b7a Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 11 Jan 2012 23:58:50 +0200 Subject: Added date_range() to the Date helper --- system/helpers/date_helper.php | 166 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 165 insertions(+), 1 deletion(-) (limited to 'system/helpers') diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index 9e58d8630..4a0791a43 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -695,5 +695,169 @@ if ( ! function_exists('timezones')) } } +// ------------------------------------------------------------------------ + +/** + * Date range + * + * Returns a list of dates within a specified period. + * + * @access public + * @param int unix_start UNIX timestamp of period start date + * @param int unix_end|days UNIX timestamp of period end date + * or interval in days. + * @param mixed is_unix Specifies wether the second @param + * is a UNIX timestamp or day interval + * - TRUE or 'unix' for a timestamp + * - FALSE or 'days' for an interval + * @param string date_format Output date format, same as in date() + * @return array + */ +if ( ! function_exists('date_range')) +{ + function date_range($unix_start = '', $mixed = '', $is_unix = TRUE, $format = 'Y-m-d') + { + if ($unix_start == '' OR $mixed == '' OR $format == '') + { + return FALSE; + } + + $is_unix = ! ( ! $is_unix OR $is_unix === 'days'); + + // Validate input and try strtotime() on invalid timestamps/intervals, just in case + if ( ( ! preg_match('/^[0-9]+$/', $unix_start) && ($unix_start = @strtotime($unix_time)) === FALSE) + OR ( ! preg_match('/^[0-9]+$/', $mixed) && ($is_unix === FALSE OR ($mixed = @strtotime($mixed)) === FALSE)) + OR ($is_unix === TRUE && $mixed < $unix_start)) + { + return FALSE; + } + + if ($is_unix && ($unix_start == $mixed OR date($format, $unix_start) === date($format, $mixed))) + { + return array($start_date); + } + + $range = array(); + + if (is_php('5.2')) + { + /* NOTE: Even though the DateTime object has many useful features, it appears that + * it doesn't always handle properly timezones, when timestamps are passed + * directly to its constructor. Neither of the following gave proper results: + * + * new DateTime('') + * new DateTime('', '') + * + * --- available in PHP 5.3: + * + * DateTime::createFromFormat('', '') + * DateTime::createFromFormat('', '', 'setTimestamp($unix_start); + if ($is_unix) + { + $arg = new DateTime(); + $arg->setTimestamp($mixed); + } + else + { + $arg = (int) $mixed; + } + $period = new DatePeriod($from, new DateInterval('P1D'), $arg); + $range = array(); + foreach ($period as $date) + { + $range[] = $date->format($format); + } + + /* If a period end date was passed to the DatePeriod constructor, it might not + * be in our results. Not sure if this is a bug or it's just possible because + * the end date might actually be less than 24 hours away from the previously + * generated DateTime object, but either way - we have to append it manually. + */ + if ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format)) + { + $range[] = $arg->format($format); + } + + return $range; + } + + $from->setDate(date('Y', $unix_start), date('n', $unix_start), date('j', $unix_start)); + $from->setTime(date('G', $unix_start), date('i', $unix_start), date('s', $unix_start)); + if ($is_unix) + { + $arg = new DateTime(); + $arg->setDate(date('Y', $mixed), date('n', $mixed), date('j', $mixed)); + $arg->setTime(date('G', $mixed), date('i', $mixed), date('s', $mixed)); + } + else + { + $arg = (int) $mixed; + } + $range[] = $from->format($format); + + if (is_int($arg)) // Day intervals + { + do + { + $from->modify('+1 day'); + $range[] = $from->format($format); + } + while (--$arg > 0); + } + else // end date UNIX timestamp + { + for ($from->modify('+1 day'), $end_check = $arg->format('Ymd'); $from->format('Ymd') < $end_check; $from->modify('+1 day')) + { + $range[] = $from->format($format); + } + + // Our loop only appended dates prior to our end date + $range[] = $arg->format($format); + } + + return $range; + } + + /* ---------------------------------------------------------------------------------- + * PHP Version is < 5.2. We have no other option, but to calculate manually ... + * + * NOTE: If we do something like this: + * + * $unix_timestamp + 86400 + * + * ... due to DST, there's a possibility of calculation errors and/or incorrect + * hours generated (if the specified format displays such data) due to DST. + */ + + $from = $to = array(); + sscanf(date('Y-n-j G:i:s', $unix_start), '%d-%d-%d %d:%d:%d', $from['y'], $from['mo'], $from['d'], $from['h'], $from['mi'], $from['s']); + + // If we don't have the end timestamp, let mktime() calculate it + $unix_end = ($is_unix) ? (int) $mixed : mktime($from['h'], $from['mi'], $from['s'], $from['mo'], $from['d'] + $mixed, $from['y']); + + $end_check = date('Ymd', $unix_end); + while (date('Ymd', $unix_start = mktime($from['h'], $from['mi'], $from['s'], $from['mo'], $from['d'], $from['y'])) !== $end_check) + { + $range[] = date($format, $unix_start); + $from['d']++; + } + + // Our loop only appended dates prior to our end date + $range[] = date($format, $unix_end); + + return $range; + } +} + /* End of file date_helper.php */ -/* Location: ./system/helpers/date_helper.php */ \ No newline at end of file +/* Location: ./system/helpers/date_helper.php */ -- cgit v1.2.3-24-g4f1b From 4f553dfe20a3dcb2d384fe30210d85cf4f645de2 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Sun, 15 Jan 2012 15:03:02 +0200 Subject: Remove a space :) --- system/helpers/date_helper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system/helpers') diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index 4a0791a43..7bec8079d 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -745,7 +745,7 @@ if ( ! function_exists('date_range')) * it doesn't always handle properly timezones, when timestamps are passed * directly to its constructor. Neither of the following gave proper results: * - * new DateTime('') + * new DateTime('') * new DateTime('', '') * * --- available in PHP 5.3: -- cgit v1.2.3-24-g4f1b From 8bbb38983b8052e32063244941315fe81199e024 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Tue, 21 Feb 2012 22:22:34 +0200 Subject: Removed a second/unnecessary variable initialization and fixed a comment --- system/helpers/date_helper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'system/helpers') diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index 7bec8079d..b186b2acb 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -771,8 +771,8 @@ if ( ! function_exists('date_range')) { $arg = (int) $mixed; } + $period = new DatePeriod($from, new DateInterval('P1D'), $arg); - $range = array(); foreach ($period as $date) { $range[] = $date->format($format); @@ -836,7 +836,7 @@ if ( ! function_exists('date_range')) * $unix_timestamp + 86400 * * ... due to DST, there's a possibility of calculation errors and/or incorrect - * hours generated (if the specified format displays such data) due to DST. + * hours generated (if the specified format displays such data). */ $from = $to = array(); -- cgit v1.2.3-24-g4f1b From 30da39bb5d65c37203c12a42dfc50f7d231fb2d1 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Sat, 10 Mar 2012 15:49:17 +0200 Subject: Remove PHP 5.1 dependancy check --- system/helpers/date_helper.php | 152 ++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 92 deletions(-) (limited to 'system/helpers') diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index a655c1f21..cb15f6df6 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -739,121 +739,89 @@ if ( ! function_exists('date_range')) $range = array(); - if (is_php('5.2')) - { - /* NOTE: Even though the DateTime object has many useful features, it appears that - * it doesn't always handle properly timezones, when timestamps are passed - * directly to its constructor. Neither of the following gave proper results: - * - * new DateTime('') - * new DateTime('', '') - * - * --- available in PHP 5.3: - * - * DateTime::createFromFormat('', '') - * DateTime::createFromFormat('', '', 'setTimestamp($unix_start); - if ($is_unix) - { - $arg = new DateTime(); - $arg->setTimestamp($mixed); - } - else - { - $arg = (int) $mixed; - } - - $period = new DatePeriod($from, new DateInterval('P1D'), $arg); - foreach ($period as $date) - { - $range[] = $date->format($format); - } - - /* If a period end date was passed to the DatePeriod constructor, it might not - * be in our results. Not sure if this is a bug or it's just possible because - * the end date might actually be less than 24 hours away from the previously - * generated DateTime object, but either way - we have to append it manually. - */ - if ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format)) - { - $range[] = $arg->format($format); - } - - return $range; - } + /* NOTE: Even though the DateTime object has many useful features, it appears that + * it doesn't always handle properly timezones, when timestamps are passed + * directly to its constructor. Neither of the following gave proper results: + * + * new DateTime('') + * new DateTime('', '') + * + * --- available in PHP 5.3: + * + * DateTime::createFromFormat('', '') + * DateTime::createFromFormat('', '', 'setDate(date('Y', $unix_start), date('n', $unix_start), date('j', $unix_start)); - $from->setTime(date('G', $unix_start), date('i', $unix_start), date('s', $unix_start)); + if (is_php('5.3')) + { + $from->setTimestamp($unix_start); if ($is_unix) { $arg = new DateTime(); - $arg->setDate(date('Y', $mixed), date('n', $mixed), date('j', $mixed)); - $arg->setTime(date('G', $mixed), date('i', $mixed), date('s', $mixed)); + $arg->setTimestamp($mixed); } else { $arg = (int) $mixed; } - $range[] = $from->format($format); - if (is_int($arg)) // Day intervals + $period = new DatePeriod($from, new DateInterval('P1D'), $arg); + foreach ($period as $date) { - do - { - $from->modify('+1 day'); - $range[] = $from->format($format); - } - while (--$arg > 0); + $range[] = $date->format($format); } - else // end date UNIX timestamp - { - for ($from->modify('+1 day'), $end_check = $arg->format('Ymd'); $from->format('Ymd') < $end_check; $from->modify('+1 day')) - { - $range[] = $from->format($format); - } - // Our loop only appended dates prior to our end date + /* If a period end date was passed to the DatePeriod constructor, it might not + * be in our results. Not sure if this is a bug or it's just possible because + * the end date might actually be less than 24 hours away from the previously + * generated DateTime object, but either way - we have to append it manually. + */ + if ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format)) + { $range[] = $arg->format($format); } return $range; } - /* ---------------------------------------------------------------------------------- - * PHP Version is < 5.2. We have no other option, but to calculate manually ... - * - * NOTE: If we do something like this: - * - * $unix_timestamp + 86400 - * - * ... due to DST, there's a possibility of calculation errors and/or incorrect - * hours generated (if the specified format displays such data). - */ - - $from = $to = array(); - sscanf(date('Y-n-j G:i:s', $unix_start), '%d-%d-%d %d:%d:%d', $from['y'], $from['mo'], $from['d'], $from['h'], $from['mi'], $from['s']); - - // If we don't have the end timestamp, let mktime() calculate it - $unix_end = ($is_unix) ? (int) $mixed : mktime($from['h'], $from['mi'], $from['s'], $from['mo'], $from['d'] + $mixed, $from['y']); + $from->setDate(date('Y', $unix_start), date('n', $unix_start), date('j', $unix_start)); + $from->setTime(date('G', $unix_start), date('i', $unix_start), date('s', $unix_start)); + if ($is_unix) + { + $arg = new DateTime(); + $arg->setDate(date('Y', $mixed), date('n', $mixed), date('j', $mixed)); + $arg->setTime(date('G', $mixed), date('i', $mixed), date('s', $mixed)); + } + else + { + $arg = (int) $mixed; + } + $range[] = $from->format($format); - $end_check = date('Ymd', $unix_end); - while (date('Ymd', $unix_start = mktime($from['h'], $from['mi'], $from['s'], $from['mo'], $from['d'], $from['y'])) !== $end_check) + if (is_int($arg)) // Day intervals { - $range[] = date($format, $unix_start); - $from['d']++; + do + { + $from->modify('+1 day'); + $range[] = $from->format($format); + } + while (--$arg > 0); } + else // end date UNIX timestamp + { + for ($from->modify('+1 day'), $end_check = $arg->format('Ymd'); $from->format('Ymd') < $end_check; $from->modify('+1 day')) + { + $range[] = $from->format($format); + } - // Our loop only appended dates prior to our end date - $range[] = date($format, $unix_end); + // Our loop only appended dates prior to our end date + $range[] = $arg->format($format); + } return $range; } -- cgit v1.2.3-24-g4f1b From ad97736d8249240cba802d33a24b7b11e02488cf Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Tue, 13 Mar 2012 12:51:50 +0200 Subject: Remove access description comment --- system/helpers/date_helper.php | 1 - 1 file changed, 1 deletion(-) (limited to 'system/helpers') diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index cb15f6df6..ead0d1723 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -702,7 +702,6 @@ if ( ! function_exists('timezones')) * * Returns a list of dates within a specified period. * - * @access public * @param int unix_start UNIX timestamp of period start date * @param int unix_end|days UNIX timestamp of period end date * or interval in days. -- cgit v1.2.3-24-g4f1b