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