3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.7 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2015 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2015
39 class CRM_Utils_Date
{
42 * Format a date by padding it with leading '0'.
46 * @param string $separator
47 * The seperator to use when formatting the date.
48 * @param int|string $invalidDate what to return if the date is invalid
51 * formatted string for date
54 public static function format($date, $separator = '', $invalidDate = 0) {
55 if (is_numeric($date) &&
56 ((strlen($date) == 8) ||
(strlen($date) == 14))
61 if (!is_array($date) ||
62 CRM_Utils_System
::isNull($date) ||
68 $date['Y'] = (int ) $date['Y'];
69 if ($date['Y'] < 1000 ||
$date['Y'] > 2999) {
73 if (array_key_exists('m', $date)) {
74 $date['M'] = $date['m'];
76 elseif (array_key_exists('F', $date)) {
77 $date['M'] = $date['F'];
80 if (!empty($date['M'])) {
81 $date['M'] = (int ) $date['M'];
82 if ($date['M'] < 1 ||
$date['M'] > 12) {
90 if (!empty($date['d'])) {
91 $date['d'] = (int ) $date['d'];
97 if (!checkdate($date['M'], $date['d'], $date['Y'])) {
101 $date['M'] = sprintf('%02d', $date['M']);
102 $date['d'] = sprintf('%02d', $date['d']);
105 if (CRM_Utils_Array
::value('H', $date) != NULL ||
106 CRM_Utils_Array
::value('h', $date) != NULL ||
107 CRM_Utils_Array
::value('i', $date) != NULL ||
108 CRM_Utils_Array
::value('s', $date) != NULL
110 // we have time too..
111 if (!empty($date['h'])) {
112 if (CRM_Utils_Array
::value('A', $date) == 'PM' or CRM_Utils_Array
::value('a', $date) == 'pm') {
113 if ($date['h'] != 12) {
114 $date['h'] = $date['h'] +
12;
117 if ((CRM_Utils_Array
::value('A', $date) == 'AM' or CRM_Utils_Array
::value('a', $date) == 'am') &&
118 CRM_Utils_Array
::value('h', $date) == 12
123 $date['h'] = (int ) $date['h'];
129 // in 24-hour format the hour is under the 'H' key
130 if (!empty($date['H'])) {
131 $date['H'] = (int) $date['H'];
137 if (!empty($date['i'])) {
138 $date['i'] = (int ) $date['i'];
144 if ($date['h'] == 0 && $date['H'] != 0) {
145 $date['h'] = $date['H'];
148 if (!empty($date['s'])) {
149 $date['s'] = (int ) $date['s'];
155 $date['h'] = sprintf('%02d', $date['h']);
156 $date['i'] = sprintf('%02d', $date['i']);
157 $date['s'] = sprintf('%02d', $date['s']);
162 $time .= $date['h'] . $separator . $date['i'] . $separator . $date['s'];
165 return $date['Y'] . $separator . $date['M'] . $separator . $date['d'] . $time;
169 * Return abbreviated weekday names according to the locale.
171 * Array will be in localized order according to 'weekBegins' setting,
172 * but array keys will always match to:
178 * 0-based array with abbreviated weekday names
181 public static function getAbbrWeekdayNames() {
182 static $days = array();
184 // First day of the week
185 $firstDay = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::LOCALIZATION_PREFERENCES_NAME
, 'weekBegins', NULL, 0);
187 // set LC_TIME and build the arrays from locale-provided names
188 // June 1st, 1970 was a Monday
189 CRM_Core_I18n
::setLcTime();
190 for ($i = $firstDay; count($days) < 7; $i = $i > 6 ?
0 : $i +
1) {
191 $days[$i] = strftime('%a', mktime(0, 0, 0, 6, $i, 1970));
198 * Return full weekday names according to the locale.
200 * Array will be in localized order according to 'weekBegins' setting,
201 * but array keys will always match to:
207 * 0-based array with full weekday names
210 public static function getFullWeekdayNames() {
211 static $days = array();
213 // First day of the week
214 $firstDay = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::LOCALIZATION_PREFERENCES_NAME
, 'weekBegins', NULL, 0);
216 // set LC_TIME and build the arrays from locale-provided names
217 // June 1st, 1970 was a Monday
218 CRM_Core_I18n
::setLcTime();
219 for ($i = $firstDay; count($days) < 7; $i = $i > 6 ?
0 : $i +
1) {
220 $days[$i] = strftime('%A', mktime(0, 0, 0, 6, $i, 1970));
227 * Return abbreviated month names according to the locale.
232 * 1-based array with abbreviated month names
235 public static function &getAbbrMonthNames($month = FALSE) {
236 static $abbrMonthNames;
237 if (!isset($abbrMonthNames)) {
239 // set LC_TIME and build the arrays from locale-provided names
240 CRM_Core_I18n
::setLcTime();
241 for ($i = 1; $i <= 12; $i++
) {
242 $abbrMonthNames[$i] = strftime('%b', mktime(0, 0, 0, $i, 10, 1970));
246 return $abbrMonthNames[$month];
248 return $abbrMonthNames;
252 * Return full month names according to the locale.
255 * 1-based array with full month names
258 public static function &getFullMonthNames() {
259 static $fullMonthNames;
260 if (!isset($fullMonthNames)) {
262 // set LC_TIME and build the arrays from locale-provided names
263 CRM_Core_I18n
::setLcTime();
264 for ($i = 1; $i <= 12; $i++
) {
265 $fullMonthNames[$i] = strftime('%B', mktime(0, 0, 0, $i, 10, 1970));
268 return $fullMonthNames;
276 public static function unixTime($string) {
277 if (empty($string)) {
280 $parsedDate = date_parse($string);
281 return mktime(CRM_Utils_Array
::value('hour', $parsedDate),
282 CRM_Utils_Array
::value('minute', $parsedDate),
284 CRM_Utils_Array
::value('month', $parsedDate),
285 CRM_Utils_Array
::value('day', $parsedDate),
286 CRM_Utils_Array
::value('year', $parsedDate)
291 * Create a date and time string in a provided format.
293 * %b - abbreviated month name ('Jan'..'Dec')
294 * %B - full month name ('January'..'December')
295 * %d - day of the month as a decimal number, 0-padded ('01'..'31')
296 * %e - day of the month as a decimal number, blank-padded (' 1'..'31')
297 * %E - day of the month as a decimal number ('1'..'31')
298 * %f - English ordinal suffix for the day of the month ('st', 'nd', 'rd', 'th')
299 * %H - hour in 24-hour format, 0-padded ('00'..'23')
300 * %I - hour in 12-hour format, 0-padded ('01'..'12')
301 * %k - hour in 24-hour format, blank-padded (' 0'..'23')
302 * %l - hour in 12-hour format, blank-padded (' 1'..'12')
303 * %m - month as a decimal number, 0-padded ('01'..'12')
304 * %M - minute, 0-padded ('00'..'60')
305 * %p - lowercase ante/post meridiem ('am', 'pm')
306 * %P - uppercase ante/post meridiem ('AM', 'PM')
307 * %Y - year as a decimal number including the century ('2005')
309 * @param string $dateString
310 * Date and time in 'YYYY-MM-DD hh:mm:ss' format.
311 * @param string $format
313 * @param array $dateParts
314 * An array with the desired date parts.
317 * the $format-formatted $date
319 public static function customFormat($dateString, $format = NULL, $dateParts = NULL) {
320 // 1-based (January) month names arrays
321 $abbrMonths = self
::getAbbrMonthNames();
322 $fullMonths = self
::getFullMonthNames();
325 $config = CRM_Core_Config
::singleton();
328 if (array_intersect(array('h', 'H'), $dateParts)) {
329 $format = $config->dateformatDatetime
;
331 elseif (array_intersect(array('d', 'j'), $dateParts)) {
332 $format = $config->dateformatFull
;
334 elseif (array_intersect(array('m', 'M'), $dateParts)) {
335 $format = $config->dateformatPartial
;
338 $format = $config->dateformatYear
;
342 if (strpos($dateString, '-')) {
343 $month = (int) substr($dateString, 5, 2);
344 $day = (int) substr($dateString, 8, 2);
347 $month = (int) substr($dateString, 4, 2);
348 $day = (int) substr($dateString, 6, 2);
351 if (strlen($dateString) > 10) {
352 $format = $config->dateformatDatetime
;
355 $format = $config->dateformatFull
;
357 elseif ($month > 0) {
358 $format = $config->dateformatPartial
;
361 $format = $config->dateformatYear
;
366 if (!CRM_Utils_System
::isNull($dateString)) {
367 if (strpos($dateString, '-')) {
368 $year = (int) substr($dateString, 0, 4);
369 $month = (int) substr($dateString, 5, 2);
370 $day = (int) substr($dateString, 8, 2);
372 $hour24 = (int) substr($dateString, 11, 2);
373 $minute = (int) substr($dateString, 14, 2);
376 $year = (int) substr($dateString, 0, 4);
377 $month = (int) substr($dateString, 4, 2);
378 $day = (int) substr($dateString, 6, 2);
380 $hour24 = (int) substr($dateString, 8, 2);
381 $minute = (int) substr($dateString, 10, 2);
384 if ($day %
10 == 1 and $day != 11) {
387 elseif ($day %
10 == 2 and $day != 12) {
390 elseif ($day %
10 == 3 and $day != 13) {
411 $hour12 = $hour24 - 12;
417 '%b' => CRM_Utils_Array
::value($month, $abbrMonths),
418 '%B' => CRM_Utils_Array
::value($month, $fullMonths),
419 '%d' => $day > 9 ?
$day : '0' . $day,
420 '%e' => $day > 9 ?
$day : ' ' . $day,
423 '%H' => $hour24 > 9 ?
$hour24 : '0' . $hour24,
424 '%h' => $hour12 > 9 ?
$hour12 : '0' . $hour12,
425 '%I' => $hour12 > 9 ?
$hour12 : '0' . $hour12,
426 '%k' => $hour24 > 9 ?
$hour24 : ' ' . $hour24,
427 '%l' => $hour12 > 9 ?
$hour12 : ' ' . $hour12,
428 '%m' => $month > 9 ?
$month : '0' . $month,
429 '%M' => $minute > 9 ?
$minute : '0' . $minute,
430 '%i' => $minute > 9 ?
$minute : '0' . $minute,
431 '%p' => strtolower($type),
437 return strtr($format, $date);
445 * Converts the date/datetime from MySQL format to ISO format
447 * @param string $mysql
448 * Date/datetime in MySQL format.
451 * date/datetime in ISO format
453 public static function mysqlToIso($mysql) {
454 $year = substr($mysql, 0, 4);
455 $month = substr($mysql, 4, 2);
456 $day = substr($mysql, 6, 2);
457 $hour = substr($mysql, 8, 2);
458 $minute = substr($mysql, 10, 2);
459 $second = substr($mysql, 12, 2);
485 * Converts the date/datetime from ISO format to MySQL format
486 * Note that until CRM-14986/ 4.4.7 this was required whenever the pattern $dao->find(TRUE): $dao->save(); was
487 * used to update an object with a date field was used. The DAO now checks for a '-' in date field strings
488 * & runs this function if the - appears - meaning it is likely redundant in the form & BAO layers
491 * Date/datetime in ISO format.
494 * date/datetime in MySQL format
496 public static function isoToMysql($iso) {
497 $dropArray = array('-' => '', ':' => '', ' ' => '');
498 return strtr($iso, $dropArray);
502 * Converts the any given date to default date format.
504 * @param array $params
505 * Has given date-format.
506 * @param int $dateType
508 * @param string $dateParam
513 public static function convertToDefaultDate(&$params, $dateType, $dateParam) {
515 $cen = substr($now['year'], 0, 2);
519 if (!empty($params[$dateParam])) {
520 // suppress hh:mm or hh:mm:ss if it exists CRM-7957
521 $value = preg_replace("/(\s(([01]\d)|[2][0-3])(:([0-5]\d)){1,2})$/", "", $params[$dateParam]);
526 if (!preg_match('/^\d\d\d\d-?(\d|\d\d)-?(\d|\d\d)$/', $value)) {
532 if (!preg_match('/^(\d|\d\d)[-\/](\d|\d\d)[-\/]\d\d$/', $value)) {
538 if (!preg_match('/^(\d|\d\d)[-\/](\d|\d\d)[-\/]\d\d\d\d$/', $value)) {
544 if (!preg_match('/^[A-Za-z]*.[ \t]?\d\d\,[ \t]?\d\d\d\d$/', $value)) {
550 if (!preg_match('/^\d\d-[A-Za-z]{3}.*-\d\d$/', $value) && !preg_match('/^\d\d[-\/]\d\d[-\/]\d\d$/', $value)) {
556 if (!preg_match('/^(\d|\d\d)[-\/](\d|\d\d)[-\/]\d\d\d\d/', $value)) {
562 if ($dateType == 1) {
563 $formattedDate = explode("-", $value);
564 if (count($formattedDate) == 3) {
565 $year = (int) $formattedDate[0];
566 $month = (int) $formattedDate[1];
567 $day = (int) $formattedDate[2];
569 elseif (count($formattedDate) == 1 && (strlen($value) == 8)) {
577 if ($dateType == 2 ||
$dateType == 4) {
578 $formattedDate = explode("/", $value);
579 if (count($formattedDate) != 3) {
580 $formattedDate = explode("-", $value);
582 if (count($formattedDate) == 3) {
583 $year = (int) $formattedDate[2];
584 $month = (int) $formattedDate[0];
585 $day = (int) $formattedDate[1];
591 if ($dateType == 8) {
592 $dateArray = explode(' ', $value);
594 $dateArray[1] = (int) substr($dateArray[1], 0, 2);
597 $fullMonths = self
::getFullMonthNames();
598 foreach ($fullMonths as $key => $val) {
599 if (strtolower($dateArray[0]) == strtolower($val)) {
605 $abbrMonths = self
::getAbbrMonthNames();
606 foreach ($abbrMonths as $key => $val) {
607 if (strtolower(trim($dateArray[0], ".")) == strtolower($val)) {
613 $year = (int) $dateArray[2];
614 $day = (int) $dateArray[1];
615 $month = (int) $monthInt;
617 if ($dateType == 16) {
618 $dateArray = explode('-', $value);
619 if (count($dateArray) != 3) {
620 $dateArray = explode('/', $value);
623 if (count($dateArray) == 3) {
625 $fullMonths = self
::getFullMonthNames();
626 foreach ($fullMonths as $key => $val) {
627 if (strtolower($dateArray[1]) == strtolower($val)) {
633 $abbrMonths = self
::getAbbrMonthNames();
634 foreach ($abbrMonths as $key => $val) {
635 if (strtolower(trim($dateArray[1], ".")) == strtolower($val)) {
642 $monthInt = $dateArray[1];
645 $year = (int) $dateArray[2];
646 $day = (int) $dateArray[0];
647 $month = (int) $monthInt;
653 if ($dateType == 32) {
654 $formattedDate = explode("/", $value);
655 if (count($formattedDate) == 3) {
656 $year = (int) $formattedDate[2];
657 $month = (int) $formattedDate[1];
658 $day = (int) $formattedDate[0];
665 $month = ($month < 10) ?
"0" . "$month" : $month;
666 $day = ($day < 10) ?
"0" . "$day" : $day;
668 $year = (int ) $year;
669 // simple heuristic to determine what century to use
670 // 00 - 20 is always 2000 - 2020
671 // 21 - 99 is always 1921 - 1999
673 $year = (strlen($year) == 1) ?
$cen . '0' . $year : $cen . $year;
675 elseif ($year < 100) {
676 $year = $prevCen . $year;
679 if ($params[$dateParam]) {
680 $params[$dateParam] = "$year$month$day";
682 //if month is invalid return as error
683 if ($month !== '00' && $month <= 12) {
694 public static function isDate(&$date) {
695 if (CRM_Utils_System
::isNull($date)) {
702 * @param null $timeStamp
704 * @return bool|string
706 public static function currentDBDate($timeStamp = NULL) {
707 return $timeStamp ?
date('YmdHis', $timeStamp) : date('YmdHis');
716 public static function overdue($date, $now = NULL) {
717 $mysqlDate = self
::isoToMysql($date);
719 $now = self
::currentDBDate();
722 $now = self
::isoToMysql($now);
725 return ($mysqlDate >= $now) ?
FALSE : TRUE;
729 * Get customized today.
731 * This function is used for getting customized today. To get
732 * actuall today pass 'dayParams' as null. or else pass the day,
733 * month, year values as array values
734 * Example: $dayParams = array(
735 * 'day' => '25', 'month' => '10',
736 * 'year' => '2007' );
738 * @param array $dayParams of the day, month, year.
739 * Array of the day, month, year.
741 * @param string $format
742 * Expected date format( default.
743 * format is 2007-12-21 )
746 * Return the customized today's date (Y-m-d)
748 public static function getToday($dayParams = NULL, $format = "Y-m-d") {
749 if (is_null($dayParams) ||
empty($dayParams)) {
750 $today = date($format);
753 $today = date($format, mktime(0, 0, 0,
764 * Find whether today's date lies in
767 * @param date $startDate
768 * Start date for the range.
769 * @param date $endDate
770 * End date for the range.
773 * true if today's date is in the given date range
775 public static function getRange($startDate, $endDate) {
776 $today = date("Y-m-d");
777 $mysqlStartDate = self
::isoToMysql($startDate);
778 $mysqlEndDate = self
::isoToMysql($endDate);
779 $mysqlToday = self
::isoToMysql($today);
781 if ((isset($mysqlStartDate) && isset($mysqlEndDate)) && (($mysqlToday >= $mysqlStartDate) && ($mysqlToday <= $mysqlEndDate))) {
784 elseif ((isset($mysqlStartDate) && !isset($mysqlEndDate)) && (($mysqlToday >= $mysqlStartDate))) {
787 elseif ((!isset($mysqlStartDate) && isset($mysqlEndDate)) && (($mysqlToday <= $mysqlEndDate))) {
794 * Get start date and end from
795 * the given relative term and unit
797 * @param date $relative
804 * start date, end date
806 public static function getFromTo($relative, $from, $to) {
808 list($term, $unit) = explode('.', $relative);
809 $dateRange = self
::relativeToAbsolute($term, $unit);
810 $from = $dateRange['from'];
811 //Take only Date Part, Sometime Time part is also present in 'to'
812 $to = substr($dateRange['to'], 0, 8);
815 $from = self
::processDate($from);
816 $to = self
::processDate($to, '235959');
818 return array($from, $to);
822 * Calculate Age in Years if greater than one year else in months.
824 * @param date $birthDate
828 * array $results contains years or months
830 static public function calculateAge($birthDate) {
832 $formatedBirthDate = CRM_Utils_Date
::customFormat($birthDate, '%Y-%m-%d');
834 $bDate = explode('-', $formatedBirthDate);
835 $birthYear = $bDate[0];
836 $birthMonth = $bDate[1];
837 $birthDay = $bDate[2];
838 $year_diff = date("Y") - $birthYear;
840 // don't calculate age CRM-3143
841 if ($birthYear == '1902') {
845 switch ($year_diff) {
847 $month = (12 - $birthMonth) +
date("m");
849 if (date("d") < $birthDay) {
852 $results['months'] = $month;
854 elseif ($month == 12 && (date("d") < $birthDay)) {
855 $results['months'] = $month - 1;
858 $results['years'] = $year_diff;
863 $month = date("m") - $birthMonth;
864 $results['months'] = $month;
868 $results['years'] = $year_diff;
869 if ((date("m") < $birthMonth) ||
(date("m") == $birthMonth) && (date("d") < $birthDay)) {
878 * Calculate next payment date according to provided unit & interval
880 * @param string $unit
881 * Frequency unit like year,month, week etc.
883 * @param int $interval
884 * Frequency interval.
887 * Start date of pledge.
889 * @param bool $dontCareTime
892 * contains new date with added interval
894 public static function intervalAdd($unit, $interval, $date, $dontCareTime = FALSE) {
895 if (is_array($date)) {
896 $hour = CRM_Utils_Array
::value('H', $date);
897 $minute = CRM_Utils_Array
::value('i', $date);
898 $second = CRM_Utils_Array
::value('s', $date);
899 $month = CRM_Utils_Array
::value('M', $date);
900 $day = CRM_Utils_Array
::value('d', $date);
901 $year = CRM_Utils_Array
::value('Y', $date);
904 extract(date_parse($date));
906 $date = mktime($hour, $minute, $second, $month, $day, $year);
909 $date = mktime($hour, $minute, $second, $month, $day, $year +
$interval);
913 $date = mktime($hour, $minute, $second, $month +
$interval, $day, $year);
917 $interval = $interval * 7;
918 $date = mktime($hour, $minute, $second, $month, $day +
$interval, $year);
922 $date = mktime($hour, $minute, $second, $month, $day +
$interval, $year);
926 $date = mktime($hour, $minute, $second +
$interval, $month, $day, $year);
930 $scheduleDate = explode("-", date("n-j-Y-H-i-s", $date));
933 $date['M'] = $scheduleDate[0];
934 $date['d'] = $scheduleDate[1];
935 $date['Y'] = $scheduleDate[2];
936 if ($dontCareTime == FALSE) {
937 $date['H'] = $scheduleDate[3];
938 $date['i'] = $scheduleDate[4];
939 $date['s'] = $scheduleDate[5];
945 * Check given format is valid for bith date.
946 * and retrun supportable birth date format w/ qf mapping.
949 * Given format ( eg 'M Y', 'Y M' ).
950 * return array of qfMapping and date parts for date format.
952 * @return array|null|string
954 public static function &checkBirthDateFormat($format = NULL) {
955 $birthDateFormat = NULL;
957 $birthDateFormat = self
::getDateFormat('birth');
960 $supportableFormats = array(
961 'mm/dd' => '%B %E%f',
962 'dd-mm' => '%E%f %B',
966 'dd/mm/yy' => '%E%f %B %Y',
969 if (array_key_exists($birthDateFormat, $supportableFormats)) {
970 $birthDateFormat = array('qfMapping' => $supportableFormats[$birthDateFormat]);
973 return $birthDateFormat;
977 * Resolves the given relative time interval into finite time limits.
979 * @param array $relativeTerm
980 * Relative time frame like this, previous, etc.
982 * Frequency unit like year, month, week etc.
985 * start date and end date for the relative time frame
987 public static function relativeToAbsolute($relativeTerm, $unit) {
989 $from = $to = $dateRange = array();
990 $from['H'] = $from['i'] = $from['s'] = 0;
994 switch ($relativeTerm) {
996 $from['d'] = $from['M'] = 1;
999 $to['Y'] = $from['Y'] = $now['year'];
1003 $from['M'] = $from['d'] = 1;
1006 $to['Y'] = $from['Y'] = $now['year'] - 1;
1009 case 'previous_before':
1010 $from['M'] = $from['d'] = 1;
1013 $to['Y'] = $from['Y'] = $now['year'] - 2;
1017 $from['M'] = $from['d'] = 1;
1020 $from['Y'] = $now['year'] - 2;
1021 $to['Y'] = $now['year'] - 1;
1027 $to['Y'] = $now['year'] - 1;
1032 $from['M'] = $from['d'] = 1;
1033 $from['Y'] = $now['year'];
1037 case 'greater_previous':
1040 $from['Y'] = $now['year'] - 1;
1045 $to['d'] = $now['mday'];
1046 $to['M'] = $now['mon'];
1047 $to['Y'] = $now['year'];
1049 $to['i'] = $to['s'] = 59;
1050 $from = self
::intervalAdd('year', -1, $to);
1051 $from = self
::intervalAdd('second', 1, $from);
1055 $from['M'] = $from['d'] = 1;
1056 $from['Y'] = $now['year'];
1058 $to['i'] = $to['s'] = 59;
1059 $to['d'] = $now['mday'];
1060 $to['M'] = $now['mon'];
1061 $to['Y'] = $now['year'];
1065 $to['d'] = $now['mday'];
1066 $to['M'] = $now['mon'];
1067 $to['Y'] = $now['year'];
1069 $to['i'] = $to['s'] = 59;
1070 $from = self
::intervalAdd('year', -2, $to);
1071 $from = self
::intervalAdd('second', 1, $from);
1075 $to['d'] = $now['mday'];
1076 $to['M'] = $now['mon'];
1077 $to['Y'] = $now['year'];
1079 $to['i'] = $to['s'] = 59;
1080 $from = self
::intervalAdd('year', -3, $to);
1081 $from = self
::intervalAdd('second', 1, $from);
1087 $to['Y'] = $now['year'];
1092 $from['M'] = $from['d'] = 1;
1095 $to['Y'] = $from['Y'] = $now['year'] +
1;
1099 $from['d'] = $now['mday'];
1100 $from['M'] = $now['mon'];
1101 $from['Y'] = $now['year'];
1102 $to['d'] = $now['mday'] - 1;
1103 $to['M'] = $now['mon'];
1104 $to['Y'] = $now['year'] +
1;
1110 $config = CRM_Core_Config
::singleton();
1111 $from['d'] = $config->fiscalYearStart
['d'];
1112 $from['M'] = $config->fiscalYearStart
['M'];
1113 $fYear = self
::calculateFiscalYear($from['d'], $from['M']);
1114 switch ($relativeTerm) {
1116 $from['Y'] = $fYear;
1117 $fiscalYear = mktime(0, 0, 0, $from['M'], $from['d'] - 1, $from['Y'] +
1);
1118 $fiscalEnd = explode('-', date("Y-m-d", $fiscalYear));
1120 $to['d'] = $fiscalEnd['2'];
1121 $to['M'] = $fiscalEnd['1'];
1122 $to['Y'] = $fiscalEnd['0'];
1126 $from['Y'] = $fYear - 1;
1127 $fiscalYear = mktime(0, 0, 0, $from['M'], $from['d'] - 1, $from['Y'] +
1);
1128 $fiscalEnd = explode('-', date("Y-m-d", $fiscalYear));
1129 $to['d'] = $fiscalEnd['2'];
1130 $to['M'] = $fiscalEnd['1'];
1131 $to['Y'] = $fiscalEnd['0'];
1135 $from['Y'] = $fYear +
1;
1136 $fiscalYear = mktime(0, 0, 0, $from['M'], $from['d'] - 1, $from['Y'] +
1);
1137 $fiscalEnd = explode('-', date("Y-m-d", $fiscalYear));
1138 $to['d'] = $fiscalEnd['2'];
1139 $to['M'] = $fiscalEnd['1'];
1140 $to['Y'] = $fiscalEnd['0'];
1146 switch ($relativeTerm) {
1149 $quarter = ceil($now['mon'] / 3);
1151 $from['M'] = (3 * $quarter) - 2;
1152 $to['M'] = 3 * $quarter;
1153 $to['Y'] = $from['Y'] = $now['year'];
1154 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $now['year']));
1159 $quarter = ceil($now['mon'] / 3);
1160 $quarter = $quarter - $difference;
1162 if ($quarter <= 0) {
1167 $from['M'] = (3 * $quarter) - 2;
1168 $to['M'] = 3 * $quarter;
1169 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1170 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1173 case 'previous_before':
1175 $quarter = ceil($now['mon'] / 3);
1176 $quarter = $quarter - $difference;
1178 if ($quarter <= 0) {
1183 $from['M'] = (3 * $quarter) - 2;
1184 $to['M'] = 3 * $quarter;
1185 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1186 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1191 $quarter = ceil($now['mon'] / 3);
1192 $current_quarter = $quarter;
1193 $quarter = $quarter - $difference;
1195 if ($quarter <= 0) {
1200 $from['M'] = (3 * $quarter) - 2;
1201 switch ($current_quarter) {
1203 $to['M'] = (4 * $quarter);
1207 $to['M'] = (4 * $quarter) +
3;
1211 $to['M'] = (4 * $quarter) +
2;
1215 $to['M'] = (4 * $quarter) +
1;
1218 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1219 if ($to['M'] > 12) {
1220 $to['M'] = 3 * ($quarter - 3);
1221 $to['Y'] = $now['year'];
1223 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1227 $quarter = ceil($now['mon'] / 3) - 1;
1229 if ($quarter <= 0) {
1233 $to['M'] = 3 * $quarter;
1234 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1235 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1240 $quarter = ceil($now['mon'] / 3);
1242 $from['M'] = (3 * $quarter) - 2;
1243 $from['Y'] = $now['year'];
1247 case 'greater_previous':
1248 $quarter = ceil($now['mon'] / 3) - 1;
1250 if ($quarter <= 0) {
1254 $from['M'] = 3 * $quarter;
1255 $from['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1256 $from['d'] = date('t', mktime(0, 0, 0, $from['M'], 1, $from['Y']));
1261 $to['d'] = $now['mday'];
1262 $to['M'] = $now['mon'];
1263 $to['Y'] = $now['year'];
1265 $to['i'] = $to['s'] = 59;
1266 $from = self
::intervalAdd('day', -90, $to);
1267 $from = self
::intervalAdd('second', 1, $from);
1271 $quarter = ceil($now['mon'] / 3);
1273 $from['M'] = (3 * $quarter) - 2;
1274 $from['Y'] = $now['year'];
1275 $to['d'] = $now['mday'];
1276 $to['M'] = $now['mon'];
1277 $to['Y'] = $now['year'];
1279 $to['i'] = $to['s'] = 59;
1283 $quarter = ceil($now['mon'] / 3);
1284 $to['M'] = 3 * $quarter;
1285 $to['Y'] = $now['year'];
1286 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $now['year']));
1293 $quarter = ceil($now['mon'] / 3);
1294 $quarter = $quarter - $difference;
1297 $now['year'] = $now['year'] +
1;
1300 if ($quarter <= 0) {
1305 $from['M'] = (3 * $quarter) - 2;
1306 $to['M'] = 3 * $quarter;
1307 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1308 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1312 $from['d'] = $now['mday'];
1313 $from['M'] = $now['mon'];
1314 $from['Y'] = $now['year'];
1316 $from['i'] = $to['s'] = 00;
1317 $to = self
::intervalAdd('day', 90, $from);
1318 $to = self
::intervalAdd('second', -1, $to);
1324 switch ($relativeTerm) {
1327 $to['d'] = date('t', mktime(0, 0, 0, $now['mon'], 1, $now['year']));
1328 $from['M'] = $to['M'] = $now['mon'];
1329 $from['Y'] = $to['Y'] = $now['year'];
1334 if ($now['mon'] == 1) {
1335 $from['M'] = $to['M'] = 12;
1336 $from['Y'] = $to['Y'] = $now['year'] - 1;
1339 $from['M'] = $to['M'] = $now['mon'] - 1;
1340 $from['Y'] = $to['Y'] = $now['year'];
1342 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1345 case 'previous_before':
1347 if ($now['mon'] < 3) {
1348 $from['M'] = $to['M'] = 10 +
$now['mon'];
1349 $from['Y'] = $to['Y'] = $now['year'] - 1;
1352 $from['M'] = $to['M'] = $now['mon'] - 2;
1353 $from['Y'] = $to['Y'] = $now['year'];
1355 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1360 if ($now['mon'] < 3) {
1361 $from['M'] = 10 +
$now['mon'];
1362 $from['Y'] = $now['year'] - 1;
1365 $from['M'] = $now['mon'] - 2;
1366 $from['Y'] = $now['year'];
1369 if ($now['mon'] == 1) {
1371 $to['Y'] = $now['year'] - 1;
1374 $to['M'] = $now['mon'] - 1;
1375 $to['Y'] = $now['year'];
1378 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1382 //before end of past month
1383 if ($now['mon'] == 1) {
1385 $to['Y'] = $now['year'] - 1;
1388 $to['M'] = $now['mon'] - 1;
1389 $to['Y'] = $now['year'];
1392 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1398 $from['M'] = $now['mon'];;
1399 $from['Y'] = $now['year'];
1403 case 'greater_previous':
1404 //from end of past month
1405 if ($now['mon'] == 1) {
1407 $from['Y'] = $now['year'] - 1;
1410 $from['M'] = $now['mon'] - 1;
1411 $from['Y'] = $now['year'];
1414 $from['d'] = date('t', mktime(0, 0, 0, $from['M'], 1, $from['Y']));
1419 $to['d'] = $now['mday'];
1420 $to['M'] = $now['mon'];
1421 $to['Y'] = $now['year'];
1423 $to['i'] = $to['s'] = 59;
1424 $from = self
::intervalAdd('day', -60, $to);
1425 $from = self
::intervalAdd('second', 1, $from);
1429 $to['d'] = $now['mday'];
1430 $to['M'] = $now['mon'];
1431 $to['Y'] = $now['year'];
1433 $to['i'] = $to['s'] = 59;
1434 $from = self
::intervalAdd('day', -30, $to);
1435 $from = self
::intervalAdd('second', 1, $from);
1440 $from['M'] = $now['mon'];;
1441 $from['Y'] = $now['year'];
1442 $to['d'] = $now['mday'];
1443 $to['M'] = $now['mon'];
1444 $to['Y'] = $now['year'];
1446 $to['i'] = $to['s'] = 59;
1451 $to['Y'] = $now['year'];
1452 $to['M'] = $now['mon'];
1453 $to['d'] = date('t', mktime(0, 0, 0, $now['mon'], 1, $now['year']));
1459 if ($now['mon'] == 12) {
1460 $from['M'] = $to['M'] = 1;
1461 $from['Y'] = $to['Y'] = $now['year'] +
1;
1464 $from['M'] = $to['M'] = $now['mon'] +
1;
1465 $from['Y'] = $to['Y'] = $now['year'];
1467 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1471 $from['d'] = $now['mday'];
1472 $from['M'] = $now['mon'];
1473 $from['Y'] = $now['year'];
1475 $from['i'] = $to['s'] = 00;
1476 $to = self
::intervalAdd('day', 30, $from);
1477 $to = self
::intervalAdd('second', -1, $to);
1481 $from['d'] = $now['mday'];
1482 $from['M'] = $now['mon'];
1483 $from['Y'] = $now['year'];
1485 $from['i'] = $to['s'] = 00;
1486 $to = self
::intervalAdd('day', 60, $from);
1487 $to = self
::intervalAdd('second', -1, $to);
1493 $weekFirst = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::LOCALIZATION_PREFERENCES_NAME
, 'weekBegins', NULL, 0);
1494 $thisDay = $now['wday'];
1495 if ($weekFirst > $thisDay) {
1496 $diffDay = $thisDay - $weekFirst +
7;
1499 $diffDay = $thisDay - $weekFirst;
1501 switch ($relativeTerm) {
1503 $from['d'] = $now['mday'];
1504 $from['M'] = $now['mon'];
1505 $from['Y'] = $now['year'];
1506 $from = self
::intervalAdd('day', -1 * ($diffDay), $from);
1507 $to = self
::intervalAdd('day', 6, $from);
1511 $from['d'] = $now['mday'];
1512 $from['M'] = $now['mon'];
1513 $from['Y'] = $now['year'];
1514 $from = self
::intervalAdd('day', -1 * ($diffDay) - 7, $from);
1515 $to = self
::intervalAdd('day', 6, $from);
1518 case 'previous_before':
1519 $from['d'] = $now['mday'];
1520 $from['M'] = $now['mon'];
1521 $from['Y'] = $now['year'];
1522 $from = self
::intervalAdd('day', -1 * ($diffDay) - 14, $from);
1523 $to = self
::intervalAdd('day', 6, $from);
1527 $from['d'] = $now['mday'];
1528 $from['M'] = $now['mon'];
1529 $from['Y'] = $now['year'];
1530 $from = self
::intervalAdd('day', -1 * ($diffDay) - 14, $from);
1531 $to = self
::intervalAdd('day', 13, $from);
1535 $to['d'] = $now['mday'];
1536 $to['M'] = $now['mon'];
1537 $to['Y'] = $now['year'];
1538 $to = self
::intervalAdd('day', -1 * ($diffDay) - 1, $to);
1543 $from['d'] = $now['mday'];
1544 $from['M'] = $now['mon'];
1545 $from['Y'] = $now['year'];
1546 $from = self
::intervalAdd('day', -1 * ($diffDay), $from);
1550 case 'greater_previous':
1551 $from['d'] = $now['mday'];
1552 $from['M'] = $now['mon'];
1553 $from['Y'] = $now['year'];
1554 $from = self
::intervalAdd('day', -1 * ($diffDay) - 1, $from);
1559 $to['d'] = $now['mday'];
1560 $to['M'] = $now['mon'];
1561 $to['Y'] = $now['year'];
1563 $to['i'] = $to['s'] = 59;
1564 $from = self
::intervalAdd('day', -7, $to);
1565 $from = self
::intervalAdd('second', 1, $from);
1569 $from['d'] = $now['mday'];
1570 $from['M'] = $now['mon'];
1571 $from['Y'] = $now['year'];
1572 $from = self
::intervalAdd('day', -1 * ($diffDay), $from);
1573 $to['d'] = $now['mday'];
1574 $to['M'] = $now['mon'];
1575 $to['Y'] = $now['year'];
1577 $to['i'] = $to['s'] = 59;
1581 $to['d'] = $now['mday'];
1582 $to['M'] = $now['mon'];
1583 $to['Y'] = $now['year'];
1585 $to = self
::intervalAdd('day', -1 * ($diffDay) +
6, $to);
1590 $from['d'] = $now['mday'];
1591 $from['M'] = $now['mon'];
1592 $from['Y'] = $now['year'];
1593 $from = self
::intervalAdd('day', -1 * ($diffDay) +
7, $from);
1594 $to = self
::intervalAdd('day', 6, $from);
1598 $from['d'] = $now['mday'];
1599 $from['M'] = $now['mon'];
1600 $from['Y'] = $now['year'];
1602 $from['i'] = $to['s'] = 00;
1603 $to = self
::intervalAdd('day', 7, $from);
1604 $to = self
::intervalAdd('second', -1, $to);
1610 switch ($relativeTerm) {
1612 $from['d'] = $to['d'] = $now['mday'];
1613 $from['M'] = $to['M'] = $now['mon'];
1614 $from['Y'] = $to['Y'] = $now['year'];
1618 $from['d'] = $now['mday'];
1619 $from['M'] = $now['mon'];
1620 $from['Y'] = $now['year'];
1621 $from = self
::intervalAdd('day', -1, $from);
1622 $to['d'] = $from['d'];
1623 $to['M'] = $from['M'];
1624 $to['Y'] = $from['Y'];
1627 case 'previous_before':
1628 $from['d'] = $now['mday'];
1629 $from['M'] = $now['mon'];
1630 $from['Y'] = $now['year'];
1631 $from = self
::intervalAdd('day', -2, $from);
1632 $to['d'] = $from['d'];
1633 $to['M'] = $from['M'];
1634 $to['Y'] = $from['Y'];
1638 $from['d'] = $to['d'] = $now['mday'];
1639 $from['M'] = $to['M'] = $now['mon'];
1640 $from['Y'] = $to['Y'] = $now['year'];
1641 $from = self
::intervalAdd('day', -2, $from);
1642 $to = self
::intervalAdd('day', -1, $to);
1646 $to['d'] = $now['mday'];
1647 $to['M'] = $now['mon'];
1648 $to['Y'] = $now['year'];
1653 $from['d'] = $now['mday'];
1654 $from['M'] = $now['mon'];;
1655 $from['Y'] = $now['year'];
1660 $to['d'] = $now['mday'];
1661 $to['M'] = $now['mon'];
1662 $to['Y'] = $now['year'];
1663 $to = self
::intervalAdd('day', 1, $to);
1664 $from['d'] = $to['d'];
1665 $from['M'] = $to['M'];
1666 $from['Y'] = $to['Y'];
1677 if (!empty($
$item)) {
1678 $dateRange[$item] = self
::format($
$item);
1681 $dateRange[$item] = NULL;
1688 * Calculate current fiscal year based on the fiscal month and day.
1690 * @param int $fyDate
1691 * Fiscal start date.
1693 * @param int $fyMonth
1694 * Fiscal Start Month.
1697 * $fy Current Fiscl Year
1699 public static function calculateFiscalYear($fyDate, $fyMonth) {
1700 $date = date("Y-m-d");
1701 $currentYear = date("Y");
1703 //recalculate the date because month 4::04 make the difference
1704 $fiscalYear = explode('-', date("Y-m-d", mktime(0, 0, 0, $fyMonth, $fyDate, $currentYear)));
1705 $fyDate = $fiscalYear[2];
1706 $fyMonth = $fiscalYear[1];
1707 $fyStartDate = date("Y-m-d", mktime(0, 0, 0, $fyMonth, $fyDate, $currentYear));
1709 if ($fyStartDate > $date) {
1710 $fy = intval(intval($currentYear) - 1);
1713 $fy = intval($currentYear);
1719 * Function to process date, convert to mysql format
1721 * @param string $date
1723 * @param string $time
1725 * @param bool|string $returnNullString 'null' needs to be returned
1726 * so that db oject will set null in db
1727 * @param string $format
1728 * Expected return date format.( default is mysql ).
1731 * date format that is excepted by mysql
1733 public static function processDate($date, $time = NULL, $returnNullString = FALSE, $format = 'YmdHis') {
1736 if ($returnNullString) {
1737 $mysqlDate = 'null';
1741 $mysqlDate = date($format, strtotime($date . ' ' . $time));
1748 * Function to convert mysql to date plugin format.
1750 * @param string $mysqlDate
1753 * @param null $formatType
1754 * @param null $format
1755 * @param null $timeFormat
1760 public static function setDateDefaults($mysqlDate = NULL, $formatType = NULL, $format = NULL, $timeFormat = NULL) {
1761 // if date is not passed assume it as today
1763 $mysqlDate = date('Y-m-d G:i:s');
1766 $config = CRM_Core_Config
::singleton();
1768 // get actual format
1769 $params = array('name' => $formatType);
1771 CRM_Core_DAO
::commonRetrieve('CRM_Core_DAO_PreferencesDate', $params, $values);
1773 if ($values['date_format']) {
1774 $format = $values['date_format'];
1777 if (isset($values['time_format'])) {
1778 $timeFormat = $values['time_format'];
1782 // now we set display date using js, hence we should always setdefault
1783 // 'm/d/Y' format. So that submitted value is alwats mm/dd/YY format
1784 // note that for date display we dynamically create text field
1787 $format = $config->dateInputFormat;
1790 // get actual format
1791 $actualPHPFormats = CRM_Core_SelectValues::datePluginToPHPFormats( );
1792 $dateFormat = CRM_Utils_Array::value( $format, $actualPHPFormats );
1795 $dateFormat = 'm/d/Y';
1796 $date = date($dateFormat, strtotime($mysqlDate));
1799 $timeFormat = $config->timeInputFormat
;
1802 $actualTimeFormat = "g:iA";
1803 $appendZeroLength = 7;
1804 if ($timeFormat > 1) {
1805 $actualTimeFormat = "G:i";
1806 $appendZeroLength = 5;
1809 $time = date($actualTimeFormat, strtotime($mysqlDate));
1811 // need to append zero for hours < 10
1812 if (strlen($time) < $appendZeroLength) {
1813 $time = '0' . $time;
1816 return array($date, $time);
1820 * Function get date format.
1822 * @param string $formatType
1823 * Date name e.g. birth.
1827 public static function getDateFormat($formatType = NULL) {
1830 $format = CRM_Core_DAO
::getFieldValue('CRM_Core_DAO_PreferencesDate',
1831 $formatType, 'date_format', 'name'
1836 $config = CRM_Core_Config
::singleton();
1837 $format = $config->dateInputFormat
;
1843 * Get the time in UTC for the current time. You can optionally send an offset from the current time if needed
1845 * @param int $offset
1846 * the offset from the current time in seconds.
1851 public static function getUTCTime($offset = 0) {
1852 $originalTimezone = date_default_timezone_get();
1853 date_default_timezone_set('UTC');
1854 $time = time() +
$offset;
1855 $now = date('YmdHis', $time);
1856 date_default_timezone_set($originalTimezone);
1865 * @return null|string
1867 public static function formatDate($date, $dateType) {
1868 $formattedDate = NULL;
1870 return $formattedDate;
1873 //1. first convert date to default format.
1874 //2. append time to default formatted date (might be removed during format)
1875 //3. validate date / date time.
1876 //4. If date and time then convert to default date time format.
1879 $dateParams = array($dateKey => $date);
1881 if (CRM_Utils_Date
::convertToDefaultDate($dateParams, $dateType, $dateKey)) {
1882 $dateVal = $dateParams[$dateKey];
1884 if ($dateType == 1) {
1886 if (preg_match("/(\s(([01]\d)|[2][0-3]):([0-5]\d))$/", $date, $matches)) {
1887 $ruleName = 'dateTime';
1888 if (strpos($date, '-') !== FALSE) {
1889 $dateVal .= array_shift($matches);
1895 $valid = CRM_Utils_Rule
::$ruleName($dateVal);
1898 //format date and time to default.
1899 if ($ruleName == 'dateTime') {
1900 $dateVal = CRM_Utils_Date
::customFormat(preg_replace("/(:|\s)?/", "", $dateVal), '%Y%m%d%H%i');
1901 //hack to add seconds
1904 $formattedDate = $dateVal;
1908 return $formattedDate;