8fc1447a4c74cba52bed6e8ba8f81071569b43e4
[fa-stable.git] / includes / date_functions.inc
1 <?php
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 ***********************************************************************/
12 /*
13 date validation and parsing functions
14
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.
19
20 */
21 if(function_exists("date_default_timezone_set") && function_exists("date_default_timezone_get"))
22         @date_default_timezone_set(@date_default_timezone_get());
23
24 function __date($year, $month, $day)
25 {
26         global $dateseps;
27         
28         $how = user_date_format();
29         $sep = $dateseps[user_date_sep()];
30         $day = (int)$day;
31         $month = (int)$month;
32         if ($day < 10)
33                 $day = "0".$day;
34         if ($month < 10)
35                 $month = "0".$month;
36         if ($how == 0)
37                 return $month.$sep.$day.$sep.$year;
38         else if ($how == 1)
39                 return $day.$sep.$month.$sep.$year;
40         else
41                 return $year.$sep.$month.$sep.$day;
42 }
43
44 function is_date($date_) 
45 {
46         global $dateseps;
47
48         if ($date_ == null || $date_ == "")
49                 return 0;
50         $how = user_date_format();
51         $sep = $dateseps[user_date_sep()];
52
53         $date_ = trim($date_);
54         $date_ = str_replace($sep, "", $date_);
55         if (strlen($date_) == 6)
56         {
57                 if ($how == 0)
58                 {
59                         $day = substr($date_,2,2);
60                         $month = substr($date_,0,2);
61                         $year = substr($date_,4,2);
62                 } 
63                 elseif ($how == 1)
64                 {
65                         $day = substr($date_,0,2);
66                         $month = substr($date_,2,2);
67                         $year = substr($date_,4,2);
68                 } 
69                 else
70                 {
71                         $day = substr($date_,4,2);
72                         $month = substr($date_,2,2);
73                         $year = substr($date_,0,2);
74                 }
75         }
76         elseif (strlen($date_) == 8)
77         {
78                 if ($how == 0)
79                 {
80                         $day = substr($date_,2,2);
81                         $month = substr($date_,0,2);
82                         $year = substr($date_,4,4);
83                 } 
84                 elseif ($how == 1)
85                 {
86                         $day = substr($date_,0,2);
87                         $month = substr($date_,2,2);
88                         $year = substr($date_,4,4);
89                 } 
90                 else
91                 {
92                         $day = substr($date_,6,2);
93                         $month = substr($date_,4,2);
94                         $year = substr($date_,0,4);
95                 }
96         }
97         if (!isset($year)|| (int)$year > 9999) 
98         {
99                 return 0;
100         }
101
102
103         if (is_long((int)$day) && is_long((int)$month) && is_long((int)$year))
104         {
105                 global $date_system;
106                 if ($date_system == 1)
107                         list($year, $month, $day) = jalali_to_gregorian($year, $month, $day);  
108                 else if ($date_system == 2)     
109                         list($year, $month, $day) = islamic_to_gregorian($year, $month, $day);  
110                 if (checkdate((int)$month, (int)$day, (int)$year))
111                 {
112                         return 1;
113                 }
114                 else
115                 {
116                         return 0;
117                 }
118         }
119         else
120         { /*Can't be in an appropriate DefaultDateFormat */
121                 return 0;
122         }
123 } //end of is_date function
124
125 function Today() 
126 {
127         global $date_system;
128
129         $year = date("Y");
130         $month = date("n");
131         $day = date("j");
132         if ($date_system == 1)
133                 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
134         else if ($date_system == 2)     
135                 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
136         return __date($year, $month, $day);     
137 }
138
139 function Now() 
140 {
141         if (user_date_format() == 0)
142                 return date("h:i a");
143         else
144                 return date("H:i");
145 }
146 //
147 //      Retrieve and optionaly set default date for new document.
148 //
149 function new_doc_date($date=null)
150 {
151         if (isset($date) && $date != '')
152                 $_SESSION['_default_date'] = $date;
153
154         if (!isset($_SESSION['_default_date']) || !sticky_doc_date())
155                 $_SESSION['_default_date'] = Today();
156
157         return $_SESSION['_default_date'];
158 }
159
160 function is_date_in_fiscalyear($date, $convert=false)
161 {
162         global $path_to_root;
163         include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
164
165         $myrow = get_current_fiscalyear();
166         if ($myrow['closed'] == 1)
167                 return 0;
168         if ($convert)
169                 $date2 = sql2date($date);
170         else
171                 $date2 = $date;
172         $begin = sql2date($myrow['begin']);
173         $end = sql2date($myrow['end']);
174         if (date1_greater_date2($begin, $date2) || date1_greater_date2($date2, $end))
175         {
176                 return 0;
177         }
178         return 1;
179 }
180
181 function begin_fiscalyear()
182 {
183         global $path_to_root;
184         include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
185
186         $myrow = get_current_fiscalyear();
187         return sql2date($myrow['begin']);
188 }
189
190 function end_fiscalyear()
191 {
192         global $path_to_root;
193         include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
194
195         $myrow = get_current_fiscalyear();
196         return sql2date($myrow['end']);
197 }
198
199 function begin_month($date)
200 {
201         global $date_system;
202     list($day, $month, $year) = explode_date_to_dmy($date);
203     if ($date_system == 1)
204         list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
205     else if ($date_system == 2) 
206         list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
207         return __date($year, $month, 1);
208 }
209
210 function end_month($date)
211 {
212         global $date_system;
213     list($day, $month, $year) = explode_date_to_dmy($date);
214         if ($date_system == 1)
215         {
216                 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
217                 $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));
218         }
219         else if ($date_system == 2)
220         {
221                 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
222                 $days_in_month = array(30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, (((((11 * $year) + 14) % 30) < 11) ? 30 : 29));
223         }
224         else // gregorian date
225                 $days_in_month = array(31, ((!($year % 4 ) && (($year % 100) || !($year % 400)))?29:28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
226         return __date($year, $month, $days_in_month[$month - 1]);
227 }
228
229 function add_days($date, $days) // accepts negative values as well
230 {
231         global $date_system;
232     list($day, $month, $year) = explode_date_to_dmy($date);
233         $timet = Mktime(0,0,0, $month, $day + $days, $year);
234     if ($date_system == 1 || $date_system == 2)
235     {
236         if ($date_system == 1)
237                 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
238         else if ($date_system == 2)     
239                 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
240         return __date($year, $month, $day);
241     }
242     return date(user_date_display(), $timet);
243 }
244
245 function add_months($date, $months) // accepts negative values as well
246 {
247         global $date_system;
248     list($day, $month, $year) = explode_date_to_dmy($date);
249         $timet = Mktime(0,0,0, $month + $months, $day, $year);
250     if ($date_system == 1 || $date_system == 2)
251     {
252         if ($date_system == 1)
253                 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
254         else if ($date_system == 2)     
255                 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
256         return __date($year, $month, $day);
257     }
258     return date(user_date_display(), $timet);
259 }
260
261 function add_years($date, $years) // accepts negative values as well
262 {
263         global $date_system;
264     list($day, $month, $year) = explode_date_to_dmy($date);
265         $timet = Mktime(0,0,0, $month, $day, $year + $years);
266     if ($date_system == 1 || $date_system == 2)
267     {
268         if ($date_system == 1)
269                 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
270         else if ($date_system == 2)     
271                 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
272         return __date($year, $month, $day);
273     }
274     return date(user_date_display(), $timet);
275 }
276
277 //_______________________________________________________________
278
279 function sql2date($date_) 
280 {
281         global $date_system;
282
283         //for MySQL dates are in the format YYYY-mm-dd
284         if ($date_ == null || strlen($date_) == 0)
285                 return "";
286
287         if (strpos($date_, "/")) 
288         { // In MySQL it could be either / or -
289                 list($year, $month, $day) = explode("/", $date_);
290         } 
291         elseif (strpos ($date_, "-")) 
292         {
293                 list($year, $month, $day) = explode("-", $date_);
294         }
295
296         if (strlen($day) > 4) 
297         {  /*chop off the time stuff */
298                 $day = substr($day, 0, 2);
299         }
300         if ($date_system == 1)
301                 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
302         else if ($date_system == 2)
303                 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
304         return __date($year, $month, $day);     
305 } // end function sql2date
306
307
308 function date2sql($date_)
309 {
310         global $dateseps, $date_system;
311 /* takes a date in a the format specified in $DefaultDateFormat
312 and converts to a yyyy/mm/dd format */
313
314         $how = user_date_format();
315         $sep = $dateseps[user_date_sep()];
316
317         if ($date_ == null || strlen($date_) == 0)
318                 return "";
319
320         $date_ = trim($date_);
321     $year = $month = $day = 0;
322
323     // Split up the date by the separator based on "how" to split it
324     if ($how == 0) // MMDDYYYY
325         list($month, $day, $year) = explode($sep, $date_);
326     elseif ($how == 1) // DDMMYYYY
327         list($day, $month, $year) = explode($sep, $date_);
328     else // $how == 2, YYYYMMDD
329         list($year, $month, $day) = explode($sep, $date_);
330
331 //to modify assumption in 2030
332         if ($date_system == 0 || $date_system == 3)
333         {
334                 if ((int)$year < 60)
335                 {
336                         $year = "20".$year;
337                 } 
338                 elseif ((int)$year > 59 && (int)$year < 100)
339                 {
340                         $year = "19".$year;
341                 }
342         }       
343         if ((int)$year > 9999)
344         {
345                 return 0;
346         }
347         if ($date_system == 1)
348                 list($year, $month, $day) = jalali_to_gregorian($year, $month, $day); 
349         else if ($date_system == 2)
350                 list($year, $month, $day) = islamic_to_gregorian($year, $month, $day); 
351
352         // Pad with 0s if needed
353         if (strlen($month) == 1)
354                 $month = "0$month";
355         if (strlen($day) == 1)
356                 $day = "0$day";
357
358         return $year."-".$month."-".$day;
359 }// end of function
360
361 function date1_greater_date2 ($date1, $date2) 
362 {
363
364 /* returns 1 true if date1 is greater than date_ 2 */
365
366         $date1 = date2sql($date1);
367         $date2 = date2sql($date2);
368
369         @list($year1, $month1, $day1) = explode("-", $date1);
370         @list($year2, $month2, $day2) = explode("-", $date2);
371
372         if ($year1 > $year2)
373         {
374                 return 1;
375         }
376         elseif ($year1 == $year2)
377         {
378                 if ($month1 > $month2)
379                 {
380                         return 1;
381                 }
382                 elseif ($month1 == $month2)
383                 {
384                         if ($day1 > $day2)
385                         {
386                                 return 1;
387                         }
388                 }
389         }
390         return 0;
391 }
392
393
394 function date_diff2 ($date1, $date2, $period) 
395 {
396
397 /* expects dates in the format specified in $DefaultDateFormat - period can be one of 'd','w','y','m'
398 months are assumed to be 30 days and years 365.25 days This only works
399 provided that both dates are after 1970. Also only works for dates up to the year 2035 ish */
400
401         $date1 = date2sql($date1);
402         $date2 = date2sql($date2);
403         list($year1, $month1, $day1) = explode("-", $date1);
404         list($year2, $month2, $day2) = explode("-", $date2);
405
406         $stamp1 = mktime(0,0,0, (int)$month1, (int)$day1, (int)$year1);
407         $stamp2 = mktime(0,0,0, (int)$month2, (int)$day2, (int)$year2);
408         $difference = $stamp1 - $stamp2;
409
410 /* difference is the number of seconds between each date negative if date_ 2 > date_ 1 */
411
412         switch ($period) 
413         {
414                 case "d":
415                         return (int)($difference / (24 * 60 * 60));
416                 case "w":
417                         return (int)($difference / (24 * 60 * 60 * 7));
418                 case "m":
419                         return (int)($difference / (24 * 60 * 60 * 30));
420                 case "s":
421                         return $difference;
422                 case "y":
423                         return (int)($difference / (24 * 60 * 60 * 365.25));
424                 default:
425                         Return 0;
426         }
427 }
428
429 function explode_date_to_dmy($date_)
430 {
431         $date = date2sql($date_);
432         if ($date == "") 
433         {
434                 return array(0,0,0);
435         }
436         list($year, $month, $day) = explode("-", $date);
437         return array($day, $month, $year);
438 }
439
440 function div($a, $b) 
441 {
442     return (int) ($a / $b);
443 }
444 /* Based on convertor to and from Gregorian and Jalali calendars.
445    Copyright (C) 2000  Roozbeh Pournader and Mohammad Toossi 
446    Released under GNU General Public License */
447
448 function gregorian_to_jalali ($g_y, $g_m, $g_d)
449 {
450     $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
451     $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
452
453         $gy = $g_y - 1600;
454         $gm = $g_m - 1;
455         $gd = $g_d - 1;
456
457         $g_day_no = 365 * $gy + div($gy + 3, 4) - div($gy + 99, 100) + div($gy + 399, 400);
458
459         for ($i = 0; $i < $gm; ++$i)
460         $g_day_no += $g_days_in_month[$i];
461         if ($gm > 1 && (($gy % 4 == 0 && $gy % 100 != 0) || ($gy % 400 == 0)))
462         /* leap and after Feb */
463         $g_day_no++;
464         $g_day_no += $gd;
465         $j_day_no = $g_day_no - 79;
466
467         $j_np = div($j_day_no, 12053); /* 12053 = 365*33 + 32/4 */
468         $j_day_no %= 12053;
469
470         $jy = 979 + 33 * $j_np + 4 * div($j_day_no, 1461); /* 1461 = 365*4 + 4/4 */
471
472         $j_day_no %= 1461;
473
474         if ($j_day_no >= 366) 
475         {
476         $jy += div($j_day_no - 1, 365);
477         $j_day_no = ($j_day_no - 1) % 365;
478         }
479
480         for ($i = 0; $i < 11 && $j_day_no >= $j_days_in_month[$i]; ++$i)
481         $j_day_no -= $j_days_in_month[$i];
482         $jm = $i + 1;
483         $jd = $j_day_no + 1;
484
485         return array($jy, $jm, $jd);
486 }
487
488 function jalali_to_gregorian($j_y, $j_m, $j_d)
489 {
490     $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
491     $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
492
493         $jy = $j_y - 979;
494         $jm = $j_m - 1;
495         $jd = $j_d - 1;
496
497         $j_day_no = 365 * $jy + div($jy, 33) * 8 + div($jy % 33 + 3, 4);
498         for ($i = 0; $i < $jm; ++$i)
499         $j_day_no += $j_days_in_month[$i];
500
501         $j_day_no += $jd;
502
503         $g_day_no = $j_day_no + 79;
504
505         $gy = 1600 + 400 * div($g_day_no, 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */
506         $g_day_no %= 146097;
507
508         $leap = true;
509         if ($g_day_no >= 36525) /* 36525 = 365*100 + 100/4 */
510         {
511         $g_day_no--;
512         $gy += 100 * div($g_day_no,  36524); /* 36524 = 365*100 + 100/4 - 100/100 */
513         $g_day_no %= 36524;
514
515         if ($g_day_no >= 365)
516                 $g_day_no++;
517         else
518                 $leap = false;
519         }
520
521         $gy += 4 * div($g_day_no, 1461); /* 1461 = 365*4 + 4/4 */
522         $g_day_no %= 1461;
523
524         if ($g_day_no >= 366) 
525         {
526         $leap = false;
527
528         $g_day_no--;
529         $gy += div($g_day_no, 365);
530         $g_day_no %= 365;
531         }
532
533         for ($i = 0; $g_day_no >= $g_days_in_month[$i] + ($i == 1 && $leap); $i++)
534         $g_day_no -= $g_days_in_month[$i] + ($i == 1 && $leap);
535         $gm = $i + 1;
536         $gd = $g_day_no + 1;
537
538         return array($gy, $gm, $gd);
539 }
540 /* Based on Hidri Date Script 
541    Released under GNU General Public License */
542 function gregorian_to_islamic($g_y, $g_m, $g_d)
543 {
544         $y = $g_y;   
545         $m = $g_m;
546         $d = $g_d;
547         if (($y > 1582) || (($y == 1582) && ($m > 10)) || (($y == 1582) && 
548                 ($m == 10) && ($d > 14))) 
549         {
550                 $jd = (int)((1461 * ($y + 4800 + (int)(($m - 14) / 12)))/ 4) + 
551                         (int)((367 * ($m - 2 - 12 * ((int)(($m - 14) / 12)))) / 12) - 
552                         (int)((3 * ((int)(($y + 4900 + (int)(($m - 14) / 12)) / 100))) / 4) + $d - 32075;
553         } 
554         else 
555         {
556                 $jd = 367 * $y - (int)((7 * ($y + 5001 + (int)(($m - 9) / 7))) / 4) + 
557                         (int)((275 * $m) / 9) + $d + 1729777;
558         }
559         $l = $jd - 1948440 + 10632;
560         $n = (int)(($l - 1) / 10631);
561         $l = $l - 10631 * $n + 354;
562         $j = ((int)((10985 - $l) / 5316)) * ((int)((50 * $l) / 17719)) + 
563                 ((int)($l / 5670)) * ((int)((43 * $l) / 15238));
564         $l = $l - ((int)((30 - $j) / 15)) * ((int)((17719 * $j) / 50)) - 
565                 ((int)($j / 16)) * ((int)((15238 * $j) / 43)) + 29;
566         $m = (int)((24 * $l) / 709);
567         $d = $l - (int)((709 * $m) / 24);
568         $y = 30 * $n + $j - 30;
569         return array($y, $m, $d);
570 }
571
572 function islamic_to_gregorian($i_y, $i_m, $i_d)
573 {
574         $y = $i_y;   
575         $m = $i_m;
576         $d = $i_d;
577
578         $jd = (int)((11 * $y + 3) / 30) + 354 * $y + 30 * $m - (int)(($m - 1) / 2) + $d + 1948440 - 385;
579         if ($jd > 2299160)
580         {
581                 $l = $jd + 68569;
582                 $n = (int)((4 * $l) / 146097);
583                 $l = $l - (int)((146097 * $n + 3) / 4);
584                 $i = (int)((4000 * ($l + 1)) / 1461001);
585                 $l = $l - (int)((1461 * $i) / 4) + 31;
586                 $j = (int)((80 * $l) / 2447);
587                 $d = $l - (int)((2447 * $j) / 80);
588                 $l= (int)($j / 11);
589                 $m = $j + 2 - 12 * $l;
590                 $y = 100 * ($n - 49) + $i + $l;
591         } 
592         else 
593         {
594                 $j = $jd + 1402;
595                 $k = (int)(($j - 1) / 1461);
596                 $l = $j - 1461 * $k;
597                 $n = (int)(($l - 1) / 365) - (int)($l / 1461);
598                 $i = $l - 365 * $n + 30;
599                 $j = (int)((80 * $i) / 2447);
600                 $d = $i - (int)((2447 * $j) / 80);
601                 $i = (int)($j / 11);
602                 $m = $j + 2 - 12 * $i;
603                 $y = 4 * $k + $n + $i - 4716;
604         }
605         return array($y, $m, $d);
606 }
607 ?>