CRM-14986 add function comments as pointer as to why isoToDate fn may be over-used
[civicrm-core.git] / CRM / Utils / Date.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
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. |
13 | |
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. |
18 | |
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 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35
36 /**
37 * Date utilties
38 */
39 class CRM_Utils_Date {
40
41 /**
42 * format a date by padding it with leading '0'.
43 *
44 * @param array $date ('Y', 'M', 'd')
45 * @param string $separator the seperator to use when formatting the date
46 * @param string $invalidDate what to return if the date is invalid
47 *
48 * @return string - formatted string for date
49 *
50 * @static
51 */
52 static function format($date, $separator = '', $invalidDate = 0) {
53 if (is_numeric($date) &&
54 ((strlen($date) == 8) || (strlen($date) == 14))
55 ) {
56 return $date;
57 }
58
59 if (!is_array($date) ||
60 CRM_Utils_System::isNull($date) ||
61 empty($date['Y'])
62 ) {
63 return $invalidDate;
64 }
65
66 $date['Y'] = (int ) $date['Y'];
67 if ($date['Y'] < 1000 || $date['Y'] > 2999) {
68 return $invalidDate;
69 }
70
71 if (array_key_exists('m', $date)) {
72 $date['M'] = $date['m'];
73 }
74 elseif (array_key_exists('F', $date)) {
75 $date['M'] = $date['F'];
76 }
77
78 if (CRM_Utils_Array::value('M', $date)) {
79 $date['M'] = (int ) $date['M'];
80 if ($date['M'] < 1 || $date['M'] > 12) {
81 return $invalidDate;
82 }
83 }
84 else {
85 $date['M'] = 1;
86 }
87
88 if (CRM_Utils_Array::value('d', $date)) {
89 $date['d'] = (int ) $date['d'];
90 }
91 else {
92 $date['d'] = 1;
93 }
94
95 if (!checkdate($date['M'], $date['d'], $date['Y'])) {
96 return $invalidDate;
97 }
98
99 $date['M'] = sprintf('%02d', $date['M']);
100 $date['d'] = sprintf('%02d', $date['d']);
101
102 $time = '';
103 if (CRM_Utils_Array::value('H', $date) != NULL ||
104 CRM_Utils_Array::value('h', $date) != NULL ||
105 CRM_Utils_Array::value('i', $date) != NULL ||
106 CRM_Utils_Array::value('s', $date) != NULL
107 ) {
108 // we have time too..
109 if (CRM_Utils_Array::value('h', $date)) {
110 if (CRM_Utils_Array::value('A', $date) == 'PM' or CRM_Utils_Array::value('a', $date) == 'pm') {
111 if ($date['h'] != 12) {
112 $date['h'] = $date['h'] + 12;
113 }
114 }
115 if ((CRM_Utils_Array::value('A', $date) == 'AM' or CRM_Utils_Array::value('a', $date) == 'am') &&
116 CRM_Utils_Array::value('h', $date) == 12
117 ) {
118 $date['h'] = '00';
119 }
120
121 $date['h'] = (int ) $date['h'];
122 }
123 else {
124 $date['h'] = 0;
125 }
126
127 // in 24-hour format the hour is under the 'H' key
128 if (CRM_Utils_Array::value('H', $date)) {
129 $date['H'] = (int) $date['H'];
130 }
131 else {
132 $date['H'] = 0;
133 }
134
135 if (CRM_Utils_Array::value('i', $date)) {
136 $date['i'] = (int ) $date['i'];
137 }
138 else {
139 $date['i'] = 0;
140 }
141
142 if ($date['h'] == 0 && $date['H'] != 0) {
143 $date['h'] = $date['H'];
144 }
145
146 if (CRM_Utils_Array::value('s', $date)) {
147 $date['s'] = (int ) $date['s'];
148 }
149 else {
150 $date['s'] = 0;
151 }
152
153 $date['h'] = sprintf('%02d', $date['h']);
154 $date['i'] = sprintf('%02d', $date['i']);
155 $date['s'] = sprintf('%02d', $date['s']);
156
157 if ($separator) {
158 $time = '&nbsp;';
159 }
160 $time .= $date['h'] . $separator . $date['i'] . $separator . $date['s'];
161 }
162
163 return $date['Y'] . $separator . $date['M'] . $separator . $date['d'] . $time;
164 }
165
166 /**
167 * return abbreviated weekday names according to the locale
168 *
169 * @return array 0-based array with abbreviated weekday names
170 *
171 * @static
172 */
173 static function &getAbbrWeekdayNames() {
174 static $abbrWeekdayNames;
175 if (!isset($abbrWeekdayNames)) {
176
177 // set LC_TIME and build the arrays from locale-provided names
178 // June 1st, 1970 was a Monday
179 CRM_Core_I18n::setLcTime();
180 for ($i = 0; $i < 7; $i++) {
181 $abbrWeekdayNames[$i] = strftime('%a', mktime(0, 0, 0, 6, $i, 1970));
182 }
183 }
184 return $abbrWeekdayNames;
185 }
186
187 /**
188 * return full weekday names according to the locale
189 *
190 * @return array 0-based array with full weekday names
191 *
192 * @static
193 */
194 static function &getFullWeekdayNames() {
195 static $fullWeekdayNames;
196 if (!isset($fullWeekdayNames)) {
197
198 // set LC_TIME and build the arrays from locale-provided names
199 // June 1st, 1970 was a Monday
200 CRM_Core_I18n::setLcTime();
201 for ($i = 0; $i < 7; $i++) {
202 $fullWeekdayNames[$i] = strftime('%A', mktime(0, 0, 0, 6, $i, 1970));
203 }
204 }
205 return $fullWeekdayNames;
206 }
207
208 /**
209 * return abbreviated month names according to the locale
210 *
211 * @return array 1-based array with abbreviated month names
212 *
213 * @static
214 */
215 static function &getAbbrMonthNames($month = FALSE) {
216 static $abbrMonthNames;
217 if (!isset($abbrMonthNames)) {
218
219 // set LC_TIME and build the arrays from locale-provided names
220 CRM_Core_I18n::setLcTime();
221 for ($i = 1; $i <= 12; $i++) {
222 $abbrMonthNames[$i] = strftime('%b', mktime(0, 0, 0, $i, 10, 1970));
223 }
224 }
225 if ($month) {
226 return $abbrMonthNames[$month];
227 }
228 return $abbrMonthNames;
229 }
230
231 /**
232 * return full month names according to the locale
233 *
234 * @return array 1-based array with full month names
235 *
236 * @static
237 */
238 static function &getFullMonthNames() {
239 static $fullMonthNames;
240 if (!isset($fullMonthNames)) {
241
242 // set LC_TIME and build the arrays from locale-provided names
243 CRM_Core_I18n::setLcTime();
244 for ($i = 1; $i <= 12; $i++) {
245 $fullMonthNames[$i] = strftime('%B', mktime(0, 0, 0, $i, 10, 1970));
246 }
247 }
248 return $fullMonthNames;
249 }
250
251 static function unixTime($string) {
252 if (empty($string)) {
253 return 0;
254 }
255 $parsedDate = date_parse($string);
256 return mktime(CRM_Utils_Array::value('hour', $parsedDate),
257 CRM_Utils_Array::value('minute', $parsedDate),
258 59,
259 CRM_Utils_Array::value('month', $parsedDate),
260 CRM_Utils_Array::value('day', $parsedDate),
261 CRM_Utils_Array::value('year', $parsedDate)
262 );
263 }
264
265 /**
266 * create a date and time string in a provided format
267 *
268 * %b - abbreviated month name ('Jan'..'Dec')
269 * %B - full month name ('January'..'December')
270 * %d - day of the month as a decimal number, 0-padded ('01'..'31')
271 * %e - day of the month as a decimal number, blank-padded (' 1'..'31')
272 * %E - day of the month as a decimal number ('1'..'31')
273 * %f - English ordinal suffix for the day of the month ('st', 'nd', 'rd', 'th')
274 * %H - hour in 24-hour format, 0-padded ('00'..'23')
275 * %I - hour in 12-hour format, 0-padded ('01'..'12')
276 * %k - hour in 24-hour format, blank-padded (' 0'..'23')
277 * %l - hour in 12-hour format, blank-padded (' 1'..'12')
278 * %m - month as a decimal number, 0-padded ('01'..'12')
279 * %M - minute, 0-padded ('00'..'60')
280 * %p - lowercase ante/post meridiem ('am', 'pm')
281 * %P - uppercase ante/post meridiem ('AM', 'PM')
282 * %Y - year as a decimal number including the century ('2005')
283 *
284 * @param string $date date and time in 'YYYY-MM-DD hh:mm:ss' format
285 * @param string $format the output format
286 * @param array $dateParts an array with the desired date parts
287 *
288 * @return string the $format-formatted $date
289 *
290 * @static
291 */
292 static function customFormat($dateString, $format = NULL, $dateParts = NULL) {
293 // 1-based (January) month names arrays
294 $abbrMonths = self::getAbbrMonthNames();
295 $fullMonths = self::getFullMonthNames();
296
297 if (!$format) {
298 $config = CRM_Core_Config::singleton();
299
300 if ($dateParts) {
301 if (array_intersect(array('h', 'H'), $dateParts)) {
302 $format = $config->dateformatDatetime;
303 }
304 elseif (array_intersect(array('d', 'j'), $dateParts)) {
305 $format = $config->dateformatFull;
306 }
307 elseif (array_intersect(array('m', 'M'), $dateParts)) {
308 $format = $config->dateformatPartial;
309 }
310 else {
311 $format = $config->dateformatYear;
312 }
313 }
314 else {
315 if (strpos($dateString, '-')) {
316 $month = (int) substr($dateString, 5, 2);
317 $day = (int) substr($dateString, 8, 2);
318 }
319 else {
320 $month = (int) substr($dateString, 4, 2);
321 $day = (int) substr($dateString, 6, 2);
322 }
323
324 if (strlen($dateString) > 10) {
325 $format = $config->dateformatDatetime;
326 }
327 elseif ($day > 0) {
328 $format = $config->dateformatFull;
329 }
330 elseif ($month > 0) {
331 $format = $config->dateformatPartial;
332 }
333 else {
334 $format = $config->dateformatYear;
335 }
336 }
337 }
338
339 if ($dateString) {
340 if (strpos($dateString, '-')) {
341 $year = (int) substr($dateString, 0, 4);
342 $month = (int) substr($dateString, 5, 2);
343 $day = (int) substr($dateString, 8, 2);
344
345 $hour24 = (int) substr($dateString, 11, 2);
346 $minute = (int) substr($dateString, 14, 2);
347 }
348 else {
349 $year = (int) substr($dateString, 0, 4);
350 $month = (int) substr($dateString, 4, 2);
351 $day = (int) substr($dateString, 6, 2);
352
353 $hour24 = (int) substr($dateString, 8, 2);
354 $minute = (int) substr($dateString, 10, 2);
355 }
356
357 if ($day % 10 == 1 and $day != 11) {
358 $suffix = 'st';
359 }
360 elseif ($day % 10 == 2 and $day != 12) {
361 $suffix = 'nd';
362 }
363 elseif ($day % 10 == 3 and $day != 13) {
364 $suffix = 'rd';
365 }
366 else {
367 $suffix = 'th';
368 }
369
370 if ($hour24 < 12) {
371 if ($hour24 == 00) {
372 $hour12 = 12;
373 }
374 else {
375 $hour12 = $hour24;
376 }
377 $type = 'AM';
378 }
379 else {
380 if ($hour24 == 12) {
381 $hour12 = 12;
382 }
383 else {
384 $hour12 = $hour24 - 12;
385 }
386 $type = 'PM';
387 }
388
389 $date = array(
390 '%b' => CRM_Utils_Array::value($month, $abbrMonths),
391 '%B' => CRM_Utils_Array::value($month, $fullMonths),
392 '%d' => $day > 9 ? $day : '0' . $day,
393 '%e' => $day > 9 ? $day : ' ' . $day,
394 '%E' => $day,
395 '%f' => $suffix,
396 '%H' => $hour24 > 9 ? $hour24 : '0' . $hour24,
397 '%h' => $hour12 > 9 ? $hour12 : '0' . $hour12,
398 '%I' => $hour12 > 9 ? $hour12 : '0' . $hour12,
399 '%k' => $hour24 > 9 ? $hour24 : ' ' . $hour24,
400 '%l' => $hour12 > 9 ? $hour12 : ' ' . $hour12,
401 '%m' => $month > 9 ? $month : '0' . $month,
402 '%M' => $minute > 9 ? $minute : '0' . $minute,
403 '%i' => $minute > 9 ? $minute : '0' . $minute,
404 '%p' => strtolower($type),
405 '%P' => $type,
406 '%A' => $type,
407 '%Y' => $year,
408 );
409
410 return strtr($format, $date);
411 }
412 else {
413 return '';
414 }
415 }
416
417 /**
418 * converts the date/datetime from MySQL format to ISO format
419 *
420 * @param string $mysql date/datetime in MySQL format
421 *
422 * @return string date/datetime in ISO format
423 * @static
424 */
425 static function mysqlToIso($mysql) {
426 $year = substr($mysql, 0, 4);
427 $month = substr($mysql, 4, 2);
428 $day = substr($mysql, 6, 2);
429 $hour = substr($mysql, 8, 2);
430 $minute = substr($mysql, 10, 2);
431 $second = substr($mysql, 12, 2);
432
433 $iso = '';
434 if ($year) {
435 $iso .= "$year";
436 }
437 if ($month) {
438 $iso .= "-$month";
439 if ($day) {
440 $iso .= "-$day";
441 }
442 }
443
444 if ($hour) {
445 $iso .= " $hour";
446 if ($minute) {
447 $iso .= ":$minute";
448 if ($second) {
449 $iso .= ":$second";
450 }
451 }
452 }
453 return $iso;
454 }
455
456 /**
457 * converts the date/datetime from ISO format to MySQL format
458 * Note that until CRM-14986/ 4.4.7 this was required whenever the pattern $dao->find(TRUE): $dao->save(); was
459 * used to update an object with a date field was used. The DAO now checks for a '-' in date field strings
460 * & runs this function if the - appears - meaning it is likely redundant in the form & BAO layers
461 *
462 * @param string $iso date/datetime in ISO format
463 *
464 * @return string date/datetime in MySQL format
465 * @static
466 */
467 static function isoToMysql($iso) {
468 $dropArray = array('-' => '', ':' => '', ' ' => '');
469 return strtr($iso, $dropArray);
470 }
471
472 /**
473 * converts the any given date to default date format.
474 *
475 * @param array $params has given date-format
476 * @param int $dateType type of date
477 * @param string $dateParam index of params
478 * @static
479 */
480 static function convertToDefaultDate(&$params, $dateType, $dateParam) {
481 $now = getDate();
482 $cen = substr($now['year'], 0, 2);
483 $prevCen = $cen - 1;
484
485 $value = NULL;
486 if (CRM_Utils_Array::value($dateParam, $params)) {
487 // suppress hh:mm or hh:mm:ss if it exists CRM-7957
488 $value = preg_replace("/(\s(([01]\d)|[2][0-3])(:([0-5]\d)){1,2})$/", "", $params[$dateParam]);
489 }
490
491 switch ($dateType) {
492 case 1:
493 if (!preg_match('/^\d\d\d\d-?(\d|\d\d)-?(\d|\d\d)$/', $value)) {
494 return FALSE;
495 }
496 break;
497
498 case 2:
499 if (!preg_match('/^(\d|\d\d)[-\/](\d|\d\d)[-\/]\d\d$/', $value)) {
500 return FALSE;
501 }
502 break;
503
504 case 4:
505 if (!preg_match('/^(\d|\d\d)[-\/](\d|\d\d)[-\/]\d\d\d\d$/', $value)) {
506 return FALSE;
507 }
508 break;
509
510 case 8:
511 if (!preg_match('/^[A-Za-z]*.[ \t]?\d\d\,[ \t]?\d\d\d\d$/', $value)) {
512 return FALSE;
513 }
514 break;
515
516 case 16:
517 if (!preg_match('/^\d\d-[A-Za-z]{3}.*-\d\d$/', $value) && !preg_match('/^\d\d[-\/]\d\d[-\/]\d\d$/', $value)) {
518 return FALSE;
519 }
520 break;
521
522 case 32:
523 if (!preg_match('/^(\d|\d\d)[-\/](\d|\d\d)[-\/]\d\d\d\d/', $value)) {
524 return FALSE;
525 }
526 break;
527 }
528
529 if ($dateType == 1) {
530 $formattedDate = explode("-", $value);
531 if (count($formattedDate) == 3) {
532 $year = (int) $formattedDate[0];
533 $month = (int) $formattedDate[1];
534 $day = (int) $formattedDate[2];
535 }
536 elseif (count($formattedDate) == 1 && (strlen($value) == 8)) {
537 return TRUE;
538 }
539 else {
540 return FALSE;
541 }
542 }
543
544
545 if ($dateType == 2 || $dateType == 4) {
546 $formattedDate = explode("/", $value);
547 if (count($formattedDate) != 3) {
548 $formattedDate = explode("-", $value);
549 }
550 if (count($formattedDate) == 3) {
551 $year = (int) $formattedDate[2];
552 $month = (int) $formattedDate[0];
553 $day = (int) $formattedDate[1];
554 }
555 else {
556 return FALSE;
557 }
558 }
559 if ($dateType == 8) {
560 $dateArray = explode(' ', $value);
561 // ignore comma(,)
562 $dateArray[1] = (int) substr($dateArray[1], 0, 2);
563
564 $monthInt = 0;
565 $fullMonths = self::getFullMonthNames();
566 foreach ($fullMonths as $key => $val) {
567 if (strtolower($dateArray[0]) == strtolower($val)) {
568 $monthInt = $key;
569 break;
570 }
571 }
572 if (!$monthInt) {
573 $abbrMonths = self::getAbbrMonthNames();
574 foreach ($abbrMonths as $key => $val) {
575 if (strtolower(trim($dateArray[0], ".")) == strtolower($val)) {
576 $monthInt = $key;
577 break;
578 }
579 }
580 }
581 $year = (int) $dateArray[2];
582 $day = (int) $dateArray[1];
583 $month = (int) $monthInt;
584 }
585 if ($dateType == 16) {
586 $dateArray = explode('-', $value);
587 if (count($dateArray) != 3) {
588 $dateArray = explode('/', $value);
589 }
590
591 if (count($dateArray) == 3) {
592 $monthInt = 0;
593 $fullMonths = self::getFullMonthNames();
594 foreach ($fullMonths as $key => $val) {
595 if (strtolower($dateArray[1]) == strtolower($val)) {
596 $monthInt = $key;
597 break;
598 }
599 }
600 if (!$monthInt) {
601 $abbrMonths = self::getAbbrMonthNames();
602 foreach ($abbrMonths as $key => $val) {
603 if (strtolower(trim($dateArray[1], ".")) == strtolower($val)) {
604 $monthInt = $key;
605 break;
606 }
607 }
608 }
609 if (!$monthInt) {
610 $monthInt = $dateArray[1];
611 }
612
613 $year = (int) $dateArray[2];
614 $day = (int) $dateArray[0];
615 $month = (int) $monthInt;
616 }
617 else {
618 return FALSE;
619 }
620 }
621 if ($dateType == 32) {
622 $formattedDate = explode("/", $value);
623 if (count($formattedDate) == 3) {
624 $year = (int) $formattedDate[2];
625 $month = (int) $formattedDate[1];
626 $day = (int) $formattedDate[0];
627 }
628 else {
629 return FALSE;
630 }
631 }
632
633 $month = ($month < 10) ? "0" . "$month" : $month;
634 $day = ($day < 10) ? "0" . "$day" : $day;
635
636 $year = (int ) $year;
637 // simple heuristic to determine what century to use
638 // 00 - 20 is always 2000 - 2020
639 // 21 - 99 is always 1921 - 1999
640 if ($year < 21) {
641 $year = (strlen($year) == 1) ? $cen . '0' . $year : $cen . $year;
642 }
643 elseif ($year < 100) {
644 $year = $prevCen . $year;
645 }
646
647 if ($params[$dateParam]) {
648 $params[$dateParam] = "$year$month$day";
649 }
650 //if month is invalid return as error
651 if ($month !== '00' && $month <= 12) {
652 return TRUE;
653 }
654 return FALSE;
655 }
656
657 static function isDate(&$date) {
658 if (CRM_Utils_System::isNull($date)) {
659 return FALSE;
660 }
661 return TRUE;
662 }
663
664 static function currentDBDate($timeStamp = NULL) {
665 return $timeStamp ? date('YmdHis', $timeStamp) : date('YmdHis');
666 }
667
668 static function overdue($date, $now = NULL) {
669 $mysqlDate = self::isoToMysql($date);
670 if (!$now) {
671 $now = self::currentDBDate();
672 }
673 else {
674 $now = self::isoToMysql($now);
675 }
676
677 return ($mysqlDate >= $now) ? FALSE : TRUE;
678 }
679
680 /**
681 * Function to get customized today
682 *
683 * This function is used for getting customized today. To get
684 * actuall today pass 'dayParams' as null. or else pass the day,
685 * month, year values as array values
686 * Example: $dayParams = array(
687 'day' => '25', 'month' => '10',
688 * 'year' => '2007' );
689 *
690 * @param Array $dayParams Array of the day, month, year
691 * values.
692 * @param string $format expected date format( default
693 * format is 2007-12-21 )
694 *
695 * @return string Return the customized todays date (Y-m-d)
696 * @static
697 */
698 static function getToday($dayParams = NULL, $format = "Y-m-d") {
699 if (is_null($dayParams) || empty($dayParams)) {
700 $today = date($format);
701 }
702 else {
703 $today = date($format, mktime(0, 0, 0,
704 $dayParams['month'],
705 $dayParams['day'],
706 $dayParams['year']
707 ));
708 }
709
710 return $today;
711 }
712
713 /**
714 * Function to find whether today's date lies in
715 * the given range
716 *
717 * @param date $startDate start date for the range
718 * @param date $endDate end date for the range
719 *
720 * @return true todays date is in the given date range
721 * @static
722 */
723 static function getRange($startDate, $endDate) {
724 $today = date("Y-m-d");
725 $mysqlStartDate = self::isoToMysql($startDate);
726 $mysqlEndDate = self::isoToMysql($endDate);
727 $mysqlToday = self::isoToMysql($today);
728
729 if ((isset($mysqlStartDate) && isset($mysqlEndDate)) && (($mysqlToday >= $mysqlStartDate) && ($mysqlToday <= $mysqlEndDate))) {
730 return TRUE;
731 }
732 elseif ((isset($mysqlStartDate) && !isset($mysqlEndDate)) && (($mysqlToday >= $mysqlStartDate))) {
733 return TRUE;
734 }
735 elseif ((!isset($mysqlStartDate) && isset($mysqlEndDate)) && (($mysqlToday <= $mysqlEndDate))) {
736 return TRUE;
737 }
738 return FALSE;
739 }
740
741 /**
742 * Function to get start date and end from
743 * the given relative term and unit
744 *
745 * @param date $relative eg: term.unit
746 *
747 * @return array start date, end date
748 * @static
749 */
750 static function getFromTo($relative, $from, $to) {
751 if ($relative) {
752 list($term, $unit) = explode('.', $relative);
753 $dateRange = self::relativeToAbsolute($term, $unit);
754 $from = $dateRange['from'];
755 //Take only Date Part, Sometime Time part is also present in 'to'
756 $to = substr($dateRange['to'], 0, 8);
757 }
758
759 $from = self::processDate($from);
760 $to = self::processDate($to, '235959');
761
762 return array($from, $to);
763 }
764
765 /**
766 * Function to calculate Age in Years if greater than one year else in months
767 *
768 * @param date $birthDate Birth Date
769 *
770 * @return int array $results contains years or months
771 * @access public
772 * @static
773 */
774 static public function calculateAge($birthDate) {
775 $results = array();
776 $formatedBirthDate = CRM_Utils_Date::customFormat($birthDate, '%Y-%m-%d');
777
778 $bDate = explode('-', $formatedBirthDate);
779 $birthYear = $bDate[0];
780 $birthMonth = $bDate[1];
781 $birthDay = $bDate[2];
782 $year_diff = date("Y") - $birthYear;
783
784 // don't calculate age CRM-3143
785 if ($birthYear == '1902') {
786 return $results;
787 }
788
789 switch ($year_diff) {
790 case 1:
791 $month = (12 - $birthMonth) + date("m");
792 if ($month < 12) {
793 if (date("d") < $birthDay) {
794 $month--;
795 }
796 $results['months'] = $month;
797 }
798 elseif ($month == 12 && (date("d") < $birthDay)) {
799 $results['months'] = $month - 1;
800 }
801 else {
802 $results['years'] = $year_diff;
803 }
804 break;
805
806 case 0:
807 $month = date("m") - $birthMonth;
808 $results['months'] = $month;
809 break;
810
811 default:
812 $results['years'] = $year_diff;
813 if ((date("m") < $birthMonth) || (date("m") == $birthMonth) && (date("d") < $birthDay)) {
814 $results['years']--;
815 }
816 }
817
818 return $results;
819 }
820
821 /**
822 * Function to calculate next payment date according to provided unit & interval
823 *
824 * @param string $unit frequency unit like year,month, week etc..
825 *
826 * @param int $interval frequency interval.
827 *
828 * @param array $date start date of pledge.
829 *
830 * @return array $result contains new date with added interval
831 * @access public
832 */
833 static function intervalAdd($unit, $interval, $date, $dontCareTime = FALSE) {
834 if (is_array($date)) {
835 $hour = CRM_Utils_Array::value('H', $date);
836 $minute = CRM_Utils_Array::value('i', $date);
837 $second = CRM_Utils_Array::value('s', $date);
838 $month = CRM_Utils_Array::value('M', $date);
839 $day = CRM_Utils_Array::value('d', $date);
840 $year = CRM_Utils_Array::value('Y', $date);
841 }
842 else {
843 extract(date_parse($date));
844 }
845 $date = mktime($hour, $minute, $second, $month, $day, $year);
846 switch ($unit) {
847 case 'year':
848 $date = mktime($hour, $minute, $second, $month, $day, $year + $interval);
849 break;
850
851 case 'month':
852 $date = mktime($hour, $minute, $second, $month + $interval, $day, $year);
853 break;
854
855 case 'week':
856 $interval = $interval * 7;
857 $date = mktime($hour, $minute, $second, $month, $day + $interval, $year);
858 break;
859
860 case 'day':
861 $date = mktime($hour, $minute, $second, $month, $day + $interval, $year);
862 break;
863
864 case 'second':
865 $date = mktime($hour, $minute, $second + $interval, $month, $day, $year);
866 break;
867 }
868
869 $scheduleDate = explode("-", date("n-j-Y-H-i-s", $date));
870
871 $date = array();
872 $date['M'] = $scheduleDate[0];
873 $date['d'] = $scheduleDate[1];
874 $date['Y'] = $scheduleDate[2];
875 if ($dontCareTime == FALSE) {
876 $date['H'] = $scheduleDate[3];
877 $date['i'] = $scheduleDate[4];
878 $date['s'] = $scheduleDate[5];
879 }
880 return $date;
881 }
882
883 /**
884 * function to check given format is valid for bith date.
885 * and retrun supportable birth date format w/ qf mapping.
886 *
887 * @param $format given format ( eg 'M Y', 'Y M' )
888 * return array of qfMapping and date parts for date format.
889 */
890 static function &checkBirthDateFormat($format = NULL) {
891 $birthDateFormat = NULL;
892 if (!$format) {
893 $birthDateFormat = self::getDateFormat('birth');
894 }
895
896 $supportableFormats = array(
897 'mm/dd' => '%B %E%f',
898 'dd-mm' => '%E%f %B',
899 'yy-mm' => '%Y %B',
900 'M yy' => '%b %Y',
901 'yy' => '%Y',
902 'dd/mm/yy' => '%E%f %B %Y',
903 );
904
905 if (array_key_exists($birthDateFormat, $supportableFormats)) {
906 $birthDateFormat = array('qfMapping' => $supportableFormats[$birthDateFormat]);
907 }
908
909 return $birthDateFormat;
910 }
911
912 /**
913 * resolves the given relative time interval into finite time limits
914 *
915 * @param array $relativeTerm relative time frame like this, previous, etc
916 * @param int $unit frequency unit like year, month, week etc..
917 *
918 * @return array $dateRange start date and end date for the relative time frame
919 * @static
920 */
921 static function relativeToAbsolute($relativeTerm, $unit) {
922 $now = getDate();
923 $from = $to = $dateRange = array();
924 $from['H'] = $from['i'] = $from['s'] = 0;
925
926 switch ($unit) {
927 case 'year':
928 switch ($relativeTerm) {
929 case 'this':
930 $from['d'] = $from['M'] = 1;
931 $to['d'] = 31;
932 $to['M'] = 12;
933 $to['Y'] = $from['Y'] = $now['year'];
934 break;
935
936 case 'previous':
937 $from['M'] = $from['d'] = 1;
938 $to['d'] = 31;
939 $to['M'] = 12;
940 $to['Y'] = $from['Y'] = $now['year'] - 1;
941 break;
942
943 case 'previous_before':
944 $from['M'] = $from['d'] = 1;
945 $to['d'] = 31;
946 $to['M'] = 12;
947 $to['Y'] = $from['Y'] = $now['year'] - 2;
948 break;
949
950 case 'previous_2':
951 $from['M'] = $from['d'] = 1;
952 $to['d'] = 31;
953 $to['M'] = 12;
954 $from['Y'] = $now['year'] - 2;
955 $to['Y'] = $now['year'] - 1;
956 break;
957
958 case 'earlier':
959 $to['d'] = 31;
960 $to['M'] = 12;
961 $to['Y'] = $now['year'] - 1;
962 unset($from);
963 break;
964
965 case 'greater':
966 $from['M'] = $from['d'] = 1;
967 $from['Y'] = $now['year'];
968 unset($to);
969 break;
970
971 case 'ending':
972 $to['d'] = $now['mday'];
973 $to['M'] = $now['mon'];
974 $to['Y'] = $now['year'];
975 $to['H'] = 23;
976 $to['i'] = $to['s'] = 59;
977 $from = self::intervalAdd('year', -1, $to);
978 $from = self::intervalAdd('second', 1, $from);
979 break;
980
981 case 'current':
982 $from['M'] = $from['d'] = 1;
983 $from['Y'] = $now['year'];
984 $to['H'] = 23;
985 $to['i'] = $to['s'] = 59;
986 $to['d'] = $now['mday'];
987 $to['M'] = $now['mon'];
988 $to['Y'] = $now['year'];
989 break;
990
991 case 'ending_2':
992 $to['d'] = $now['mday'];
993 $to['M'] = $now['mon'];
994 $to['Y'] = $now['year'];
995 $to['H'] = 23;
996 $to['i'] = $to['s'] = 59;
997 $from = self::intervalAdd('year', -2, $to);
998 $from = self::intervalAdd('second', 1, $from);
999 break;
1000
1001 case 'ending_3':
1002 $to['d'] = $now['mday'];
1003 $to['M'] = $now['mon'];
1004 $to['Y'] = $now['year'];
1005 $to['H'] = 23;
1006 $to['i'] = $to['s'] = 59;
1007 $from = self::intervalAdd('year', -3, $to);
1008 $from = self::intervalAdd('second', 1, $from);
1009 break;
1010 }
1011 break;
1012
1013 case 'fiscal_year':
1014 $config = CRM_Core_Config::singleton();
1015 $from['d'] = $config->fiscalYearStart['d'];
1016 $from['M'] = $config->fiscalYearStart['M'];
1017 $fYear = self::calculateFiscalYear($from['d'], $from['M']);
1018 switch ($relativeTerm) {
1019 case 'this':
1020 $from['Y'] = $fYear;
1021 $fiscalYear = mktime(0, 0, 0, $from['M'], $form['d'], $from['Y'] + 1);
1022 $fiscalEnd = explode('-', date("Y-m-d", $fiscalYear));
1023
1024 $to['d'] = $fiscalEnd['2'];
1025 $to['M'] = $fiscalEnd['1'];
1026 $to['Y'] = $fiscalEnd['0'];
1027 break;
1028
1029 case 'previous':
1030 $from['Y'] = $fYear - 1;
1031 $fiscalYear = mktime(0, 0, 0, $from['M'], $form['d'], $from['Y'] + 1);
1032 $fiscalEnd = explode('-', date("Y-m-d", $fiscalYear));
1033
1034 $to['d'] = $fiscalEnd['2'];
1035 $to['M'] = $fiscalEnd['1'];
1036 $to['Y'] = $fiscalEnd['0'];
1037 break;
1038 }
1039 break;
1040
1041 case 'quarter':
1042 switch ($relativeTerm) {
1043 case 'this':
1044
1045 $quarter = ceil($now['mon'] / 3);
1046 $from['d'] = 1;
1047 $from['M'] = (3 * $quarter) - 2;
1048 $to['M'] = 3 * $quarter;
1049 $to['Y'] = $from['Y'] = $now['year'];
1050 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $now['year']));
1051 break;
1052
1053 case 'previous':
1054 $difference = 1;
1055 $quarter = ceil($now['mon'] / 3);
1056 $quarter = $quarter - $difference;
1057 $subtractYear = 0;
1058 if ($quarter <= 0) {
1059 $subtractYear = 1;
1060 $quarter += 4;
1061 }
1062 $from['d'] = 1;
1063 $from['M'] = (3 * $quarter) - 2;
1064 $to['M'] = 3 * $quarter;
1065 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1066 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1067 break;
1068
1069 case 'previous_before':
1070 $difference = 2;
1071 $quarter = ceil($now['mon'] / 3);
1072 $quarter = $quarter - $difference;
1073 if ($quarter <= 0) {
1074 $subtractYear = 1;
1075 $quarter += 4;
1076 }
1077 $from['d'] = 1;
1078 $from['M'] = (3 * $quarter) - 2;
1079 $to['M'] = 3 * $quarter;
1080 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1081 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1082 break;
1083
1084 case 'previous_2':
1085 $difference = 2;
1086 $quarter = ceil($now['mon'] / 3);
1087 $current_quarter = $quarter;
1088 $quarter = $quarter - $difference;
1089 $subtractYear = 0;
1090 if ($quarter <= 0) {
1091 $subtractYear = 1;
1092 $quarter += 4;
1093 }
1094 $from['d'] = 1;
1095 $from['M'] = (3 * $quarter) - 2;
1096 switch ($current_quarter) {
1097 case 1:
1098 $to['M'] = (4 * $quarter);
1099 break;
1100
1101 case 2:
1102 $to['M'] = (4 * $quarter) + 3;
1103 break;
1104
1105 case 3:
1106 $to['M'] = (4 * $quarter) + 2;
1107 break;
1108
1109 case 4:
1110 $to['M'] = (4 * $quarter) + 1;
1111 break;
1112 }
1113 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1114 if ($to['M'] > 12) {
1115 $to['M'] = 3 * ($quarter - 3);
1116 $to['Y'] = $now['year'];
1117 }
1118 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1119 break;
1120
1121 case 'earlier':
1122 $quarter = ceil($now['mon'] / 3) - 1;
1123 if ($quarter <= 0) {
1124 $subtractYear = 1;
1125 $quarter += 4;
1126 }
1127 $to['M'] = 3 * $quarter;
1128 $to['Y'] = $from['Y'] = $now['year'] - $subtractYear;
1129 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1130 unset($from);
1131 break;
1132
1133 case 'greater':
1134 $quarter = ceil($now['mon'] / 3);
1135 $from['d'] = 1;
1136 $from['M'] = (3 * $quarter) - 2;
1137 $from['Y'] = $now['year'];
1138 unset($to);
1139 break;
1140
1141 case 'ending':
1142 $to['d'] = $now['mday'];
1143 $to['M'] = $now['mon'];
1144 $to['Y'] = $now['year'];
1145 $to['H'] = 23;
1146 $to['i'] = $to['s'] = 59;
1147 $from = self::intervalAdd('month', -3, $to);
1148 $from = self::intervalAdd('second', 1, $from);
1149 break;
1150
1151 case 'current':
1152 $quarter = ceil($now['mon'] / 3);
1153 $from['d'] = 1;
1154 $from['M'] = (3 * $quarter) - 2;
1155 $from['Y'] = $now['year'];
1156 $to['d'] = $now['mday'];
1157 $to['M'] = $now['mon'];
1158 $to['Y'] = $now['year'];
1159 $to['H'] = 23;
1160 $to['i'] = $to['s'] = 59;
1161 break;
1162 }
1163 break;
1164
1165 case 'month':
1166 switch ($relativeTerm) {
1167 case 'this':
1168 $from['d'] = 1;
1169 $to['d'] = date('t', mktime(0, 0, 0, $now['mon'], 1, $now['year']));
1170 $from['M'] = $to['M'] = $now['mon'];
1171 $from['Y'] = $to['Y'] = $now['year'];
1172 break;
1173
1174 case 'previous':
1175 $from['d'] = 1;
1176 if ($now['mon'] == 1) {
1177 $from['M'] = $to['M'] = 12;
1178 $from['Y'] = $to['Y'] = $now['year'] - 1;
1179 }
1180 else {
1181 $from['M'] = $to['M'] = $now['mon'] - 1;
1182 $from['Y'] = $to['Y'] = $now['year'];
1183 }
1184 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1185 break;
1186
1187 case 'previous_before':
1188 $from['d'] = 1;
1189 if ($now['mon'] < 3) {
1190 $from['M'] = $to['M'] = 10 + $now['mon'];
1191 $from['Y'] = $to['Y'] = $now['year'] - 1;
1192 }
1193 else {
1194 $from['M'] = $to['M'] = $now['mon'] - 2;
1195 $from['Y'] = $to['Y'] = $now['year'];
1196 }
1197 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1198 break;
1199
1200 case 'previous_2':
1201 $from['d'] = 1;
1202 if ($now['mon'] < 3) {
1203 $from['M'] = 10 + $now['mon'];
1204 $from['Y'] = $now['year'] - 1;
1205 }
1206 else {
1207 $from['M'] = $now['mon'] - 2;
1208 $from['Y'] = $now['year'];
1209 }
1210
1211 if ($now['mon'] == 1) {
1212 $to['M'] = 12;
1213 $to['Y'] = $now['year'] - 1;
1214 }
1215 else {
1216 $to['M'] = $now['mon'] - 1;
1217 $to['Y'] = $now['year'];
1218 }
1219
1220 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1221 break;
1222
1223 case 'earlier':
1224 //before end of past month
1225 if ($now['mon'] == 1) {
1226 $to['M'] = 12;
1227 $to['Y'] = $now['year'] - 1;
1228 }
1229 else {
1230 $to['M'] = $now['mon'] - 1;
1231 $to['Y'] = $now['year'];
1232 }
1233
1234 $to['d'] = date('t', mktime(0, 0, 0, $to['M'], 1, $to['Y']));
1235 unset($from);
1236 break;
1237
1238 case 'greater':
1239 $from['d'] = 1;
1240 $from['M'] = $now['mon'];;
1241 $from['Y'] = $now['year'];
1242 unset($to);
1243 break;
1244
1245 case 'ending':
1246 $to['d'] = $now['mday'];
1247 $to['M'] = $now['mon'];
1248 $to['Y'] = $now['year'];
1249 $to['H'] = 23;
1250 $to['i'] = $to['s'] = 59;
1251 $from = self::intervalAdd('month', -1, $to);
1252 $from = self::intervalAdd('second', 1, $from);
1253 break;
1254
1255 case 'current':
1256 $from['d'] = 1;
1257 $from['M'] = $now['mon'];;
1258 $from['Y'] = $now['year'];
1259 $to['d'] = $now['mday'];
1260 $to['M'] = $now['mon'];
1261 $to['Y'] = $now['year'];
1262 $to['H'] = 23;
1263 $to['i'] = $to['s'] = 59;
1264 break;
1265 }
1266 break;
1267
1268 case 'week':
1269 switch ($relativeTerm) {
1270 case 'this':
1271 $from['d'] = $now['mday'];
1272 $from['M'] = $now['mon'];
1273 $from['Y'] = $now['year'];
1274 $from = self::intervalAdd('day', -1 * ($now['wday']), $from);
1275 $to = self::intervalAdd('day', 6, $from);
1276 break;
1277
1278 case 'previous':
1279 $from['d'] = $now['mday'];
1280 $from['M'] = $now['mon'];
1281 $from['Y'] = $now['year'];
1282 $from = self::intervalAdd('day', -1 * ($now['wday']) - 7, $from);
1283 $to = self::intervalAdd('day', 6, $from);
1284 break;
1285
1286 case 'previous_before':
1287 $from['d'] = $now['mday'];
1288 $from['M'] = $now['mon'];
1289 $from['Y'] = $now['year'];
1290 $from = self::intervalAdd('day', -1 * ($now['wday']) - 14, $from);
1291 $to = self::intervalAdd('day', 6, $from);
1292 break;
1293
1294 case 'previous_2':
1295 $from['d'] = $now['mday'];
1296 $from['M'] = $now['mon'];
1297 $from['Y'] = $now['year'];
1298 $from = self::intervalAdd('day', -1 * ($now['wday']) - 14, $from);
1299 $to = self::intervalAdd('day', 13, $from);
1300 break;
1301
1302 case 'earlier':
1303 $to['d'] = $now['mday'];
1304 $to['M'] = $now['mon'];
1305 $to['Y'] = $now['year'];
1306 $to = self::intervalAdd('day', -1 * ($now['wday']) - 1, $to);
1307 unset($from);
1308 break;
1309
1310 case 'greater':
1311 $from['d'] = $now['mday'];
1312 $from['M'] = $now['mon'];
1313 $from['Y'] = $now['year'];
1314 $from = self::intervalAdd('day', -1 * ($now['wday']), $from);
1315 unset($to);
1316 break;
1317
1318 case 'ending':
1319 $to['d'] = $now['mday'];
1320 $to['M'] = $now['mon'];
1321 $to['Y'] = $now['year'];
1322 $to['H'] = 23;
1323 $to['i'] = $to['s'] = 59;
1324 $from = self::intervalAdd('day', -7, $to);
1325 $from = self::intervalAdd('second', 1, $from);
1326 break;
1327
1328 case 'current':
1329 $from['d'] = $now['mday'];
1330 $from['M'] = $now['mon'];
1331 $from['Y'] = $now['year'];
1332 $from = self::intervalAdd('day', -1 * ($now['wday']), $from);
1333 $to['d'] = $now['mday'];
1334 $to['M'] = $now['mon'];
1335 $to['Y'] = $now['year'];
1336 $to['H'] = 23;
1337 $to['i'] = $to['s'] = 59;
1338 break;
1339 }
1340 break;
1341
1342 case 'day':
1343 switch ($relativeTerm) {
1344 case 'this':
1345 $from['d'] = $to['d'] = $now['mday'];
1346 $from['M'] = $to['M'] = $now['mon'];
1347 $from['Y'] = $to['Y'] = $now['year'];
1348 break;
1349
1350 case 'previous':
1351 $from['d'] = $now['mday'];
1352 $from['M'] = $now['mon'];
1353 $from['Y'] = $now['year'];
1354 $from = self::intervalAdd('day', -1, $from);
1355 $to['d'] = $from['d'];
1356 $to['M'] = $from['M'];
1357 $to['Y'] = $from['Y'];
1358 break;
1359
1360 case 'previous_before':
1361 $from['d'] = $now['mday'];
1362 $from['M'] = $now['mon'];
1363 $from['Y'] = $now['year'];
1364 $from = self::intervalAdd('day', -2, $from);
1365 $to['d'] = $from['d'];
1366 $to['M'] = $from['M'];
1367 $to['Y'] = $from['Y'];
1368 break;
1369
1370 case 'previous_2':
1371 $from['d'] = $to['d'] = $now['mday'];
1372 $from['M'] = $to['M'] = $now['mon'];
1373 $from['Y'] = $to['Y'] = $now['year'];
1374 $from = self::intervalAdd('day', -2, $from);
1375 $to = self::intervalAdd('day', -1, $to);
1376 break;
1377
1378 case 'earlier':
1379 $to['d'] = $now['mday'];
1380 $to['M'] = $now['mon'];
1381 $to['Y'] = $now['year'];
1382 unset($from);
1383 break;
1384
1385 case 'greater':
1386 $from['d'] = $now['mday'];
1387 $from['M'] = $now['mon'];;
1388 $from['Y'] = $now['year'];
1389 unset($to);
1390 break;
1391 }
1392 break;
1393 }
1394
1395 foreach (array(
1396 'from', 'to') as $item) {
1397 if (!empty($$item)) {
1398 $dateRange[$item] = self::format($$item);
1399 }
1400 else {
1401 $dateRange[$item] = NULL;
1402 }
1403 }
1404 return $dateRange;
1405 }
1406
1407 /**
1408 * Function to calculate current fiscal year based on the fiscal month and day
1409 *
1410 * @param int $fyDate Fiscal start date
1411 *
1412 * @param int $fyMonth Fiscal Start Month
1413 *
1414 * @return int $fy Current Fiscl Year
1415 * @access public
1416 * @static
1417 */
1418 static function calculateFiscalYear($fyDate, $fyMonth) {
1419 $date = date("Y-m-d");
1420 $currentYear = date("Y");
1421
1422 //recalculate the date because month 4::04 make the difference
1423 $fiscalYear = explode('-', date("Y-m-d", mktime(0, 0, 0, $fyMonth, $fyDate, $currentYear)));
1424 $fyDate = $fiscalYear[2];
1425 $fyMonth = $fiscalYear[1];
1426 $fyStartDate = date("Y-m-d", mktime(0, 0, 0, $fyMonth, $fyDate, $currentYear));
1427
1428 if ($fyStartDate > $date) {
1429 $fy = intval(intval($currentYear) - 1);
1430 }
1431 else {
1432 $fy = intval($currentYear);
1433 }
1434 return $fy;
1435 }
1436
1437 /**
1438 * Function to process date, convert to mysql format
1439 *
1440 * @param string $date date string
1441 * @param string $time time string
1442 * @param string $returnNullString 'null' needs to be returned
1443 * so that db oject will set null in db
1444 * @param string $format expected return date format.( default is mysql )
1445 *
1446 * @return string $mysqlDate date format that is excepted by mysql
1447 */
1448 static function processDate($date, $time = NULL, $returnNullString = FALSE, $format = 'YmdHis') {
1449 $mysqlDate = NULL;
1450
1451 if ($returnNullString) {
1452 $mysqlDate = 'null';
1453 }
1454
1455 if (trim($date)) {
1456 $mysqlDate = date($format, strtotime($date . ' ' . $time));
1457 }
1458
1459 return $mysqlDate;
1460 }
1461
1462 /**
1463 * Function to convert mysql to date plugin format
1464 *
1465 * @param string $mysqlDate date string
1466 *
1467 * @return array $date and time
1468 */
1469 static function setDateDefaults($mysqlDate = NULL, $formatType = NULL, $format = NULL, $timeFormat = NULL) {
1470 // if date is not passed assume it as today
1471 if (!$mysqlDate) {
1472 $mysqlDate = date('Y-m-d G:i:s');
1473 }
1474
1475 $config = CRM_Core_Config::singleton();
1476 if ($formatType) {
1477 // get actual format
1478 $params = array('name' => $formatType);
1479 $values = array();
1480 CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_PreferencesDate', $params, $values);
1481
1482 if ($values['date_format']) {
1483 $format = $values['date_format'];
1484 }
1485
1486 if (isset($values['time_format'])) {
1487 $timeFormat = $values['time_format'];
1488 }
1489 }
1490
1491 // now we set display date using js, hence we should always setdefault
1492 // 'm/d/Y' format. So that submitted value is alwats mm/dd/YY format
1493 // note that for date display we dynamically create text field
1494 /*
1495 if ( !$format ) {
1496 $format = $config->dateInputFormat;
1497 }
1498
1499 // get actual format
1500 $actualPHPFormats = CRM_Core_SelectValues::datePluginToPHPFormats( );
1501 $dateFormat = CRM_Utils_Array::value( $format, $actualPHPFormats );
1502 */
1503
1504
1505 $dateFormat = 'm/d/Y';
1506 $date = date($dateFormat, strtotime($mysqlDate));
1507
1508 if (!$timeFormat) {
1509 $timeFormat = $config->timeInputFormat;
1510 }
1511
1512 $actualTimeFormat = "g:iA";
1513 $appendZeroLength = 7;
1514 if ($timeFormat > 1) {
1515 $actualTimeFormat = "G:i";
1516 $appendZeroLength = 5;
1517 }
1518
1519 $time = date($actualTimeFormat, strtotime($mysqlDate));
1520
1521 // need to append zero for hours < 10
1522 if (strlen($time) < $appendZeroLength) {
1523 $time = '0' . $time;
1524 }
1525
1526 return array($date, $time);
1527 }
1528
1529 /**
1530 * Function get date format
1531 *
1532 * @param string $formatType Date name e.g. birth
1533 *
1534 * @return string $format
1535 */
1536 static function getDateFormat($formatType = NULL) {
1537 $format = NULL;
1538 if ($formatType) {
1539 $format = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_PreferencesDate',
1540 $formatType, 'date_format', 'name'
1541 );
1542 }
1543
1544 if (!$format) {
1545 $config = CRM_Core_Config::singleton();
1546 $format = $config->dateInputFormat;
1547 }
1548 return $format;
1549 }
1550
1551 /**
1552 * Get the time in UTC for the current time. You can optionally send an offset from the current time if needed
1553 *
1554 * @param $offset int the offset from the current time in seconds
1555 *
1556 * @return the time in UTC
1557 * @static
1558 * @public
1559 */
1560 static function getUTCTime($offset = 0) {
1561 $originalTimezone = date_default_timezone_get();
1562 date_default_timezone_set('UTC');
1563 $time = time() + $offset;
1564 $now = date('YmdHis', $time);
1565 date_default_timezone_set($originalTimezone);
1566 return $now;
1567 }
1568
1569
1570 static function formatDate($date, $dateType) {
1571 $formattedDate = NULL;
1572 if (empty($date)) {
1573 return $formattedDate;
1574 }
1575
1576 //1. first convert date to default format.
1577 //2. append time to default formatted date (might be removed during format)
1578 //3. validate date / date time.
1579 //4. If date and time then convert to default date time format.
1580
1581 $dateKey = 'date';
1582 $dateParams = array($dateKey => $date);
1583
1584 if (CRM_Utils_Date::convertToDefaultDate($dateParams, $dateType, $dateKey)) {
1585 $dateVal = $dateParams[$dateKey];
1586 $ruleName = 'date';
1587 if ($dateType == 1) {
1588 $matches = array();
1589 if (preg_match("/(\s(([01]\d)|[2][0-3]):([0-5]\d))$/", $date, $matches)) {
1590 $ruleName = 'dateTime';
1591 if (strpos($date, '-') !== FALSE) {
1592 $dateVal .= array_shift($matches);
1593 }
1594 }
1595 }
1596
1597 // validate date.
1598 $valid = CRM_Utils_Rule::$ruleName($dateVal);
1599
1600 if ($valid) {
1601 //format date and time to default.
1602 if ($ruleName == 'dateTime') {
1603 $dateVal = CRM_Utils_Date::customFormat(preg_replace("/(:|\s)?/", "", $dateVal), '%Y%m%d%H%i');
1604 //hack to add seconds
1605 $dateVal .= '00';
1606 }
1607 $formattedDate = $dateVal;
1608 }
1609 }
1610
1611 return $formattedDate;
1612 }
1613
1614 }
1615