commiting uncommited changes on live site
[weblabels.fsf.org.git] / crm.fsf.org / 20131203 / files / sites / all / modules-new / civicrm / packages / Date / Calc.php
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
3
4 // {{{ Header
5
6 /**
7 * Calculates, manipulates and retrieves dates
8 *
9 * It does not rely on 32-bit system time stamps, so it works dates
10 * before 1970 and after 2038.
11 *
12 * PHP versions 4 and 5
13 *
14 * LICENSE:
15 *
16 * Copyright (c) 1999-2006 Monte Ohrt, Pierre-Alain Joye, Daniel Convissor
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted under the terms of the BSD License.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 *
35 * @category Date and Time
36 * @package Date
37 * @author Monte Ohrt <monte@ispi.net>
38 * @author Pierre-Alain Joye <pajoye@php.net>
39 * @author Daniel Convissor <danielc@php.net>
40 * @copyright 1999-2006 Monte Ohrt, Pierre-Alain Joye, Daniel Convissor
41 * @license http://www.opensource.org/licenses/bsd-license.php
42 * BSD License
43 * @version CVS: $Id: Calc.php,v 1.35 2006/11/21 23:01:13 firman Exp $
44 * @link http://pear.php.net/package/Date
45 * @since File available since Release 1.2
46 */
47
48 // }}}
49
50 if (!defined('DATE_CALC_BEGIN_WEEKDAY')) {
51 /**
52 * Defines what day starts the week
53 *
54 * Monday (1) is the international standard.
55 * Redefine this to 0 if you want weeks to begin on Sunday.
56 */
57 define('DATE_CALC_BEGIN_WEEKDAY', 1);
58 }
59
60 if (!defined('DATE_CALC_FORMAT')) {
61 /**
62 * The default value for each method's $format parameter
63 *
64 * The default is '%Y%m%d'. To override this default, define
65 * this constant before including Calc.php.
66 *
67 * @since Constant available since Release 1.4.4
68 */
69 define('DATE_CALC_FORMAT', '%Y%m%d');
70 }
71
72 // {{{ Class: Date_Calc
73
74 /**
75 * Calculates, manipulates and retrieves dates
76 *
77 * It does not rely on 32-bit system time stamps, so it works dates
78 * before 1970 and after 2038.
79 *
80 * @author Monte Ohrt <monte@ispi.net>
81 * @author Daniel Convissor <danielc@php.net>
82 * @copyright 1999-2006 Monte Ohrt, Pierre-Alain Joye, Daniel Convissor
83 * @license http://www.opensource.org/licenses/bsd-license.php
84 * BSD License
85 * @version Release: 1.4.7
86 * @link http://pear.php.net/package/Date
87 * @since Class available since Release 1.2
88 */
89 class Date_Calc
90 {
91 // {{{ dateFormat()
92
93 /**
94 * Formats the date in the given format, much like strfmt()
95 *
96 * This function is used to alleviate the problem with 32-bit numbers for
97 * dates pre 1970 or post 2038, as strfmt() has on most systems.
98 * Most of the formatting options are compatible.
99 *
100 * Formatting options:
101 * <pre>
102 * %a abbreviated weekday name (Sun, Mon, Tue)
103 * %A full weekday name (Sunday, Monday, Tuesday)
104 * %b abbreviated month name (Jan, Feb, Mar)
105 * %B full month name (January, February, March)
106 * %d day of month (range 00 to 31)
107 * %e day of month, single digit (range 0 to 31)
108 * %E number of days since unspecified epoch (integer)
109 * (%E is useful for passing a date in a URL as
110 * an integer value. Then simply use
111 * daysToDate() to convert back to a date.)
112 * %j day of year (range 001 to 366)
113 * %m month as decimal number (range 1 to 12)
114 * %n newline character (\n)
115 * %t tab character (\t)
116 * %w weekday as decimal (0 = Sunday)
117 * %U week number of current year, first sunday as first week
118 * %y year as decimal (range 00 to 99)
119 * %Y year as decimal including century (range 0000 to 9999)
120 * %% literal '%'
121 * </pre>
122 *
123 * @param int $day the day of the month
124 * @param int $month the month
125 * @param int $year the year. Use the complete year instead of the
126 * abbreviated version. E.g. use 2005, not 05.
127 * Do not add leading 0's for years prior to 1000.
128 * @param string $format the format string
129 *
130 * @return string the date in the desired format
131 *
132 * @access public
133 * @static
134 */
135 function dateFormat($day, $month, $year, $format)
136 {
137 if (!Date_Calc::isValidDate($day, $month, $year)) {
138 $year = Date_Calc::dateNow('%Y');
139 $month = Date_Calc::dateNow('%m');
140 $day = Date_Calc::dateNow('%d');
141 }
142
143 $output = '';
144
145 for ($strpos = 0; $strpos < strlen($format); $strpos++) {
146 $char = substr($format, $strpos, 1);
147 if ($char == '%') {
148 $nextchar = substr($format, $strpos + 1, 1);
149 switch($nextchar) {
150 case 'a':
151 $output .= Date_Calc::getWeekdayAbbrname($day, $month, $year);
152 break;
153 case 'A':
154 $output .= Date_Calc::getWeekdayFullname($day, $month, $year);
155 break;
156 case 'b':
157 $output .= Date_Calc::getMonthAbbrname($month);
158 break;
159 case 'B':
160 $output .= Date_Calc::getMonthFullname($month);
161 break;
162 case 'd':
163 $output .= sprintf('%02d', $day);
164 break;
165 case 'e':
166 $output .= $day;
167 break;
168 case 'E':
169 $output .= Date_Calc::dateToDays($day, $month, $year);
170 break;
171 case 'j':
172 $output .= Date_Calc::julianDate($day, $month, $year);
173 break;
174 case 'm':
175 $output .= sprintf('%02d', $month);
176 break;
177 case 'n':
178 $output .= "\n";
179 break;
180 case 't':
181 $output .= "\t";
182 break;
183 case 'w':
184 $output .= Date_Calc::dayOfWeek($day, $month, $year);
185 break;
186 case 'U':
187 $output .= Date_Calc::weekOfYear($day, $month, $year);
188 break;
189 case 'y':
190 $output .= substr($year, 2, 2);
191 break;
192 case 'Y':
193 $output .= $year;
194 break;
195 case '%':
196 $output .= '%';
197 break;
198 default:
199 $output .= $char.$nextchar;
200 }
201 $strpos++;
202 } else {
203 $output .= $char;
204 }
205 }
206 return $output;
207 }
208
209 // }}}
210 // {{{ defaultCentury()
211
212 /**
213 * Turns a two digit year into a four digit year
214 *
215 * From '51 to '99 is in the 1900's, otherwise it's in the 2000's.
216 *
217 * @param int $year the 2 digit year
218 *
219 * @return string the 4 digit year
220 *
221 * @access public
222 * @static
223 */
224 function defaultCentury($year)
225 {
226 if (strlen($year) == 1) {
227 $year = '0' . $year;
228 }
229 if ($year > 50) {
230 return '19' . $year;
231 } else {
232 return '20' . $year;
233 }
234 }
235
236 // }}}
237 // {{{ dateToDays()
238
239 /**
240 * Converts a date to number of days since a distant unspecified epoch
241 *
242 * @param int $day the day of the month
243 * @param int $month the month
244 * @param int $year the year. Use the complete year instead of the
245 * abbreviated version. E.g. use 2005, not 05.
246 * Do not add leading 0's for years prior to 1000.
247 *
248 * @return integer the number of days since the Date_Calc epoch
249 *
250 * @access public
251 * @static
252 */
253 function dateToDays($day, $month, $year)
254 {
255 $century = (int)substr($year, 0, 2);
256 $year = (int)substr($year, 2, 2);
257 if ($month > 2) {
258 $month -= 3;
259 } else {
260 $month += 9;
261 if ($year) {
262 $year--;
263 } else {
264 $year = 99;
265 $century --;
266 }
267 }
268
269 return (floor((146097 * $century) / 4 ) +
270 floor((1461 * $year) / 4 ) +
271 floor((153 * $month + 2) / 5 ) +
272 $day + 1721119);
273 }
274
275 // }}}
276 // {{{ daysToDate()
277
278 /**
279 * Converts number of days to a distant unspecified epoch
280 *
281 * @param int $days the number of days since the Date_Calc epoch
282 * @param string $format the string indicating how to format the output
283 *
284 * @return string the date in the desired format
285 *
286 * @access public
287 * @static
288 */
289 function daysToDate($days, $format = DATE_CALC_FORMAT)
290 {
291 $days -= 1721119;
292 $century = floor((4 * $days - 1) / 146097);
293 $days = floor(4 * $days - 1 - 146097 * $century);
294 $day = floor($days / 4);
295
296 $year = floor((4 * $day + 3) / 1461);
297 $day = floor(4 * $day + 3 - 1461 * $year);
298 $day = floor(($day + 4) / 4);
299
300 $month = floor((5 * $day - 3) / 153);
301 $day = floor(5 * $day - 3 - 153 * $month);
302 $day = floor(($day + 5) / 5);
303
304 if ($month < 10) {
305 $month +=3;
306 } else {
307 $month -=9;
308 if ($year++ == 99) {
309 $year = 0;
310 $century++;
311 }
312 }
313
314 $century = sprintf('%02d', $century);
315 $year = sprintf('%02d', $year);
316 return Date_Calc::dateFormat($day, $month, $century . $year, $format);
317 }
318
319 // }}}
320 // {{{ gregorianToISO()
321
322 /**
323 * Converts from Gregorian Year-Month-Day to ISO Year-WeekNumber-WeekDay
324 *
325 * Uses ISO 8601 definitions. Algorithm by Rick McCarty, 1999 at
326 * http://personal.ecu.edu/mccartyr/ISOwdALG.txt .
327 * Transcribed to PHP by Jesus M. Castagnetto.
328 *
329 * @param int $day the day of the month
330 * @param int $month the month
331 * @param int $year the year. Use the complete year instead of the
332 * abbreviated version. E.g. use 2005, not 05.
333 * Do not add leading 0's for years prior to 1000.
334 *
335 * @return string the date in ISO Year-WeekNumber-WeekDay format
336 *
337 * @access public
338 * @static
339 */
340 function gregorianToISO($day, $month, $year)
341 {
342 $mnth = array (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
343 $y_isleap = Date_Calc::isLeapYear($year);
344 $y_1_isleap = Date_Calc::isLeapYear($year - 1);
345 $day_of_year_number = $day + $mnth[$month - 1];
346 if ($y_isleap && $month > 2) {
347 $day_of_year_number++;
348 }
349 // find Jan 1 weekday (monday = 1, sunday = 7)
350 $yy = ($year - 1) % 100;
351 $c = ($year - 1) - $yy;
352 $g = $yy + intval($yy / 4);
353 $jan1_weekday = 1 + intval((((($c / 100) % 4) * 5) + $g) % 7);
354 // weekday for year-month-day
355 $h = $day_of_year_number + ($jan1_weekday - 1);
356 $weekday = 1 + intval(($h - 1) % 7);
357 // find if Y M D falls in YearNumber Y-1, WeekNumber 52 or
358 if ($day_of_year_number <= (8 - $jan1_weekday) && $jan1_weekday > 4){
359 $yearnumber = $year - 1;
360 if ($jan1_weekday == 5 || ($jan1_weekday == 6 && $y_1_isleap)) {
361 $weeknumber = 53;
362 } else {
363 $weeknumber = 52;
364 }
365 } else {
366 $yearnumber = $year;
367 }
368 // find if Y M D falls in YearNumber Y+1, WeekNumber 1
369 if ($yearnumber == $year) {
370 if ($y_isleap) {
371 $i = 366;
372 } else {
373 $i = 365;
374 }
375 if (($i - $day_of_year_number) < (4 - $weekday)) {
376 $yearnumber++;
377 $weeknumber = 1;
378 }
379 }
380 // find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
381 if ($yearnumber == $year) {
382 $j = $day_of_year_number + (7 - $weekday) + ($jan1_weekday - 1);
383 $weeknumber = intval($j / 7);
384 if ($jan1_weekday > 4) {
385 $weeknumber--;
386 }
387 }
388 // put it all together
389 if ($weeknumber < 10) {
390 $weeknumber = '0'.$weeknumber;
391 }
392 return $yearnumber . '-' . $weeknumber . '-' . $weekday;
393 }
394
395 // }}}
396 // {{{ dateSeason()
397
398 /**
399 * Determines julian date of the given season
400 *
401 * Adapted from previous work in Java by James Mark Hamilton.
402 *
403 * @param string $season the season to get the date for: VERNALEQUINOX,
404 * SUMMERSOLSTICE, AUTUMNALEQUINOX,
405 * or WINTERSOLSTICE
406 * @param string $year the year in four digit format. Must be between
407 * -1000BC and 3000AD.
408 *
409 * @return float the julian date the season starts on
410 *
411 * @author James Mark Hamilton <mhamilton@qwest.net>
412 * @author Robert Butler <rob@maxwellcreek.org>
413 * @access public
414 * @static
415 */
416 function dateSeason($season, $year = 0)
417 {
418 if ($year == '') {
419 $year = Date_Calc::dateNow('%Y');
420 }
421 if (($year >= -1000) && ($year <= 1000)) {
422 $y = $year / 1000.0;
423 switch ($season) {
424 case 'VERNALEQUINOX':
425 $juliandate = (((((((-0.00071 * $y) - 0.00111) * $y) + 0.06134) * $y) + 365242.1374) * $y) + 1721139.29189;
426 break;
427 case 'SUMMERSOLSTICE':
428 $juliandate = (((((((0.00025 * $y) + 0.00907) * $y) - 0.05323) * $y) + 365241.72562) * $y) + 1721233.25401;
429 break;
430 case 'AUTUMNALEQUINOX':
431 $juliandate = (((((((0.00074 * $y) - 0.00297) * $y) - 0.11677) * $y) + 365242.49558) * $y) + 1721325.70455;
432 break;
433 case 'WINTERSOLSTICE':
434 default:
435 $juliandate = (((((((-0.00006 * $y) - 0.00933) * $y) - 0.00769) * $y) + 365242.88257) * $y) + 1721414.39987;
436 }
437 } elseif (($year > 1000) && ($year <= 3000)) {
438 $y = ($year - 2000) / 1000;
439 switch ($season) {
440 case 'VERNALEQUINOX':
441 $juliandate = (((((((-0.00057 * $y) - 0.00411) * $y) + 0.05169) * $y) + 365242.37404) * $y) + 2451623.80984;
442 break;
443 case 'SUMMERSOLSTICE':
444 $juliandate = (((((((-0.0003 * $y) + 0.00888) * $y) + 0.00325) * $y) + 365241.62603) * $y) + 2451716.56767;
445 break;
446 case 'AUTUMNALEQUINOX':
447 $juliandate = (((((((0.00078 * $y) + 0.00337) * $y) - 0.11575) * $y) + 365242.01767) * $y) + 2451810.21715;
448 break;
449 case 'WINTERSOLSTICE':
450 default:
451 $juliandate = (((((((0.00032 * $y) - 0.00823) * $y) - 0.06223) * $y) + 365242.74049) * $y) + 2451900.05952;
452 }
453 }
454 return $juliandate;
455 }
456
457 // }}}
458 // {{{ dateNow()
459
460 /**
461 * Returns the current local date
462 *
463 * NOTE: This function retrieves the local date using strftime(),
464 * which may or may not be 32-bit safe on your system.
465 *
466 * @param string $format the string indicating how to format the output
467 *
468 * @return string the current date in the specified format
469 *
470 * @access public
471 * @static
472 */
473 function dateNow($format = DATE_CALC_FORMAT)
474 {
475 return strftime($format, time());
476 }
477
478 // }}}
479 // {{{ getYear()
480
481 /**
482 * Returns the current local year in format CCYY
483 *
484 * @return string the current year in four digit format
485 *
486 * @access public
487 * @static
488 */
489 function getYear()
490 {
491 return Date_Calc::dateNow('%Y');
492 }
493
494 // }}}
495 // {{{ getMonth()
496
497 /**
498 * Returns the current local month in format MM
499 *
500 * @return string the current month in two digit format
501 *
502 * @access public
503 * @static
504 */
505 function getMonth()
506 {
507 return Date_Calc::dateNow('%m');
508 }
509
510 // }}}
511 // {{{ getDay()
512
513 /**
514 * Returns the current local day in format DD
515 *
516 * @return string the current day of the month in two digit format
517 *
518 * @access public
519 * @static
520 */
521 function getDay()
522 {
523 return Date_Calc::dateNow('%d');
524 }
525
526 // }}}
527 // {{{ julianDate()
528
529 /**
530 * Returns number of days since 31 December of year before given date
531 *
532 * @param int $day the day of the month, default is current local day
533 * @param int $month the month, default is current local month
534 * @param int $year the year in four digit format, default is current local year
535 *
536 * @return int the julian date for the date
537 *
538 * @access public
539 * @static
540 */
541 function julianDate($day = 0, $month = 0, $year = 0)
542 {
543 if (empty($year)) {
544 $year = Date_Calc::dateNow('%Y');
545 }
546 if (empty($month)) {
547 $month = Date_Calc::dateNow('%m');
548 }
549 if (empty($day)) {
550 $day = Date_Calc::dateNow('%d');
551 }
552 $days = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
553 $julian = ($days[$month - 1] + $day);
554 if ($month > 2 && Date_Calc::isLeapYear($year)) {
555 $julian++;
556 }
557 return $julian;
558 }
559
560 // }}}
561 // {{{ getWeekdayFullname()
562
563 /**
564 * Returns the full weekday name for the given date
565 *
566 * @param int $day the day of the month, default is current local day
567 * @param int $month the month, default is current local month
568 * @param int $year the year in four digit format, default is current local year
569 *
570 * @return string the full name of the day of the week
571 *
572 * @access public
573 * @static
574 */
575 function getWeekdayFullname($day = 0, $month = 0, $year = 0)
576 {
577 if (empty($year)) {
578 $year = Date_Calc::dateNow('%Y');
579 }
580 if (empty($month)) {
581 $month = Date_Calc::dateNow('%m');
582 }
583 if (empty($day)) {
584 $day = Date_Calc::dateNow('%d');
585 }
586 $weekday_names = Date_Calc::getWeekDays();
587 $weekday = Date_Calc::dayOfWeek($day, $month, $year);
588 return $weekday_names[$weekday];
589 }
590
591 // }}}
592 // {{{ getWeekdayAbbrname()
593
594 /**
595 * Returns the abbreviated weekday name for the given date
596 *
597 * @param int $day the day of the month, default is current local day
598 * @param int $month the month, default is current local month
599 * @param int $year the year in four digit format, default is current local year
600 * @param int $length the length of abbreviation
601 *
602 * @return string the abbreviated name of the day of the week
603 *
604 * @access public
605 * @static
606 * @see Date_Calc::getWeekdayFullname()
607 */
608 function getWeekdayAbbrname($day = 0, $month = 0, $year = 0, $length = 3)
609 {
610 if (empty($year)) {
611 $year = Date_Calc::dateNow('%Y');
612 }
613 if (empty($month)) {
614 $month = Date_Calc::dateNow('%m');
615 }
616 if (empty($day)) {
617 $day = Date_Calc::dateNow('%d');
618 }
619 return substr(Date_Calc::getWeekdayFullname($day, $month, $year),
620 0, $length);
621 }
622
623 // }}}
624 // {{{ getMonthFullname()
625
626 /**
627 * Returns the full month name for the given month
628 *
629 * @param int $month the month
630 *
631 * @return string the full name of the month
632 *
633 * @access public
634 * @static
635 */
636 function getMonthFullname($month)
637 {
638 $month = (int)$month;
639 if (empty($month)) {
640 $month = (int)Date_Calc::dateNow('%m');
641 }
642 $month_names = Date_Calc::getMonthNames();
643 return $month_names[$month];
644 }
645
646 // }}}
647 // {{{ getMonthAbbrname()
648
649 /**
650 * Returns the abbreviated month name for the given month
651 *
652 * @param int $month the month
653 * @param int $length the length of abbreviation
654 *
655 * @return string the abbreviated name of the month
656 *
657 * @access public
658 * @static
659 * @see Date_Calc::getMonthFullname
660 */
661 function getMonthAbbrname($month, $length = 3)
662 {
663 $month = (int)$month;
664 if (empty($month)) {
665 $month = Date_Calc::dateNow('%m');
666 }
667 return substr(Date_Calc::getMonthFullname($month), 0, $length);
668 }
669
670 // }}}
671 // {{{ getMonthNames()
672
673 /**
674 * Returns an array of month names
675 *
676 * Used to take advantage of the setlocale function to return
677 * language specific month names.
678 *
679 * TODO: cache values to some global array to avoid preformace
680 * hits when called more than once.
681 *
682 * @returns array an array of month names
683 *
684 * @access public
685 * @static
686 */
687 function getMonthNames()
688 {
689 $months = array();
690 for ($i = 1; $i < 13; $i++) {
691 $months[$i] = strftime('%B', mktime(0, 0, 0, $i, 1, 2001));
692 }
693 return $months;
694 }
695
696 // }}}
697 // {{{ getWeekDays()
698
699 /**
700 * Returns an array of week days
701 *
702 * Used to take advantage of the setlocale function to
703 * return language specific week days.
704 *
705 * TODO: cache values to some global array to avoid preformace
706 * hits when called more than once.
707 *
708 * @returns array an array of week day names
709 *
710 * @access public
711 * @static
712 */
713 function getWeekDays()
714 {
715 $weekdays = array();
716 for ($i = 0; $i < 7; $i++) {
717 $weekdays[$i] = strftime('%A', mktime(0, 0, 0, 1, $i, 2001));
718 }
719 return $weekdays;
720 }
721
722 // }}}
723 // {{{ dayOfWeek()
724
725 /**
726 * Returns day of week for given date (0 = Sunday)
727 *
728 * @param int $day the day of the month, default is current local day
729 * @param int $month the month, default is current local month
730 * @param int $year the year in four digit format, default is current local year
731 *
732 * @return int the number of the day in the week
733 *
734 * @access public
735 * @static
736 */
737 function dayOfWeek($day = 0, $month = 0, $year = 0)
738 {
739 if (empty($year)) {
740 $year = Date_Calc::dateNow('%Y');
741 }
742 if (empty($month)) {
743 $month = Date_Calc::dateNow('%m');
744 }
745 if (empty($day)) {
746 $day = Date_Calc::dateNow('%d');
747 }
748 if ($month > 2) {
749 $month -= 2;
750 } else {
751 $month += 10;
752 $year--;
753 }
754
755 $day = (floor((13 * $month - 1) / 5) +
756 $day + ($year % 100) +
757 floor(($year % 100) / 4) +
758 floor(($year / 100) / 4) - 2 *
759 floor($year / 100) + 77);
760
761 $weekday_number = $day - 7 * floor($day / 7);
762 return $weekday_number;
763 }
764
765 // }}}
766 // {{{ weekOfYear()
767
768 /**
769 * Returns week of the year, first Sunday is first day of first week
770 *
771 * @param int $day the day of the month, default is current local day
772 * @param int $month the month, default is current local month
773 * @param int $year the year in four digit format, default is current local year
774 *
775 * @return int the number of the week in the year
776 *
777 * @access public
778 * @static
779 */
780 function weekOfYear($day = 0, $month = 0, $year = 0)
781 {
782 if (empty($year)) {
783 $year = Date_Calc::dateNow('%Y');
784 }
785 if (empty($month)) {
786 $month = Date_Calc::dateNow('%m');
787 }
788 if (empty($day)) {
789 $day = Date_Calc::dateNow('%d');
790 }
791 $iso = Date_Calc::gregorianToISO($day, $month, $year);
792 $parts = explode('-', $iso);
793 $week_number = intval($parts[1]);
794 return $week_number;
795 }
796
797 // }}}
798 // {{{ quarterOfYear()
799
800 /**
801 * Returns quarter of the year for given date
802 *
803 * @param int $day the day of the month, default is current local day
804 * @param int $month the month, default is current local month
805 * @param int $year the year in four digit format, default is current local year
806 *
807 * @return int the number of the quarter in the year
808 *
809 * @access public
810 * @static
811 */
812 function quarterOfYear($day = 0, $month = 0, $year = 0)
813 {
814 if (empty($year)) {
815 $year = Date_Calc::dateNow('%Y');
816 }
817 if (empty($month)) {
818 $month = Date_Calc::dateNow('%m');
819 }
820 if (empty($day)) {
821 $day = Date_Calc::dateNow('%d');
822 }
823 $year_quarter = intval(($month - 1) / 3 + 1);
824 return $year_quarter;
825 }
826
827 // }}}
828 // {{{ daysInMonth()
829
830 /**
831 * Find the number of days in the given month
832 *
833 * @param int $month the month, default is current local month
834 * @param int $year the year in four digit format, default is current local year
835 *
836 * @return int the number of days the month has
837 *
838 * @access public
839 * @static
840 */
841 function daysInMonth($month = 0, $year = 0)
842 {
843 if (empty($year)) {
844 $year = Date_Calc::dateNow('%Y');
845 }
846 if (empty($month)) {
847 $month = Date_Calc::dateNow('%m');
848 }
849
850 if ($year == 1582 && $month == 10) {
851 return 21; // October 1582 only had 1st-4th and 15th-31st
852 }
853
854 if ($month == 2) {
855 if (Date_Calc::isLeapYear($year)) {
856 return 29;
857 } else {
858 return 28;
859 }
860 } elseif ($month == 4 or $month == 6 or $month == 9 or $month == 11) {
861 return 30;
862 } else {
863 return 31;
864 }
865 }
866
867 // }}}
868 // {{{ weeksInMonth()
869
870 /**
871 * Returns the number of rows on a calendar month
872 *
873 * Useful for determining the number of rows when displaying a typical
874 * month calendar.
875 *
876 * @param int $month the month, default is current local month
877 * @param int $year the year in four digit format, default is current local year
878 *
879 * @return int the number of weeks the month has
880 *
881 * @access public
882 * @static
883 */
884 function weeksInMonth($month = 0, $year = 0)
885 {
886 if (empty($year)) {
887 $year = Date_Calc::dateNow('%Y');
888 }
889 if (empty($month)) {
890 $month = Date_Calc::dateNow('%m');
891 }
892 $FDOM = Date_Calc::firstOfMonthWeekday($month, $year);
893 if (DATE_CALC_BEGIN_WEEKDAY==1 && $FDOM==0) {
894 $first_week_days = 7 - $FDOM + DATE_CALC_BEGIN_WEEKDAY;
895 $weeks = 1;
896 } elseif (DATE_CALC_BEGIN_WEEKDAY==0 && $FDOM == 6) {
897 $first_week_days = 7 - $FDOM + DATE_CALC_BEGIN_WEEKDAY;
898 $weeks = 1;
899 } else {
900 $first_week_days = DATE_CALC_BEGIN_WEEKDAY - $FDOM;
901 $weeks = 0;
902 }
903 $first_week_days %= 7;
904 return ceil((Date_Calc::daysInMonth($month, $year)
905 - $first_week_days) / 7) + $weeks;
906 }
907
908 // }}}
909 // {{{ getCalendarWeek()
910
911 /**
912 * Return an array with days in week
913 *
914 * @param int $day the day of the month, default is current local day
915 * @param int $month the month, default is current local month
916 * @param int $year the year in four digit format, default is current local year
917 * @param string $format the string indicating how to format the output
918 *
919 * @return array $week[$weekday]
920 *
921 * @access public
922 * @static
923 */
924 function getCalendarWeek($day = 0, $month = 0, $year = 0,
925 $format = DATE_CALC_FORMAT)
926 {
927 if (empty($year)) {
928 $year = Date_Calc::dateNow('%Y');
929 }
930 if (empty($month)) {
931 $month = Date_Calc::dateNow('%m');
932 }
933 if (empty($day)) {
934 $day = Date_Calc::dateNow('%d');
935 }
936
937 $week_array = array();
938
939 // date for the column of week
940
941 $curr_day = Date_Calc::beginOfWeek($day, $month, $year,'%E');
942
943 for ($counter = 0; $counter <= 6; $counter++) {
944 $week_array[$counter] = Date_Calc::daysToDate($curr_day, $format);
945 $curr_day++;
946 }
947 return $week_array;
948 }
949
950 // }}}
951 // {{{ getCalendarMonth()
952
953 /**
954 * Return a set of arrays to construct a calendar month for the given date
955 *
956 * @param int $month the month, default is current local month
957 * @param int $year the year in four digit format, default is current local year
958 * @param string $format the string indicating how to format the output
959 *
960 * @return array $month[$row][$col]
961 *
962 * @access public
963 * @static
964 */
965 function getCalendarMonth($month = 0, $year = 0,
966 $format = DATE_CALC_FORMAT)
967 {
968 if (empty($year)) {
969 $year = Date_Calc::dateNow('%Y');
970 }
971 if (empty($month)) {
972 $month = Date_Calc::dateNow('%m');
973 }
974
975 $month_array = array();
976
977 // date for the first row, first column of calendar month
978 if (DATE_CALC_BEGIN_WEEKDAY == 1) {
979 if (Date_Calc::firstOfMonthWeekday($month, $year) == 0) {
980 $curr_day = Date_Calc::dateToDays('01', $month, $year) - 6;
981 } else {
982 $curr_day = Date_Calc::dateToDays('01', $month, $year)
983 - Date_Calc::firstOfMonthWeekday($month, $year) + 1;
984 }
985 } else {
986 $curr_day = (Date_Calc::dateToDays('01', $month, $year)
987 - Date_Calc::firstOfMonthWeekday($month, $year));
988 }
989
990 // number of days in this month
991 $daysInMonth = Date_Calc::daysInMonth($month, $year);
992
993 $weeksInMonth = Date_Calc::weeksInMonth($month, $year);
994 for ($row_counter = 0; $row_counter < $weeksInMonth; $row_counter++) {
995 for ($column_counter = 0; $column_counter <= 6; $column_counter++) {
996 $month_array[$row_counter][$column_counter] =
997 Date_Calc::daysToDate($curr_day , $format);
998 $curr_day++;
999 }
1000 }
1001
1002 return $month_array;
1003 }
1004
1005 // }}}
1006 // {{{ getCalendarYear()
1007
1008 /**
1009 * Return a set of arrays to construct a calendar year for the given date
1010 *
1011 * @param int $year the year in four digit format, default current local year
1012 * @param string $format the string indicating how to format the output
1013 *
1014 * @return array $year[$month][$row][$col]
1015 *
1016 * @access public
1017 * @static
1018 */
1019 function getCalendarYear($year = 0, $format = DATE_CALC_FORMAT)
1020 {
1021 if (empty($year)) {
1022 $year = Date_Calc::dateNow('%Y');
1023 }
1024
1025 $year_array = array();
1026
1027 for ($curr_month = 0; $curr_month <= 11; $curr_month++) {
1028 $year_array[$curr_month] =
1029 Date_Calc::getCalendarMonth($curr_month + 1,
1030 $year, $format);
1031 }
1032
1033 return $year_array;
1034 }
1035
1036 // }}}
1037 // {{{ prevDay()
1038
1039 /**
1040 * Returns date of day before given date
1041 *
1042 * @param int $day the day of the month, default is current local day
1043 * @param int $month the month, default is current local month
1044 * @param int $year the year in four digit format, default is current local year
1045 * @param string $format the string indicating how to format the output
1046 *
1047 * @return string the date in the desired format
1048 *
1049 * @access public
1050 * @static
1051 */
1052 function prevDay($day = 0, $month = 0, $year = 0,
1053 $format = DATE_CALC_FORMAT)
1054 {
1055 if (empty($year)) {
1056 $year = Date_Calc::dateNow('%Y');
1057 }
1058 if (empty($month)) {
1059 $month = Date_Calc::dateNow('%m');
1060 }
1061 if (empty($day)) {
1062 $day = Date_Calc::dateNow('%d');
1063 }
1064 $days = Date_Calc::dateToDays($day, $month, $year);
1065 return Date_Calc::daysToDate($days - 1, $format);
1066 }
1067
1068 // }}}
1069 // {{{ nextDay()
1070
1071 /**
1072 * Returns date of day after given date
1073 *
1074 * @param int $day the day of the month, default is current local day
1075 * @param int $month the month, default is current local month
1076 * @param int $year the year in four digit format, default is current local year
1077 * @param string $format the string indicating how to format the output
1078 *
1079 * @return string the date in the desired format
1080 *
1081 * @access public
1082 * @static
1083 */
1084 function nextDay($day = 0, $month = 0, $year = 0,
1085 $format = DATE_CALC_FORMAT)
1086 {
1087 if (empty($year)) {
1088 $year = Date_Calc::dateNow('%Y');
1089 }
1090 if (empty($month)) {
1091 $month = Date_Calc::dateNow('%m');
1092 }
1093 if (empty($day)) {
1094 $day = Date_Calc::dateNow('%d');
1095 }
1096 $days = Date_Calc::dateToDays($day, $month, $year);
1097 return Date_Calc::daysToDate($days + 1, $format);
1098 }
1099
1100 // }}}
1101 // {{{ prevWeekday()
1102
1103 /**
1104 * Returns date of the previous weekday, skipping from Monday to Friday
1105 *
1106 * @param int $day the day of the month, default is current local day
1107 * @param int $month the month, default is current local month
1108 * @param int $year the year in four digit format, default is current local year
1109 * @param string $format the string indicating how to format the output
1110 *
1111 * @return string the date in the desired format
1112 *
1113 * @access public
1114 * @static
1115 */
1116 function prevWeekday($day = 0, $month = 0, $year = 0,
1117 $format = DATE_CALC_FORMAT)
1118 {
1119 if (empty($year)) {
1120 $year = Date_Calc::dateNow('%Y');
1121 }
1122 if (empty($month)) {
1123 $month = Date_Calc::dateNow('%m');
1124 }
1125 if (empty($day)) {
1126 $day = Date_Calc::dateNow('%d');
1127 }
1128 $days = Date_Calc::dateToDays($day, $month, $year);
1129 if (Date_Calc::dayOfWeek($day, $month, $year) == 1) {
1130 $days -= 3;
1131 } elseif (Date_Calc::dayOfWeek($day, $month, $year) == 0) {
1132 $days -= 2;
1133 } else {
1134 $days -= 1;
1135 }
1136 return Date_Calc::daysToDate($days, $format);
1137 }
1138
1139 // }}}
1140 // {{{ nextWeekday()
1141
1142 /**
1143 * Returns date of the next weekday of given date, skipping from
1144 * Friday to Monday
1145 *
1146 * @param int $day the day of the month, default is current local day
1147 * @param int $month the month, default is current local month
1148 * @param int $year the year in four digit format, default is current local year
1149 * @param string $format the string indicating how to format the output
1150 *
1151 * @return string the date in the desired format
1152 *
1153 * @access public
1154 * @static
1155 */
1156 function nextWeekday($day = 0, $month = 0, $year = 0,
1157 $format = DATE_CALC_FORMAT)
1158 {
1159 if (empty($year)) {
1160 $year = Date_Calc::dateNow('%Y');
1161 }
1162 if (empty($month)) {
1163 $month = Date_Calc::dateNow('%m');
1164 }
1165 if (empty($day)) {
1166 $day = Date_Calc::dateNow('%d');
1167 }
1168 $days = Date_Calc::dateToDays($day, $month, $year);
1169 if (Date_Calc::dayOfWeek($day, $month, $year) == 5) {
1170 $days += 3;
1171 } elseif (Date_Calc::dayOfWeek($day, $month, $year) == 6) {
1172 $days += 2;
1173 } else {
1174 $days += 1;
1175 }
1176 return Date_Calc::daysToDate($days, $format);
1177 }
1178
1179 // }}}
1180 // {{{ prevDayOfWeek()
1181
1182 /**
1183 * Returns date of the previous specific day of the week
1184 * from the given date
1185 *
1186 * @param int day of week, 0=Sunday
1187 * @param int $day the day of the month, default is current local day
1188 * @param int $month the month, default is current local month
1189 * @param int $year the year in four digit format, default is current local year
1190 * @param bool $onOrBefore if true and days are same, returns current day
1191 * @param string $format the string indicating how to format the output
1192 *
1193 * @return string the date in the desired format
1194 *
1195 * @access public
1196 * @static
1197 */
1198 function prevDayOfWeek($dow, $day = 0, $month = 0, $year = 0,
1199 $format = DATE_CALC_FORMAT, $onOrBefore = false)
1200 {
1201 if (empty($year)) {
1202 $year = Date_Calc::dateNow('%Y');
1203 }
1204 if (empty($month)) {
1205 $month = Date_Calc::dateNow('%m');
1206 }
1207 if (empty($day)) {
1208 $day = Date_Calc::dateNow('%d');
1209 }
1210 $days = Date_Calc::dateToDays($day, $month, $year);
1211 $curr_weekday = Date_Calc::dayOfWeek($day, $month, $year);
1212 if ($curr_weekday == $dow) {
1213 if (!$onOrBefore) {
1214 $days -= 7;
1215 }
1216 } elseif ($curr_weekday < $dow) {
1217 $days -= 7 - ($dow - $curr_weekday);
1218 } else {
1219 $days -= $curr_weekday - $dow;
1220 }
1221 return Date_Calc::daysToDate($days, $format);
1222 }
1223
1224 // }}}
1225 // {{{ nextDayOfWeek()
1226
1227 /**
1228 * Returns date of the next specific day of the week
1229 * from the given date
1230 *
1231 * @param int $dow the day of the week (0 = Sunday)
1232 * @param int $day the day of the month, default is current local day
1233 * @param int $month the month, default is current local month
1234 * @param int $year the year in four digit format, default is current local year
1235 * @param bool $onOrAfter if true and days are same, returns current day
1236 * @param string $format the string indicating how to format the output
1237 *
1238 * @return string the date in the desired format
1239 *
1240 * @access public
1241 * @static
1242 */
1243 function nextDayOfWeek($dow, $day = 0, $month = 0, $year = 0,
1244 $format = DATE_CALC_FORMAT, $onOrAfter = false)
1245 {
1246 if (empty($year)) {
1247 $year = Date_Calc::dateNow('%Y');
1248 }
1249 if (empty($month)) {
1250 $month = Date_Calc::dateNow('%m');
1251 }
1252 if (empty($day)) {
1253 $day = Date_Calc::dateNow('%d');
1254 }
1255
1256 $days = Date_Calc::dateToDays($day, $month, $year);
1257 $curr_weekday = Date_Calc::dayOfWeek($day, $month, $year);
1258
1259 if ($curr_weekday == $dow) {
1260 if (!$onOrAfter) {
1261 $days += 7;
1262 }
1263 } elseif ($curr_weekday > $dow) {
1264 $days += 7 - ($curr_weekday - $dow);
1265 } else {
1266 $days += $dow - $curr_weekday;
1267 }
1268
1269 return Date_Calc::daysToDate($days, $format);
1270 }
1271
1272 // }}}
1273 // {{{ prevDayOfWeekOnOrBefore()
1274
1275 /**
1276 * Returns date of the previous specific day of the week
1277 * on or before the given date
1278 *
1279 * @param int $dow the day of the week (0 = Sunday)
1280 * @param int $day the day of the month, default is current local day
1281 * @param int $month the month, default is current local month
1282 * @param int $year the year in four digit format, default is current local year
1283 * @param string $format the string indicating how to format the output
1284 *
1285 * @return string the date in the desired format
1286 *
1287 * @access public
1288 * @static
1289 */
1290 function prevDayOfWeekOnOrBefore($dow, $day = 0, $month = 0, $year = 0,
1291 $format = DATE_CALC_FORMAT)
1292 {
1293 return Date_Calc::prevDayOfWeek($dow, $day, $month, $year, $format,
1294 true);
1295 }
1296
1297 // }}}
1298 // {{{ nextDayOfWeekOnOrAfter()
1299
1300 /**
1301 * Returns date of the next specific day of the week
1302 * on or after the given date
1303 *
1304 * @param int $dow the day of the week (0 = Sunday)
1305 * @param int $day the day of the month, default is current local day
1306 * @param int $month the month, default is current local month
1307 * @param int $year the year in four digit format, default is current local year
1308 * @param string $format the string indicating how to format the output
1309 *
1310 * @return string the date in the desired format
1311 *
1312 * @access public
1313 * @static
1314 */
1315 function nextDayOfWeekOnOrAfter($dow, $day = 0, $month = 0, $year = 0,
1316 $format = DATE_CALC_FORMAT)
1317 {
1318 return Date_Calc::nextDayOfWeek($dow, $day, $month, $year, $format,
1319 true);
1320 }
1321
1322 // }}}
1323 // {{{ beginOfWeek()
1324
1325 /**
1326 * Find the month day of the beginning of week for given date,
1327 * using DATE_CALC_BEGIN_WEEKDAY
1328 *
1329 * Can return weekday of prev month.
1330 *
1331 * @param int $day the day of the month, default is current local day
1332 * @param int $month the month, default is current local month
1333 * @param int $year the year in four digit format, default is current local year
1334 * @param string $format the string indicating how to format the output
1335 *
1336 * @return string the date in the desired format
1337 *
1338 * @access public
1339 * @static
1340 */
1341 function beginOfWeek($day = 0, $month = 0, $year = 0,
1342 $format = DATE_CALC_FORMAT)
1343 {
1344 if (empty($year)) {
1345 $year = Date_Calc::dateNow('%Y');
1346 }
1347 if (empty($month)) {
1348 $month = Date_Calc::dateNow('%m');
1349 }
1350 if (empty($day)) {
1351 $day = Date_Calc::dateNow('%d');
1352 }
1353 $this_weekday = Date_Calc::dayOfWeek($day, $month, $year);
1354 $interval = (7 - DATE_CALC_BEGIN_WEEKDAY + $this_weekday) % 7;
1355 return Date_Calc::daysToDate(Date_Calc::dateToDays($day, $month, $year)
1356 - $interval, $format);
1357 }
1358
1359 // }}}
1360 // {{{ endOfWeek()
1361
1362 /**
1363 * Find the month day of the end of week for given date,
1364 * using DATE_CALC_BEGIN_WEEKDAY
1365 *
1366 * Can return weekday of following month.
1367 *
1368 * @param int $day the day of the month, default is current local day
1369 * @param int $month the month, default is current local month
1370 * @param int $year the year in four digit format, default is current local year
1371 * @param string $format the string indicating how to format the output
1372 *
1373 * @return string the date in the desired format
1374 *
1375 * @access public
1376 * @static
1377 */
1378 function endOfWeek($day = 0, $month = 0, $year = 0,
1379 $format = DATE_CALC_FORMAT)
1380 {
1381 if (empty($year)) {
1382 $year = Date_Calc::dateNow('%Y');
1383 }
1384 if (empty($month)) {
1385 $month = Date_Calc::dateNow('%m');
1386 }
1387 if (empty($day)) {
1388 $day = Date_Calc::dateNow('%d');
1389 }
1390 $this_weekday = Date_Calc::dayOfWeek($day, $month, $year);
1391 $interval = (6 + DATE_CALC_BEGIN_WEEKDAY - $this_weekday) % 7;
1392 return Date_Calc::daysToDate(Date_Calc::dateToDays($day, $month, $year)
1393 + $interval, $format);
1394 }
1395
1396 // }}}
1397 // {{{ beginOfPrevWeek()
1398
1399 /**
1400 * Find the month day of the beginning of week before given date,
1401 * using DATE_CALC_BEGIN_WEEKDAY
1402 *
1403 * Can return weekday of prev month.
1404 *
1405 * @param int $day the day of the month, default is current local day
1406 * @param int $month the month, default is current local month
1407 * @param int $year the year in four digit format, default is current local year
1408 * @param string $format the string indicating how to format the output
1409 *
1410 * @return string the date in the desired format
1411 *
1412 * @access public
1413 * @static
1414 */
1415 function beginOfPrevWeek($day = 0, $month = 0, $year = 0,
1416 $format = DATE_CALC_FORMAT)
1417 {
1418 if (empty($year)) {
1419 $year = Date_Calc::dateNow('%Y');
1420 }
1421 if (empty($month)) {
1422 $month = Date_Calc::dateNow('%m');
1423 }
1424 if (empty($day)) {
1425 $day = Date_Calc::dateNow('%d');
1426 }
1427
1428 $date = Date_Calc::daysToDate(Date_Calc::dateToDays($day-7,
1429 $month,
1430 $year),
1431 '%Y%m%d');
1432
1433 $prev_week_year = substr($date, 0, 4);
1434 $prev_week_month = substr($date, 4, 2);
1435 $prev_week_day = substr($date, 6, 2);
1436
1437 return Date_Calc::beginOfWeek($prev_week_day, $prev_week_month,
1438 $prev_week_year, $format);
1439 }
1440
1441 // }}}
1442 // {{{ beginOfNextWeek()
1443
1444 /**
1445 * Find the month day of the beginning of week after given date,
1446 * using DATE_CALC_BEGIN_WEEKDAY
1447 *
1448 * Can return weekday of prev month.
1449 *
1450 * @param int $day the day of the month, default is current local day
1451 * @param int $month the month, default is current local month
1452 * @param int $year the year in four digit format, default is current local year
1453 * @param string $format the string indicating how to format the output
1454 *
1455 * @return string the date in the desired format
1456 *
1457 * @access public
1458 * @static
1459 */
1460 function beginOfNextWeek($day = 0, $month = 0, $year = 0,
1461 $format = DATE_CALC_FORMAT)
1462 {
1463 if (empty($year)) {
1464 $year = Date_Calc::dateNow('%Y');
1465 }
1466 if (empty($month)) {
1467 $month = Date_Calc::dateNow('%m');
1468 }
1469 if (empty($day)) {
1470 $day = Date_Calc::dateNow('%d');
1471 }
1472
1473 $date = Date_Calc::daysToDate(Date_Calc::dateToDays($day + 7,
1474 $month,
1475 $year),
1476 '%Y%m%d');
1477
1478 $next_week_year = substr($date, 0, 4);
1479 $next_week_month = substr($date, 4, 2);
1480 $next_week_day = substr($date, 6, 2);
1481
1482 return Date_Calc::beginOfWeek($next_week_day, $next_week_month,
1483 $next_week_year, $format);
1484 }
1485
1486 // }}}
1487 // {{{ beginOfMonth()
1488
1489 /**
1490 * Return date of first day of month of given date
1491 *
1492 * @param int $month the month, default is current local month
1493 * @param int $year the year in four digit format, default is current local year
1494 * @param string $format the string indicating how to format the output
1495 *
1496 * @return string the date in the desired format
1497 *
1498 * @access public
1499 * @static
1500 * @see Date_Calc::beginOfMonthBySpan()
1501 * @deprecated Method deprecated in Release 1.4.4
1502 */
1503 function beginOfMonth($month = 0, $year = 0, $format = DATE_CALC_FORMAT)
1504 {
1505 if (empty($year)) {
1506 $year = Date_Calc::dateNow('%Y');
1507 }
1508 if (empty($month)) {
1509 $month = Date_Calc::dateNow('%m');
1510 }
1511 return Date_Calc::dateFormat('01', $month, $year, $format);
1512 }
1513
1514 // }}}
1515 // {{{ beginOfPrevMonth()
1516
1517 /**
1518 * Returns date of the first day of previous month of given date
1519 *
1520 * @param int $day the day of the month, default is current local day
1521 * @param int $month the month, default is current local month
1522 * @param int $year the year in four digit format, default is current local year
1523 * @param string $format the string indicating how to format the output
1524 *
1525 * @return string the date in the desired format
1526 *
1527 * @access public
1528 * @static
1529 * @see Date_Calc::beginOfMonthBySpan()
1530 * @deprecated Method deprecated in Release 1.4.4
1531 */
1532 function beginOfPrevMonth($day = 0, $month = 0, $year = 0,
1533 $format = DATE_CALC_FORMAT)
1534 {
1535 if (empty($year)) {
1536 $year = Date_Calc::dateNow('%Y');
1537 }
1538 if (empty($month)) {
1539 $month = Date_Calc::dateNow('%m');
1540 }
1541 if (empty($day)) {
1542 $day = Date_Calc::dateNow('%d');
1543 }
1544 if ($month > 1) {
1545 $month--;
1546 $day = 1;
1547 } else {
1548 $year--;
1549 $month = 12;
1550 $day = 1;
1551 }
1552 return Date_Calc::dateFormat($day, $month, $year, $format);
1553 }
1554
1555 // }}}
1556 // {{{ endOfPrevMonth()
1557
1558 /**
1559 * Returns date of the last day of previous month for given date
1560 *
1561 * @param int $day the day of the month, default is current local day
1562 * @param int $month the month, default is current local month
1563 * @param int $year the year in four digit format, default is current local year
1564 * @param string $format the string indicating how to format the output
1565 *
1566 * @return string the date in the desired format
1567 *
1568 * @access public
1569 * @static
1570 * @see Date_Calc::endOfMonthBySpan()
1571 * @deprecated Method deprecated in Release 1.4.4
1572 */
1573 function endOfPrevMonth($day = 0, $month = 0, $year = 0,
1574 $format = DATE_CALC_FORMAT)
1575 {
1576 if (empty($year)) {
1577 $year = Date_Calc::dateNow('%Y');
1578 }
1579 if (empty($month)) {
1580 $month = Date_Calc::dateNow('%m');
1581 }
1582 if (empty($day)) {
1583 $day = Date_Calc::dateNow('%d');
1584 }
1585 if ($month > 1) {
1586 $month--;
1587 } else {
1588 $year--;
1589 $month = 12;
1590 }
1591 $day = Date_Calc::daysInMonth($month, $year);
1592 return Date_Calc::dateFormat($day, $month, $year, $format);
1593 }
1594
1595 // }}}
1596 // {{{ beginOfNextMonth()
1597
1598 /**
1599 * Returns date of begin of next month of given date
1600 *
1601 * @param int $day the day of the month, default is current local day
1602 * @param int $month the month, default is current local month
1603 * @param int $year the year in four digit format, default is current local year
1604 * @param string $format the string indicating how to format the output
1605 *
1606 * @return string the date in the desired format
1607 *
1608 * @access public
1609 * @static
1610 * @see Date_Calc::beginOfMonthBySpan()
1611 * @deprecated Method deprecated in Release 1.4.4
1612 */
1613 function beginOfNextMonth($day = 0, $month = 0, $year = 0,
1614 $format = DATE_CALC_FORMAT)
1615 {
1616 if (empty($year)) {
1617 $year = Date_Calc::dateNow('%Y');
1618 }
1619 if (empty($month)) {
1620 $month = Date_Calc::dateNow('%m');
1621 }
1622 if (empty($day)) {
1623 $day = Date_Calc::dateNow('%d');
1624 }
1625 if ($month < 12) {
1626 $month++;
1627 $day = 1;
1628 } else {
1629 $year++;
1630 $month = 1;
1631 $day = 1;
1632 }
1633 return Date_Calc::dateFormat($day, $month, $year, $format);
1634 }
1635
1636 // }}}
1637 // {{{ endOfNextMonth()
1638
1639 /**
1640 * Returns date of the last day of next month of given date
1641 *
1642 * @param int $day the day of the month, default is current local day
1643 * @param int $month the month, default is current local month
1644 * @param int $year the year in four digit format, default is current local year
1645 * @param string $format the string indicating how to format the output
1646 *
1647 * @return string the date in the desired format
1648 *
1649 * @access public
1650 * @static
1651 * @see Date_Calc::endOfMonthBySpan()
1652 * @deprecated Method deprecated in Release 1.4.4
1653 */
1654 function endOfNextMonth($day = 0, $month = 0, $year = 0,
1655 $format = DATE_CALC_FORMAT)
1656 {
1657 if (empty($year)) {
1658 $year = Date_Calc::dateNow('%Y');
1659 }
1660 if (empty($month)) {
1661 $month = Date_Calc::dateNow('%m');
1662 }
1663 if (empty($day)) {
1664 $day = Date_Calc::dateNow('%d');
1665 }
1666 if ($month < 12) {
1667 $month++;
1668 } else {
1669 $year++;
1670 $month = 1;
1671 }
1672 $day = Date_Calc::daysInMonth($month, $year);
1673 return Date_Calc::dateFormat($day, $month, $year, $format);
1674 }
1675
1676 // }}}
1677 // {{{ beginOfMonthBySpan()
1678
1679 /**
1680 * Returns date of the first day of the month in the number of months
1681 * from the given date
1682 *
1683 * @param int $months the number of months from the date provided.
1684 * Positive numbers go into the future.
1685 * Negative numbers go into the past.
1686 * 0 is the month presented in $month.
1687 * @param string $month the month, default is current local month
1688 * @param string $year the year in four digit format, default is the
1689 * current local year
1690 * @param string $format the string indicating how to format the output
1691 *
1692 * @return string the date in the desired format
1693 *
1694 * @access public
1695 * @static
1696 * @since Method available since Release 1.4.4
1697 */
1698 function beginOfMonthBySpan($months = 0, $month = 0, $year = 0,
1699 $format = DATE_CALC_FORMAT)
1700 {
1701 if (empty($year)) {
1702 $year = Date_Calc::dateNow('%Y');
1703 }
1704 if (empty($month)) {
1705 $month = Date_Calc::dateNow('%m');
1706 }
1707 if ($months > 0) {
1708 // future month
1709 $tmp_mo = $month + $months;
1710 $month = $tmp_mo % 12;
1711 if ($month == 0) {
1712 $month = 12;
1713 $year = $year + floor(($tmp_mo - 1) / 12);
1714 } else {
1715 $year = $year + floor($tmp_mo / 12);
1716 }
1717 } else {
1718 // past or present month
1719 $tmp_mo = $month + $months;
1720 if ($tmp_mo > 0) {
1721 // same year
1722 $month = $tmp_mo;
1723 } elseif ($tmp_mo == 0) {
1724 // prior dec
1725 $month = 12;
1726 $year--;
1727 } else {
1728 // some time in a prior year
1729 $month = 12 + ($tmp_mo % 12);
1730 $year = $year + floor($tmp_mo / 12);
1731 }
1732 }
1733 return Date_Calc::dateFormat(1, $month, $year, $format);
1734 }
1735
1736 // }}}
1737 // {{{ endOfMonthBySpan()
1738
1739 /**
1740 * Returns date of the last day of the month in the number of months
1741 * from the given date
1742 *
1743 * @param int $months the number of months from the date provided.
1744 * Positive numbers go into the future.
1745 * Negative numbers go into the past.
1746 * 0 is the month presented in $month.
1747 * @param string $month the month, default is current local month
1748 * @param string $year the year in four digit format, default is the
1749 * current local year
1750 * @param string $format the string indicating how to format the output
1751 *
1752 * @return string the date in the desired format
1753 *
1754 * @access public
1755 * @static
1756 * @since Method available since Release 1.4.4
1757 */
1758 function endOfMonthBySpan($months = 0, $month = 0, $year = 0,
1759 $format = DATE_CALC_FORMAT)
1760 {
1761 if (empty($year)) {
1762 $year = Date_Calc::dateNow('%Y');
1763 }
1764 if (empty($month)) {
1765 $month = Date_Calc::dateNow('%m');
1766 }
1767 if ($months > 0) {
1768 // future month
1769 $tmp_mo = $month + $months;
1770 $month = $tmp_mo % 12;
1771 if ($month == 0) {
1772 $month = 12;
1773 $year = $year + floor(($tmp_mo - 1) / 12);
1774 } else {
1775 $year = $year + floor($tmp_mo / 12);
1776 }
1777 } else {
1778 // past or present month
1779 $tmp_mo = $month + $months;
1780 if ($tmp_mo > 0) {
1781 // same year
1782 $month = $tmp_mo;
1783 } elseif ($tmp_mo == 0) {
1784 // prior dec
1785 $month = 12;
1786 $year--;
1787 } else {
1788 // some time in a prior year
1789 $month = 12 + ($tmp_mo % 12);
1790 $year = $year + floor($tmp_mo / 12);
1791 }
1792 }
1793 return Date_Calc::dateFormat(Date_Calc::daysInMonth($month, $year),
1794 $month, $year, $format);
1795 }
1796
1797 // }}}
1798 // {{{ firstOfMonthWeekday()
1799
1800 /**
1801 * Find the day of the week for the first of the month of given date
1802 *
1803 * @param int $month the month, default is current local month
1804 * @param int $year the year in four digit format, default is current local year
1805 *
1806 * @return int number of weekday for the first day, 0=Sunday
1807 *
1808 * @access public
1809 * @static
1810 */
1811 function firstOfMonthWeekday($month = 0, $year = 0)
1812 {
1813 if (empty($year)) {
1814 $year = Date_Calc::dateNow('%Y');
1815 }
1816 if (empty($month)) {
1817 $month = Date_Calc::dateNow('%m');
1818 }
1819 return Date_Calc::dayOfWeek('01', $month, $year);
1820 }
1821
1822 // }}}
1823 // {{{ NWeekdayOfMonth()
1824
1825 /**
1826 * Calculates the date of the Nth weekday of the month,
1827 * such as the second Saturday of January 2000
1828 *
1829 * @param int $week the number of the week to get
1830 * (1 = first, etc. Also can be 'last'.)
1831 * @param int $dow the day of the week (0 = Sunday)
1832 * @param int $month the month
1833 * @param int $year the year. Use the complete year instead of the
1834 * abbreviated version. E.g. use 2005, not 05.
1835 * Do not add leading 0's for years prior to 1000.
1836 * @param string $format the string indicating how to format the output
1837 *
1838 * @return string the date in the desired format
1839 *
1840 * @access public
1841 * @static
1842 */
1843 function NWeekdayOfMonth($week, $dow, $month, $year,
1844 $format = DATE_CALC_FORMAT)
1845 {
1846 if (is_numeric($week)) {
1847 $DOW1day = ($week - 1) * 7 + 1;
1848 $DOW1 = Date_Calc::dayOfWeek($DOW1day, $month, $year);
1849 $wdate = ($week - 1) * 7 + 1 + (7 + $dow - $DOW1) % 7;
1850 if ($wdate > Date_Calc::daysInMonth($month, $year)) {
1851 return -1;
1852 } else {
1853 return Date_Calc::dateFormat($wdate, $month, $year, $format);
1854 }
1855 } elseif ($week == 'last' && $dow < 7) {
1856 $lastday = Date_Calc::daysInMonth($month, $year);
1857 $lastdow = Date_Calc::dayOfWeek($lastday, $month, $year);
1858 $diff = $dow - $lastdow;
1859 if ($diff > 0) {
1860 return Date_Calc::dateFormat($lastday - (7 - $diff), $month,
1861 $year, $format);
1862 } else {
1863 return Date_Calc::dateFormat($lastday + $diff, $month,
1864 $year, $format);
1865 }
1866 } else {
1867 return -1;
1868 }
1869 }
1870
1871 // }}}
1872 // {{{ isValidDate()
1873
1874 /**
1875 * Returns true for valid date, false for invalid date
1876 *
1877 * @param int $day the day of the month
1878 * @param int $month the month
1879 * @param int $year the year. Use the complete year instead of the
1880 * abbreviated version. E.g. use 2005, not 05.
1881 * Do not add leading 0's for years prior to 1000.
1882 *
1883 * @return boolean
1884 *
1885 * @access public
1886 * @static
1887 */
1888 function isValidDate($day, $month, $year)
1889 {
1890 if ($year < 0 || $year > 9999) {
1891 return false;
1892 }
1893 if (!checkdate($month, $day, $year)) {
1894 return false;
1895 }
1896 return true;
1897 }
1898
1899 // }}}
1900 // {{{ isLeapYear()
1901
1902 /**
1903 * Returns true for a leap year, else false
1904 *
1905 * @param int $year the year. Use the complete year instead of the
1906 * abbreviated version. E.g. use 2005, not 05.
1907 * Do not add leading 0's for years prior to 1000.
1908 *
1909 * @return boolean
1910 *
1911 * @access public
1912 * @static
1913 */
1914 function isLeapYear($year = 0)
1915 {
1916 if (empty($year)) {
1917 $year = Date_Calc::dateNow('%Y');
1918 }
1919 if (preg_match('/\D/', $year)) {
1920 return false;
1921 }
1922 if ($year < 1000) {
1923 return false;
1924 }
1925 if ($year < 1582) {
1926 // pre Gregorio XIII - 1582
1927 return ($year % 4 == 0);
1928 } else {
1929 // post Gregorio XIII - 1582
1930 return (($year % 4 == 0) && ($year % 100 != 0)) || ($year % 400 == 0);
1931 }
1932 }
1933
1934 // }}}
1935 // {{{ isFutureDate()
1936
1937 /**
1938 * Determines if given date is a future date from now
1939 *
1940 * @param int $day the day of the month
1941 * @param int $month the month
1942 * @param int $year the year. Use the complete year instead of the
1943 * abbreviated version. E.g. use 2005, not 05.
1944 * Do not add leading 0's for years prior to 1000.
1945 *
1946 * @return boolean
1947 *
1948 * @access public
1949 * @static
1950 */
1951 function isFutureDate($day, $month, $year)
1952 {
1953 $this_year = Date_Calc::dateNow('%Y');
1954 $this_month = Date_Calc::dateNow('%m');
1955 $this_day = Date_Calc::dateNow('%d');
1956
1957 if ($year > $this_year) {
1958 return true;
1959 } elseif ($year == $this_year) {
1960 if ($month > $this_month) {
1961 return true;
1962 } elseif ($month == $this_month) {
1963 if ($day > $this_day) {
1964 return true;
1965 }
1966 }
1967 }
1968 return false;
1969 }
1970
1971 // }}}
1972 // {{{ isPastDate()
1973
1974 /**
1975 * Determines if given date is a past date from now
1976 *
1977 * @param int $day the day of the month
1978 * @param int $month the month
1979 * @param int $year the year. Use the complete year instead of the
1980 * abbreviated version. E.g. use 2005, not 05.
1981 * Do not add leading 0's for years prior to 1000.
1982 *
1983 * @return boolean
1984 *
1985 * @access public
1986 * @static
1987 */
1988 function isPastDate($day, $month, $year)
1989 {
1990 $this_year = Date_Calc::dateNow('%Y');
1991 $this_month = Date_Calc::dateNow('%m');
1992 $this_day = Date_Calc::dateNow('%d');
1993
1994 if ($year < $this_year) {
1995 return true;
1996 } elseif ($year == $this_year) {
1997 if ($month < $this_month) {
1998 return true;
1999 } elseif ($month == $this_month) {
2000 if ($day < $this_day) {
2001 return true;
2002 }
2003 }
2004 }
2005 return false;
2006 }
2007
2008 // }}}
2009 // {{{ dateDiff()
2010
2011 /**
2012 * Returns number of days between two given dates
2013 *
2014 * @param int $day1 the day of the month
2015 * @param int $month1 the month
2016 * @param int $year1 the year. Use the complete year instead of the
2017 * abbreviated version. E.g. use 2005, not 05.
2018 * Do not add leading 0's for years prior to 1000.
2019 * @param int $day2 the day of the month
2020 * @param int $month2 the month
2021 * @param int $year2 the year. Use the complete year instead of the
2022 * abbreviated version. E.g. use 2005, not 05.
2023 * Do not add leading 0's for years prior to 1000.
2024 *
2025 * @return int the absolute number of days between the two dates.
2026 * If an error occurs, -1 is returned.
2027 *
2028 * @access public
2029 * @static
2030 */
2031 function dateDiff($day1, $month1, $year1, $day2, $month2, $year2)
2032 {
2033 if (!Date_Calc::isValidDate($day1, $month1, $year1)) {
2034 return -1;
2035 }
2036 if (!Date_Calc::isValidDate($day2, $month2, $year2)) {
2037 return -1;
2038 }
2039 return abs(Date_Calc::dateToDays($day1, $month1, $year1)
2040 - Date_Calc::dateToDays($day2, $month2, $year2));
2041 }
2042
2043 // }}}
2044 // {{{ compareDates()
2045
2046 /**
2047 * Compares two dates
2048 *
2049 * @param int $day1 the day of the month
2050 * @param int $month1 the month
2051 * @param int $year1 the year. Use the complete year instead of the
2052 * abbreviated version. E.g. use 2005, not 05.
2053 * Do not add leading 0's for years prior to 1000.
2054 * @param int $day2 the day of the month
2055 * @param int $month2 the month
2056 * @param int $year2 the year. Use the complete year instead of the
2057 * abbreviated version. E.g. use 2005, not 05.
2058 * Do not add leading 0's for years prior to 1000.
2059 *
2060 * @return int 0 if the dates are equal. 1 if date 1 is later, -1 if
2061 * date 1 is earlier.
2062 *
2063 * @access public
2064 * @static
2065 */
2066 function compareDates($day1, $month1, $year1, $day2, $month2, $year2)
2067 {
2068 $ndays1 = Date_Calc::dateToDays($day1, $month1, $year1);
2069 $ndays2 = Date_Calc::dateToDays($day2, $month2, $year2);
2070 if ($ndays1 == $ndays2) {
2071 return 0;
2072 }
2073 return ($ndays1 > $ndays2) ? 1 : -1;
2074 }
2075
2076 // }}}
2077 }
2078
2079 // }}}
2080
2081 /*
2082 * Local variables:
2083 * mode: php
2084 * tab-width: 4
2085 * c-basic-offset: 4
2086 * c-hanging-comment-ender-p: nil
2087 * End:
2088 */
2089 ?>