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 (is_date_closed($date2))
205 if (user_check_access('SA_MULTIFISCALYEARS')) // allow all open years for this one
206 return is_date_in_fiscalyears($date2, false);
208 $myrow = get_current_fiscalyear();
209 $begin = sql2date($myrow['begin']);
210 $end = sql2date($myrow['end']);
211 if (date1_greater_date2($begin, $date2) || date1_greater_date2($date2, $end))
218 function is_date_closed($date)
220 return !date1_greater_date2($date, sql2date(get_company_pref('gl_closing_date')));
223 function begin_fiscalyear()
225 global $path_to_root;
226 include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
228 $myrow = get_current_fiscalyear();
229 return sql2date($myrow['begin']);
232 function end_fiscalyear()
234 global $path_to_root;
235 include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
237 $myrow = get_current_fiscalyear();
238 return sql2date($myrow['end']);
241 function begin_month($date)
244 list($day, $month, $year) = explode_date_to_dmy($date);
245 if ($SysPrefs->date_system == 1)
246 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
247 elseif ($SysPrefs->date_system == 2)
248 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
249 return __date($year, $month, 1);
252 function days_in_month($month, $year)
256 if ($SysPrefs->date_system == 1)
258 $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));
260 elseif ($SysPrefs->date_system == 2)
262 $days_in_month = array(30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, (((((11 * $year) + 14) % 30) < 11) ? 30 : 29));
264 else // gregorian date
265 $days_in_month = array(31, ((!($year % 4 ) && (($year % 100) || !($year % 400)))?29:28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
267 return $days_in_month[$month - 1];
270 function end_month($date)
274 list($day, $month, $year) = explode_date_to_dmy($date);
275 if ($SysPrefs->date_system == 1)
277 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
279 elseif ($SysPrefs->date_system == 2)
281 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
284 return __date($year, $month, days_in_month($month, $year));
287 function add_days($date, $days) // accepts negative values as well
290 list($day, $month, $year) = explode_date_to_dmy($date);
291 $timet = mktime(0,0,0, $month, $day + $days, $year);
292 if ($SysPrefs->date_system == 1 || $SysPrefs->date_system == 2)
294 if ($SysPrefs->date_system == 1)
295 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
296 elseif ($SysPrefs->date_system == 2)
297 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
298 return __date($year, $month, $day);
300 list($year, $month, $day) = explode("-", date("Y-m-d", $timet));
301 return __date($year, $month, $day);
304 function add_months($date, $months) // accepts negative values as well
308 list($day, $month, $year) = explode_date_to_dmy($date);
310 $months += $year*12+$month;
311 $month = ($months-1)%12+1;
312 $year = ($months-$month)/12;
314 $timet = mktime(0,0,0, $month, min($day, days_in_month($month, $year)), $year);
316 if ($SysPrefs->date_system == 1 || $SysPrefs->date_system == 2)
318 if ($SysPrefs->date_system == 1)
319 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
320 elseif ($SysPrefs->date_system == 2)
321 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
322 return __date($year, $month, $day);
324 list($year, $month, $day) = explode("-", date("Y-m-d", $timet));
325 return __date($year, $month, $day);
328 function add_years($date, $years) // accepts negative values as well
332 list($day, $month, $year) = explode_date_to_dmy($date);
333 $timet = Mktime(0,0,0, $month, $day, $year + $years);
334 if ($SysPrefs->date_system == 1 || $SysPrefs->date_system == 2)
336 if ($SysPrefs->date_system == 1)
337 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
338 elseif ($SysPrefs->date_system == 2)
339 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
340 return __date($year, $month, $day);
342 list($year, $month, $day) = explode("-", date("Y-m-d", $timet));
343 return __date($year, $month, $day);
346 //_______________________________________________________________
348 function sql2date($date_)
352 //for MySQL dates are in the format YYYY-mm-dd
355 if (strpos($date_, "/"))
356 { // In MySQL it could be either / or -
357 list($year, $month, $day) = explode("/", $date_);
359 elseif (strpos ($date_, "-"))
361 list($year, $month, $day) = explode("-", $date_);
363 if (!isset($day)) // data format error
366 if (strlen($day) > 4)
367 { /*chop off the time stuff */
368 $day = substr($day, 0, 2);
370 if ($SysPrefs->date_system == 1)
371 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
372 elseif ($SysPrefs->date_system == 2)
373 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
374 return __date($year, $month, $day);
375 } // end function sql2date
378 function date2sql($date_)
380 global $SysPrefs, $tmonths;
381 /* takes a date in a the format specified in $DefaultDateFormat
382 and converts to a yyyy/mm/dd format */
384 $how = user_date_format();
385 $sep = $SysPrefs->dateseps[user_date_sep()];
387 $date_ = trim($date_);
388 if ($date_ == null || strlen($date_) == 0)
391 $year = $month = $day = 0;
392 // Split up the date by the separator based on "how" to split it
393 if ($how == 0 || $how == 3) // MMDDYYYY or MmmDDYYYY
394 list($month, $day, $year) = explode($sep, $date_);
395 elseif ($how == 1 || $how == 4) // DDMMYYYY or DDMmYYYY
396 list($day, $month, $year) = explode($sep, $date_);
397 else // $how == 2 || $how == 5, YYYYMMDD or YYYYMmmDD
398 list($year, $month, $day) = explode($sep, $date_);
403 $month = array_search($month, $tmonths);
405 if ($year+$day+$month) {
406 //to modify assumption in 2030
407 if ($SysPrefs->date_system == 0 || $SysPrefs->date_system == 3)
413 elseif ((int)$year > 59 && (int)$year < 100)
418 if ((int)$year > 9999)
422 if ($SysPrefs->date_system == 1)
423 list($year, $month, $day) = jalali_to_gregorian($year, $month, $day);
424 elseif ($SysPrefs->date_system == 2)
425 list($year, $month, $day) = islamic_to_gregorian($year, $month, $day);
427 return sprintf("%04d-%02d-%02d", $year, $month, $day);
431 * Compare dates in sql format.
432 * Return +1 if sql date1>date2, -1 if date1<date2,
433 * or 0 if dates are equal.
435 function sql_date_comp($date1, $date2)
437 @list($year1, $month1, $day1) = explode("-", $date1);
438 @list($year2, $month2, $day2) = explode("-", $date2);
440 if ($year1 != $year2) {
441 return $year1 < $year2 ? -1 : +1;
443 elseif ($month1 != $month2) {
444 return $month1 < $month2 ? -1 : +1;
446 elseif ($day1 != $day2) {
447 return $day1 < $day2 ? -1 : +1;
452 Compare dates in user format.
454 function date_comp($date1, $date2)
456 $date1 = date2sql($date1);
457 $date2 = date2sql($date2);
459 return sql_date_comp($date1, $date2);
462 function date1_greater_date2 ($date1, $date2)
465 /* returns 1 true if date1 is greater than date_ 2 */
467 $date1 = date2sql($date1);
468 $date2 = date2sql($date2);
470 @list($year1, $month1, $day1) = explode("-", $date1);
471 @list($year2, $month2, $day2) = explode("-", $date2);
477 elseif ($year1 == $year2)
479 if ($month1 > $month2)
483 elseif ($month1 == $month2)
494 function date_diff2 ($date1, $date2, $period)
497 /* expects dates in the format specified in $DefaultDateFormat - period can be one of 'd','w','y','m'
498 months are assumed to be 30 days and years 365.25 days This only works
499 provided that both dates are after 1970. Also only works for dates up to the year 2035 ish */
501 $date1 = date2sql($date1);
502 $date2 = date2sql($date2);
503 list($year1, $month1, $day1) = explode("-", $date1);
504 list($year2, $month2, $day2) = explode("-", $date2);
506 $stamp1 = mktime(0,0,0, (int)$month1, (int)$day1, (int)$year1);
507 $stamp2 = mktime(0,0,0, (int)$month2, (int)$day2, (int)$year2);
508 $difference = $stamp1 - $stamp2;
510 /* difference is the number of seconds between each date negative if date_ 2 > date_ 1 */
515 return (int)($difference / (24 * 60 * 60));
517 return (int)($difference / (24 * 60 * 60 * 7));
519 return (int)($difference / (24 * 60 * 60 * 30));
523 return (int)($difference / (24 * 60 * 60 * 365.25));
529 function explode_date_to_dmy($date_)
531 $date = date2sql($date_);
536 list($year, $month, $day) = explode("-", $date);
537 return array($day, $month, $year);
542 return (int) ($a / $b);
544 /* Based on convertor to and from Gregorian and Jalali calendars.
545 Copyright (C) 2000 Roozbeh Pournader and Mohammad Toossi
546 Released under GNU General Public License */
548 function gregorian_to_jalali ($g_y, $g_m, $g_d)
550 $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
551 $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
557 $g_day_no = 365 * $gy + div($gy + 3, 4) - div($gy + 99, 100) + div($gy + 399, 400);
559 for ($i = 0; $i < $gm; ++$i)
560 $g_day_no += $g_days_in_month[$i];
561 if ($gm > 1 && (($gy % 4 == 0 && $gy % 100 != 0) || ($gy % 400 == 0)))
562 /* leap and after Feb */
565 $j_day_no = $g_day_no - 79;
567 $j_np = div($j_day_no, 12053); /* 12053 = 365*33 + 32/4 */
570 $jy = 979 + 33 * $j_np + 4 * div($j_day_no, 1461); /* 1461 = 365*4 + 4/4 */
574 if ($j_day_no >= 366)
576 $jy += div($j_day_no - 1, 365);
577 $j_day_no = ($j_day_no - 1) % 365;
580 for ($i = 0; $i < 11 && $j_day_no >= $j_days_in_month[$i]; ++$i)
581 $j_day_no -= $j_days_in_month[$i];
585 return array($jy, $jm, $jd);
588 function jalali_to_gregorian($j_y, $j_m, $j_d)
590 $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
591 $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
597 $j_day_no = 365 * $jy + div($jy, 33) * 8 + div($jy % 33 + 3, 4);
598 for ($i = 0; $i < $jm; ++$i)
599 $j_day_no += $j_days_in_month[$i];
603 $g_day_no = $j_day_no + 79;
605 $gy = 1600 + 400 * div($g_day_no, 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */
609 if ($g_day_no >= 36525) /* 36525 = 365*100 + 100/4 */
612 $gy += 100 * div($g_day_no, 36524); /* 36524 = 365*100 + 100/4 - 100/100 */
615 if ($g_day_no >= 365)
621 $gy += 4 * div($g_day_no, 1461); /* 1461 = 365*4 + 4/4 */
624 if ($g_day_no >= 366)
629 $gy += div($g_day_no, 365);
633 for ($i = 0; $g_day_no >= $g_days_in_month[$i] + ($i == 1 && $leap); $i++)
634 $g_day_no -= $g_days_in_month[$i] + ($i == 1 && $leap);
638 return array($gy, $gm, $gd);
640 /* Based on Hidri Date Script
641 Released under GNU General Public License */
642 function gregorian_to_islamic($g_y, $g_m, $g_d)
647 if (($y > 1582) || (($y == 1582) && ($m > 10)) || (($y == 1582) &&
648 ($m == 10) && ($d > 14)))
650 $jd = (int)((1461 * ($y + 4800 + (int)(($m - 14) / 12)))/ 4) +
651 (int)((367 * ($m - 2 - 12 * ((int)(($m - 14) / 12)))) / 12) -
652 (int)((3 * ((int)(($y + 4900 + (int)(($m - 14) / 12)) / 100))) / 4) + $d - 32075;
656 $jd = 367 * $y - (int)((7 * ($y + 5001 + (int)(($m - 9) / 7))) / 4) +
657 (int)((275 * $m) / 9) + $d + 1729777;
659 $l = $jd - 1948440 + 10632;
660 $n = (int)(($l - 1) / 10631);
661 $l = $l - 10631 * $n + 354;
662 $j = ((int)((10985 - $l) / 5316)) * ((int)((50 * $l) / 17719)) +
663 ((int)($l / 5670)) * ((int)((43 * $l) / 15238));
664 $l = $l - ((int)((30 - $j) / 15)) * ((int)((17719 * $j) / 50)) -
665 ((int)($j / 16)) * ((int)((15238 * $j) / 43)) + 29;
666 $m = (int)((24 * $l) / 709);
667 $d = $l - (int)((709 * $m) / 24);
668 $y = 30 * $n + $j - 30;
669 return array($y, $m, $d);
672 function islamic_to_gregorian($i_y, $i_m, $i_d)
678 $jd = (int)((11 * $y + 3) / 30) + 354 * $y + 30 * $m - (int)(($m - 1) / 2) + $d + 1948440 - 385;
682 $n = (int)((4 * $l) / 146097);
683 $l = $l - (int)((146097 * $n + 3) / 4);
684 $i = (int)((4000 * ($l + 1)) / 1461001);
685 $l = $l - (int)((1461 * $i) / 4) + 31;
686 $j = (int)((80 * $l) / 2447);
687 $d = $l - (int)((2447 * $j) / 80);
689 $m = $j + 2 - 12 * $l;
690 $y = 100 * ($n - 49) + $i + $l;
695 $k = (int)(($j - 1) / 1461);
697 $n = (int)(($l - 1) / 365) - (int)($l / 1461);
698 $i = $l - 365 * $n + 30;
699 $j = (int)((80 * $i) / 2447);
700 $d = $i - (int)((2447 * $j) / 80);
702 $m = $j + 2 - 12 * $i;
703 $y = 4 * $k + $n + $i - 4716;
705 return array($y, $m, $d);