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