2 /**********************************************************************
3 Copyright (C) FrontAccounting, LLC.
4 Released under the terms of the GNU General Public License, GPL,
5 as published by the Free Software Foundation, either version 3
6 of the License, or (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
13 date validation and parsing functions
15 These functions refer to the global variable defining the date format
16 The date format is defined in config.php called dateformats
17 this can be a string either "d/m/Y" for UK/Australia/New Zealand dates or
18 "m/d/Y" for US/Canada format dates depending on setting in preferences.
22 function __date($year, $month, $day)
24 global $SysPrefs, $tmonths;
26 $how = user_date_format();
27 $sep = $SysPrefs->dateseps[user_date_sep()];
38 return $month.$sep.$day.$sep.$year;
40 return $day.$sep.$month.$sep.$year;
42 return $year.$sep.$month.$sep.$day;
44 return $tmonths[$month].$sep.$day.$sep.$year;
46 return $day.$sep.$tmonths[$month].$sep.$year;
48 return $year.$sep.$tmonths[$month].$sep.$day;
51 function is_date($date_)
55 if ($date_ == null || $date_ == "")
57 $how = user_date_format();
58 $sep = $SysPrefs->dateseps[user_date_sep()];
60 $date_ = trim($date_);
61 $date = str_replace($sep, "", $date_);
66 $dd = explode($sep, $date_);
70 $month = array_search($dd[0], $tmonths);
76 $month = array_search($dd[1], $tmonths);
82 $month = array_search($dd[1], $tmonths);
88 elseif (strlen($date) == 6)
92 $day = substr($date,2,2);
93 $month = substr($date,0,2);
94 $year = substr($date,4,2);
98 $day = substr($date,0,2);
99 $month = substr($date,2,2);
100 $year = substr($date,4,2);
104 $day = substr($date,4,2);
105 $month = substr($date,2,2);
106 $year = substr($date,0,2);
109 elseif (strlen($date) == 8)
113 $day = substr($date,2,2);
114 $month = substr($date,0,2);
115 $year = substr($date,4,4);
119 $day = substr($date,0,2);
120 $month = substr($date,2,2);
121 $year = substr($date,4,4);
125 $day = substr($date,6,2);
126 $month = substr($date,4,2);
127 $year = substr($date,0,4);
130 if (!isset($year)|| (int)$year > 9999)
135 if (is_long((int)$day) && is_long((int)$month) && is_long((int)$year))
138 if ($SysPrefs->date_system == 1)
139 list($year, $month, $day) = jalali_to_gregorian($year, $month, $day);
140 elseif ($SysPrefs->date_system == 2)
141 list($year, $month, $day) = islamic_to_gregorian($year, $month, $day);
142 if (checkdate((int)$month, (int)$day, (int)$year))
152 { /*Can't be in an appropriate DefaultDateFormat */
155 } //end of is_date function
164 if ($SysPrefs->date_system == 1)
165 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
166 elseif ($SysPrefs->date_system == 2)
167 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
168 return __date($year, $month, $day);
173 if (user_date_format() == 0)
174 return date("h:i a");
179 // Retrieve and optionaly set default date for new document.
181 function new_doc_date($date=null)
183 if (isset($date) && $date != '')
184 $_SESSION['_default_date'] = $date;
186 if (!isset($_SESSION['_default_date']) || !sticky_doc_date())
187 $_SESSION['_default_date'] = Today();
189 return $_SESSION['_default_date'];
192 function is_date_in_fiscalyear($date, $convert=false)
194 global $path_to_root;
195 include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
198 $date2 = sql2date($date);
202 if (user_check_access('SA_MULTIFISCALYEARS')) // allow all open years for this one
203 return is_date_in_fiscalyears($date2, false);
205 if (is_date_closed($date2))
207 $myrow = get_current_fiscalyear();
208 $begin = sql2date($myrow['begin']);
209 $end = sql2date($myrow['end']);
210 if (date1_greater_date2($begin, $date2) || date1_greater_date2($date2, $end))
217 function is_date_closed($date)
219 return !date1_greater_date2($date, sql2date(get_company_pref('gl_closing_date')));
222 function begin_fiscalyear()
224 global $path_to_root;
225 include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
227 $myrow = get_current_fiscalyear();
228 return sql2date($myrow['begin']);
231 function end_fiscalyear()
233 global $path_to_root;
234 include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
236 $myrow = get_current_fiscalyear();
237 return sql2date($myrow['end']);
240 function begin_month($date)
243 list($day, $month, $year) = explode_date_to_dmy($date);
244 if ($SysPrefs->date_system == 1)
245 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
246 elseif ($SysPrefs->date_system == 2)
247 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
248 return __date($year, $month, 1);
251 function days_in_month($month, $year)
255 if ($SysPrefs->date_system == 1)
257 $days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, ((((((($year - (($year > 0) ? 474 : 473)) % 2820) + 474) + 38) * 682) % 2816) < 682 ? 30 : 29));
259 elseif ($SysPrefs->date_system == 2)
261 $days_in_month = array(30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, (((((11 * $year) + 14) % 30) < 11) ? 30 : 29));
263 else // gregorian date
264 $days_in_month = array(31, ((!($year % 4 ) && (($year % 100) || !($year % 400)))?29:28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
266 return $days_in_month[$month - 1];
269 function end_month($date)
273 list($day, $month, $year) = explode_date_to_dmy($date);
274 if ($SysPrefs->date_system == 1)
276 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
278 elseif ($SysPrefs->date_system == 2)
280 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
283 return __date($year, $month, days_in_month($month, $year));
286 function add_days($date, $days) // accepts negative values as well
289 list($day, $month, $year) = explode_date_to_dmy($date);
290 $timet = mktime(0,0,0, $month, $day + $days, $year);
291 if ($SysPrefs->date_system == 1 || $SysPrefs->date_system == 2)
293 if ($SysPrefs->date_system == 1)
294 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
295 elseif ($SysPrefs->date_system == 2)
296 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
297 return __date($year, $month, $day);
299 list($year, $month, $day) = explode("-", date("Y-m-d", $timet));
300 return __date($year, $month, $day);
303 function add_months($date, $months) // accepts negative values as well
307 list($day, $month, $year) = explode_date_to_dmy($date);
309 $months += $year*12+$month;
310 $month = ($months-1)%12+1;
311 $year = ($months-$month)/12;
313 $timet = mktime(0,0,0, $month, min($day, days_in_month($month, $year)), $year);
315 if ($SysPrefs->date_system == 1 || $SysPrefs->date_system == 2)
317 if ($SysPrefs->date_system == 1)
318 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
319 elseif ($SysPrefs->date_system == 2)
320 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
321 return __date($year, $month, $day);
323 list($year, $month, $day) = explode("-", date("Y-m-d", $timet));
324 return __date($year, $month, $day);
327 function add_years($date, $years) // accepts negative values as well
331 list($day, $month, $year) = explode_date_to_dmy($date);
332 $timet = Mktime(0,0,0, $month, $day, $year + $years);
333 if ($SysPrefs->date_system == 1 || $SysPrefs->date_system == 2)
335 if ($SysPrefs->date_system == 1)
336 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
337 elseif ($SysPrefs->date_system == 2)
338 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
339 return __date($year, $month, $day);
341 list($year, $month, $day) = explode("-", date("Y-m-d", $timet));
342 return __date($year, $month, $day);
345 //_______________________________________________________________
347 function sql2date($date_)
351 //for MySQL dates are in the format YYYY-mm-dd
353 if (strpos($date_, "/"))
354 { // In MySQL it could be either / or -
355 list($year, $month, $day) = explode("/", $date_);
357 elseif (strpos ($date_, "-"))
359 list($year, $month, $day) = explode("-", $date_);
361 if (!isset($day)) // data format error
364 if (strlen($day) > 4)
365 { /*chop off the time stuff */
366 $day = substr($day, 0, 2);
368 if ($SysPrefs->date_system == 1)
369 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
370 elseif ($SysPrefs->date_system == 2)
371 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
372 return __date($year, $month, $day);
373 } // end function sql2date
376 function date2sql($date_)
378 global $SysPrefs, $tmonths;
379 /* takes a date in a the format specified in $DefaultDateFormat
380 and converts to a yyyy/mm/dd format */
382 $how = user_date_format();
383 $sep = $SysPrefs->dateseps[user_date_sep()];
385 if ($date_ == null || strlen($date_) == 0)
388 $date_ = trim($date_);
389 $year = $month = $day = 0;
390 // Split up the date by the separator based on "how" to split it
391 if ($how == 0 || $how == 3) // MMDDYYYY or MmmDDYYYY
392 list($month, $day, $year) = explode($sep, $date_);
393 elseif ($how == 1 || $how == 4) // DDMMYYYY or DDMmYYYY
394 list($day, $month, $year) = explode($sep, $date_);
395 else // $how == 2 || $how == 5, YYYYMMDD or YYYYMmmDD
396 list($year, $month, $day) = explode($sep, $date_);
400 $month = array_search($month, $tmonths);
402 //to modify assumption in 2030
403 if ($SysPrefs->date_system == 0 || $SysPrefs->date_system == 3)
409 elseif ((int)$year > 59 && (int)$year < 100)
414 if ((int)$year > 9999)
418 if ($SysPrefs->date_system == 1)
419 list($year, $month, $day) = jalali_to_gregorian($year, $month, $day);
420 elseif ($SysPrefs->date_system == 2)
421 list($year, $month, $day) = islamic_to_gregorian($year, $month, $day);
423 return sprintf("%04d-%02d-%02d", $year, $month, $day);
427 * Compare dates in sql format.
428 * Return +1 if sql date1>date2, -1 if date1<date2,
429 * or 0 if dates are equal.
431 function sql_date_comp($date1, $date2)
433 @list($year1, $month1, $day1) = explode("-", $date1);
434 @list($year2, $month2, $day2) = explode("-", $date2);
436 if ($year1 != $year2) {
437 return $year1 < $year2 ? -1 : +1;
439 elseif ($month1 != $month2) {
440 return $month1 < $month2 ? -1 : +1;
442 elseif ($day1 != $day2) {
443 return $day1 < $day2 ? -1 : +1;
448 Compare dates in user format.
450 function date_comp($date1, $date2)
452 $date1 = date2sql($date1);
453 $date2 = date2sql($date2);
455 return sql_date_comp($date1, $date2);
458 function date1_greater_date2 ($date1, $date2)
461 /* returns 1 true if date1 is greater than date_ 2 */
463 $date1 = date2sql($date1);
464 $date2 = date2sql($date2);
466 @list($year1, $month1, $day1) = explode("-", $date1);
467 @list($year2, $month2, $day2) = explode("-", $date2);
473 elseif ($year1 == $year2)
475 if ($month1 > $month2)
479 elseif ($month1 == $month2)
490 function date_diff2 ($date1, $date2, $period)
493 /* expects dates in the format specified in $DefaultDateFormat - period can be one of 'd','w','y','m'
494 months are assumed to be 30 days and years 365.25 days This only works
495 provided that both dates are after 1970. Also only works for dates up to the year 2035 ish */
497 $date1 = date2sql($date1);
498 $date2 = date2sql($date2);
499 list($year1, $month1, $day1) = explode("-", $date1);
500 list($year2, $month2, $day2) = explode("-", $date2);
502 $stamp1 = mktime(0,0,0, (int)$month1, (int)$day1, (int)$year1);
503 $stamp2 = mktime(0,0,0, (int)$month2, (int)$day2, (int)$year2);
504 $difference = $stamp1 - $stamp2;
506 /* difference is the number of seconds between each date negative if date_ 2 > date_ 1 */
511 return (int)($difference / (24 * 60 * 60));
513 return (int)($difference / (24 * 60 * 60 * 7));
515 return (int)($difference / (24 * 60 * 60 * 30));
519 return (int)($difference / (24 * 60 * 60 * 365.25));
525 function explode_date_to_dmy($date_)
527 $date = date2sql($date_);
532 list($year, $month, $day) = explode("-", $date);
533 return array($day, $month, $year);
538 return (int) ($a / $b);
540 /* Based on convertor to and from Gregorian and Jalali calendars.
541 Copyright (C) 2000 Roozbeh Pournader and Mohammad Toossi
542 Released under GNU General Public License */
544 function gregorian_to_jalali ($g_y, $g_m, $g_d)
546 $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
547 $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
553 $g_day_no = 365 * $gy + div($gy + 3, 4) - div($gy + 99, 100) + div($gy + 399, 400);
555 for ($i = 0; $i < $gm; ++$i)
556 $g_day_no += $g_days_in_month[$i];
557 if ($gm > 1 && (($gy % 4 == 0 && $gy % 100 != 0) || ($gy % 400 == 0)))
558 /* leap and after Feb */
561 $j_day_no = $g_day_no - 79;
563 $j_np = div($j_day_no, 12053); /* 12053 = 365*33 + 32/4 */
566 $jy = 979 + 33 * $j_np + 4 * div($j_day_no, 1461); /* 1461 = 365*4 + 4/4 */
570 if ($j_day_no >= 366)
572 $jy += div($j_day_no - 1, 365);
573 $j_day_no = ($j_day_no - 1) % 365;
576 for ($i = 0; $i < 11 && $j_day_no >= $j_days_in_month[$i]; ++$i)
577 $j_day_no -= $j_days_in_month[$i];
581 return array($jy, $jm, $jd);
584 function jalali_to_gregorian($j_y, $j_m, $j_d)
586 $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
587 $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
593 $j_day_no = 365 * $jy + div($jy, 33) * 8 + div($jy % 33 + 3, 4);
594 for ($i = 0; $i < $jm; ++$i)
595 $j_day_no += $j_days_in_month[$i];
599 $g_day_no = $j_day_no + 79;
601 $gy = 1600 + 400 * div($g_day_no, 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */
605 if ($g_day_no >= 36525) /* 36525 = 365*100 + 100/4 */
608 $gy += 100 * div($g_day_no, 36524); /* 36524 = 365*100 + 100/4 - 100/100 */
611 if ($g_day_no >= 365)
617 $gy += 4 * div($g_day_no, 1461); /* 1461 = 365*4 + 4/4 */
620 if ($g_day_no >= 366)
625 $gy += div($g_day_no, 365);
629 for ($i = 0; $g_day_no >= $g_days_in_month[$i] + ($i == 1 && $leap); $i++)
630 $g_day_no -= $g_days_in_month[$i] + ($i == 1 && $leap);
634 return array($gy, $gm, $gd);
636 /* Based on Hidri Date Script
637 Released under GNU General Public License */
638 function gregorian_to_islamic($g_y, $g_m, $g_d)
643 if (($y > 1582) || (($y == 1582) && ($m > 10)) || (($y == 1582) &&
644 ($m == 10) && ($d > 14)))
646 $jd = (int)((1461 * ($y + 4800 + (int)(($m - 14) / 12)))/ 4) +
647 (int)((367 * ($m - 2 - 12 * ((int)(($m - 14) / 12)))) / 12) -
648 (int)((3 * ((int)(($y + 4900 + (int)(($m - 14) / 12)) / 100))) / 4) + $d - 32075;
652 $jd = 367 * $y - (int)((7 * ($y + 5001 + (int)(($m - 9) / 7))) / 4) +
653 (int)((275 * $m) / 9) + $d + 1729777;
655 $l = $jd - 1948440 + 10632;
656 $n = (int)(($l - 1) / 10631);
657 $l = $l - 10631 * $n + 354;
658 $j = ((int)((10985 - $l) / 5316)) * ((int)((50 * $l) / 17719)) +
659 ((int)($l / 5670)) * ((int)((43 * $l) / 15238));
660 $l = $l - ((int)((30 - $j) / 15)) * ((int)((17719 * $j) / 50)) -
661 ((int)($j / 16)) * ((int)((15238 * $j) / 43)) + 29;
662 $m = (int)((24 * $l) / 709);
663 $d = $l - (int)((709 * $m) / 24);
664 $y = 30 * $n + $j - 30;
665 return array($y, $m, $d);
668 function islamic_to_gregorian($i_y, $i_m, $i_d)
674 $jd = (int)((11 * $y + 3) / 30) + 354 * $y + 30 * $m - (int)(($m - 1) / 2) + $d + 1948440 - 385;
678 $n = (int)((4 * $l) / 146097);
679 $l = $l - (int)((146097 * $n + 3) / 4);
680 $i = (int)((4000 * ($l + 1)) / 1461001);
681 $l = $l - (int)((1461 * $i) / 4) + 31;
682 $j = (int)((80 * $l) / 2447);
683 $d = $l - (int)((2447 * $j) / 80);
685 $m = $j + 2 - 12 * $l;
686 $y = 100 * ($n - 49) + $i + $l;
691 $k = (int)(($j - 1) / 1461);
693 $n = (int)(($l - 1) / 365) - (int)($l / 1461);
694 $i = $l - 365 * $n + 30;
695 $j = (int)((80 * $i) / 2447);
696 $d = $i - (int)((2447 * $j) / 80);
698 $m = $j + 2 - 12 * $i;
699 $y = 4 * $k + $n + $i - 4716;
701 return array($y, $m, $d);