94525a3307fcc3195c3d1e37d72a6c285636f758
[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     //Chaitanya
164     if ($convert)
165         $date2 = sql2date($date);
166     else
167         $date2 = $date;
168
169     if ($_SESSION["wa_current_user"]->can_access('SA_MULTIFISCALYEARS')) // allow all open years for this one
170         return is_date_in_fiscalyears($date2, false); 
171
172     $myrow = get_current_fiscalyear();
173     if ($myrow['closed'] == 1)
174         return 0;
175     
176     $begin = sql2date($myrow['begin']);
177     $end = sql2date($myrow['end']);
178     if (date1_greater_date2($begin, $date2) || date1_greater_date2($date2, $end))
179     {
180         return 0;
181     }
182     return 1;
183 }
184
185 function begin_fiscalyear()
186 {
187         global $path_to_root;
188         include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
189
190         $myrow = get_current_fiscalyear();
191         return sql2date($myrow['begin']);
192 }
193
194 function end_fiscalyear()
195 {
196         global $path_to_root;
197         include_once($path_to_root . "/admin/db/fiscalyears_db.inc");
198
199         $myrow = get_current_fiscalyear();
200         return sql2date($myrow['end']);
201 }
202
203 function begin_month($date)
204 {
205         global $date_system;
206     list($day, $month, $year) = explode_date_to_dmy($date);
207     if ($date_system == 1)
208         list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
209     elseif ($date_system == 2)  
210         list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
211         return __date($year, $month, 1);
212 }
213
214 function days_in_month($month, $year)
215 {
216         global $date_system;
217
218         if ($date_system == 1)
219         {
220                 $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));
221         }
222         elseif ($date_system == 2)
223         {
224                 $days_in_month = array(30, 29, 30, 29, 30, 29, 30, 29, 30, 29, 30, (((((11 * $year) + 14) % 30) < 11) ? 30 : 29));
225         }
226         else // gregorian date
227                 $days_in_month = array(31, ((!($year % 4 ) && (($year % 100) || !($year % 400)))?29:28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
228
229         return $days_in_month[$month - 1];
230 }
231
232 function end_month($date)
233 {
234         global $date_system;
235
236     list($day, $month, $year) = explode_date_to_dmy($date);
237         if ($date_system == 1)
238         {
239                 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
240         }
241         elseif ($date_system == 2)
242         {
243                 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
244         }
245
246         return __date($year, $month, days_in_month($month, $year));
247 }
248
249 function add_days($date, $days) // accepts negative values as well
250 {
251         global $date_system;
252     list($day, $month, $year) = explode_date_to_dmy($date);
253         $timet = mktime(0,0,0, $month, $day + $days, $year);
254     if ($date_system == 1 || $date_system == 2)
255     {
256         if ($date_system == 1)
257                 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
258         elseif ($date_system == 2)      
259                 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
260         return __date($year, $month, $day);
261     }
262     return date(user_date_display(), $timet);
263 }
264
265 function add_months($date, $months) // accepts negative values as well
266 {
267         global $date_system;
268     list($day, $month, $year) = explode_date_to_dmy($date);
269         $months += $year*12+$month;
270         $month = ($months-1)%12+1;
271         $year = ($months-$month)/12;
272         if ($month < 0)
273                 $month += 12;
274
275         $timet = mktime(0,0,0, $month, min($day, days_in_month($month, $year)), $year);
276
277     if ($date_system == 1 || $date_system == 2)
278     {
279         if ($date_system == 1)
280                 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
281         elseif ($date_system == 2)      
282                 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
283         return __date($year, $month, $day);
284     }
285     return date(user_date_display(), $timet);
286 }
287
288 function add_years($date, $years) // accepts negative values as well
289 {
290         global $date_system;
291     list($day, $month, $year) = explode_date_to_dmy($date);
292         $timet = Mktime(0,0,0, $month, $day, $year + $years);
293     if ($date_system == 1 || $date_system == 2)
294     {
295         if ($date_system == 1)
296                 list($year, $month, $day) = gregorian_to_jalali(date("Y", $timet), date("n", $timet), date("j", $timet));
297         elseif ($date_system == 2)      
298                 list($year, $month, $day) = gregorian_to_islamic(date("Y", $timet), date("n", $timet), date("j", $timet));
299         return __date($year, $month, $day);
300     }
301     return date(user_date_display(), $timet);
302 }
303
304 //_______________________________________________________________
305
306 function sql2date($date_) 
307 {
308         global $date_system;
309
310         //for MySQL dates are in the format YYYY-mm-dd
311         if ($date_ == null || strlen($date_) == 0)
312                 return "";
313
314         if (strpos($date_, "/")) 
315         { // In MySQL it could be either / or -
316                 list($year, $month, $day) = explode("/", $date_);
317         } 
318         elseif (strpos ($date_, "-")) 
319         {
320                 list($year, $month, $day) = explode("-", $date_);
321         }
322
323         if (strlen($day) > 4) 
324         {  /*chop off the time stuff */
325                 $day = substr($day, 0, 2);
326         }
327         if ($date_system == 1)
328                 list($year, $month, $day) = gregorian_to_jalali($year, $month, $day);
329         elseif ($date_system == 2)
330                 list($year, $month, $day) = gregorian_to_islamic($year, $month, $day);
331         return __date($year, $month, $day);     
332 } // end function sql2date
333
334
335 function date2sql($date_)
336 {
337         global $dateseps, $date_system;
338 /* takes a date in a the format specified in $DefaultDateFormat
339 and converts to a yyyy/mm/dd format */
340
341         $how = user_date_format();
342         $sep = $dateseps[user_date_sep()];
343
344         if ($date_ == null || strlen($date_) == 0)
345                 return "";
346
347         $date_ = trim($date_);
348     $year = $month = $day = 0;
349
350     // Split up the date by the separator based on "how" to split it
351     if ($how == 0) // MMDDYYYY
352         list($month, $day, $year) = explode($sep, $date_);
353     elseif ($how == 1) // DDMMYYYY
354         list($day, $month, $year) = explode($sep, $date_);
355     else // $how == 2, YYYYMMDD
356         list($year, $month, $day) = explode($sep, $date_);
357
358 //to modify assumption in 2030
359         if ($date_system == 0 || $date_system == 3)
360         {
361                 if ((int)$year < 60)
362                 {
363                         $year = "20".$year;
364                 } 
365                 elseif ((int)$year > 59 && (int)$year < 100)
366                 {
367                         $year = "19".$year;
368                 }
369         }       
370         if ((int)$year > 9999)
371         {
372                 return 0;
373         }
374         if ($date_system == 1)
375                 list($year, $month, $day) = jalali_to_gregorian($year, $month, $day); 
376         elseif ($date_system == 2)
377                 list($year, $month, $day) = islamic_to_gregorian($year, $month, $day); 
378
379         return sprintf("%04d-%02d-%02d", $year, $month, $day);
380 }// end of function
381
382 function date1_greater_date2 ($date1, $date2) 
383 {
384
385 /* returns 1 true if date1 is greater than date_ 2 */
386
387         $date1 = date2sql($date1);
388         $date2 = date2sql($date2);
389
390         @list($year1, $month1, $day1) = explode("-", $date1);
391         @list($year2, $month2, $day2) = explode("-", $date2);
392
393         if ($year1 > $year2)
394         {
395                 return 1;
396         }
397         elseif ($year1 == $year2)
398         {
399                 if ($month1 > $month2)
400                 {
401                         return 1;
402                 }
403                 elseif ($month1 == $month2)
404                 {
405                         if ($day1 > $day2)
406                         {
407                                 return 1;
408                         }
409                 }
410         }
411         return 0;
412 }
413
414
415 function date_diff2 ($date1, $date2, $period) 
416 {
417
418 /* expects dates in the format specified in $DefaultDateFormat - period can be one of 'd','w','y','m'
419 months are assumed to be 30 days and years 365.25 days This only works
420 provided that both dates are after 1970. Also only works for dates up to the year 2035 ish */
421
422         $date1 = date2sql($date1);
423         $date2 = date2sql($date2);
424         list($year1, $month1, $day1) = explode("-", $date1);
425         list($year2, $month2, $day2) = explode("-", $date2);
426
427         $stamp1 = mktime(0,0,0, (int)$month1, (int)$day1, (int)$year1);
428         $stamp2 = mktime(0,0,0, (int)$month2, (int)$day2, (int)$year2);
429         $difference = $stamp1 - $stamp2;
430
431 /* difference is the number of seconds between each date negative if date_ 2 > date_ 1 */
432
433         switch ($period) 
434         {
435                 case "d":
436                         return (int)($difference / (24 * 60 * 60));
437                 case "w":
438                         return (int)($difference / (24 * 60 * 60 * 7));
439                 case "m":
440                         return (int)($difference / (24 * 60 * 60 * 30));
441                 case "s":
442                         return $difference;
443                 case "y":
444                         return (int)($difference / (24 * 60 * 60 * 365.25));
445                 default:
446                         Return 0;
447         }
448 }
449
450 function explode_date_to_dmy($date_)
451 {
452         $date = date2sql($date_);
453         if ($date == "") 
454         {
455                 return array(0,0,0);
456         }
457         list($year, $month, $day) = explode("-", $date);
458         return array($day, $month, $year);
459 }
460
461 function div($a, $b) 
462 {
463     return (int) ($a / $b);
464 }
465 /* Based on convertor to and from Gregorian and Jalali calendars.
466    Copyright (C) 2000  Roozbeh Pournader and Mohammad Toossi 
467    Released under GNU General Public License */
468
469 function gregorian_to_jalali ($g_y, $g_m, $g_d)
470 {
471     $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
472     $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
473
474         $gy = $g_y - 1600;
475         $gm = $g_m - 1;
476         $gd = $g_d - 1;
477
478         $g_day_no = 365 * $gy + div($gy + 3, 4) - div($gy + 99, 100) + div($gy + 399, 400);
479
480         for ($i = 0; $i < $gm; ++$i)
481         $g_day_no += $g_days_in_month[$i];
482         if ($gm > 1 && (($gy % 4 == 0 && $gy % 100 != 0) || ($gy % 400 == 0)))
483         /* leap and after Feb */
484         $g_day_no++;
485         $g_day_no += $gd;
486         $j_day_no = $g_day_no - 79;
487
488         $j_np = div($j_day_no, 12053); /* 12053 = 365*33 + 32/4 */
489         $j_day_no %= 12053;
490
491         $jy = 979 + 33 * $j_np + 4 * div($j_day_no, 1461); /* 1461 = 365*4 + 4/4 */
492
493         $j_day_no %= 1461;
494
495         if ($j_day_no >= 366) 
496         {
497         $jy += div($j_day_no - 1, 365);
498         $j_day_no = ($j_day_no - 1) % 365;
499         }
500
501         for ($i = 0; $i < 11 && $j_day_no >= $j_days_in_month[$i]; ++$i)
502         $j_day_no -= $j_days_in_month[$i];
503         $jm = $i + 1;
504         $jd = $j_day_no + 1;
505
506         return array($jy, $jm, $jd);
507 }
508
509 function jalali_to_gregorian($j_y, $j_m, $j_d)
510 {
511     $g_days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
512     $j_days_in_month = array(31, 31, 31, 31, 31, 31, 30, 30, 30, 30, 30, 29);
513
514         $jy = $j_y - 979;
515         $jm = $j_m - 1;
516         $jd = $j_d - 1;
517
518         $j_day_no = 365 * $jy + div($jy, 33) * 8 + div($jy % 33 + 3, 4);
519         for ($i = 0; $i < $jm; ++$i)
520         $j_day_no += $j_days_in_month[$i];
521
522         $j_day_no += $jd;
523
524         $g_day_no = $j_day_no + 79;
525
526         $gy = 1600 + 400 * div($g_day_no, 146097); /* 146097 = 365*400 + 400/4 - 400/100 + 400/400 */
527         $g_day_no %= 146097;
528
529         $leap = true;
530         if ($g_day_no >= 36525) /* 36525 = 365*100 + 100/4 */
531         {
532         $g_day_no--;
533         $gy += 100 * div($g_day_no,  36524); /* 36524 = 365*100 + 100/4 - 100/100 */
534         $g_day_no %= 36524;
535
536         if ($g_day_no >= 365)
537                 $g_day_no++;
538         else
539                 $leap = false;
540         }
541
542         $gy += 4 * div($g_day_no, 1461); /* 1461 = 365*4 + 4/4 */
543         $g_day_no %= 1461;
544
545         if ($g_day_no >= 366) 
546         {
547         $leap = false;
548
549         $g_day_no--;
550         $gy += div($g_day_no, 365);
551         $g_day_no %= 365;
552         }
553
554         for ($i = 0; $g_day_no >= $g_days_in_month[$i] + ($i == 1 && $leap); $i++)
555         $g_day_no -= $g_days_in_month[$i] + ($i == 1 && $leap);
556         $gm = $i + 1;
557         $gd = $g_day_no + 1;
558
559         return array($gy, $gm, $gd);
560 }
561 /* Based on Hidri Date Script 
562    Released under GNU General Public License */
563 function gregorian_to_islamic($g_y, $g_m, $g_d)
564 {
565         $y = $g_y;   
566         $m = $g_m;
567         $d = $g_d;
568         if (($y > 1582) || (($y == 1582) && ($m > 10)) || (($y == 1582) && 
569                 ($m == 10) && ($d > 14))) 
570         {
571                 $jd = (int)((1461 * ($y + 4800 + (int)(($m - 14) / 12)))/ 4) + 
572                         (int)((367 * ($m - 2 - 12 * ((int)(($m - 14) / 12)))) / 12) - 
573                         (int)((3 * ((int)(($y + 4900 + (int)(($m - 14) / 12)) / 100))) / 4) + $d - 32075;
574         } 
575         else 
576         {
577                 $jd = 367 * $y - (int)((7 * ($y + 5001 + (int)(($m - 9) / 7))) / 4) + 
578                         (int)((275 * $m) / 9) + $d + 1729777;
579         }
580         $l = $jd - 1948440 + 10632;
581         $n = (int)(($l - 1) / 10631);
582         $l = $l - 10631 * $n + 354;
583         $j = ((int)((10985 - $l) / 5316)) * ((int)((50 * $l) / 17719)) + 
584                 ((int)($l / 5670)) * ((int)((43 * $l) / 15238));
585         $l = $l - ((int)((30 - $j) / 15)) * ((int)((17719 * $j) / 50)) - 
586                 ((int)($j / 16)) * ((int)((15238 * $j) / 43)) + 29;
587         $m = (int)((24 * $l) / 709);
588         $d = $l - (int)((709 * $m) / 24);
589         $y = 30 * $n + $j - 30;
590         return array($y, $m, $d);
591 }
592
593 function islamic_to_gregorian($i_y, $i_m, $i_d)
594 {
595         $y = $i_y;   
596         $m = $i_m;
597         $d = $i_d;
598
599         $jd = (int)((11 * $y + 3) / 30) + 354 * $y + 30 * $m - (int)(($m - 1) / 2) + $d + 1948440 - 385;
600         if ($jd > 2299160)
601         {
602                 $l = $jd + 68569;
603                 $n = (int)((4 * $l) / 146097);
604                 $l = $l - (int)((146097 * $n + 3) / 4);
605                 $i = (int)((4000 * ($l + 1)) / 1461001);
606                 $l = $l - (int)((1461 * $i) / 4) + 31;
607                 $j = (int)((80 * $l) / 2447);
608                 $d = $l - (int)((2447 * $j) / 80);
609                 $l= (int)($j / 11);
610                 $m = $j + 2 - 12 * $l;
611                 $y = 100 * ($n - 49) + $i + $l;
612         } 
613         else 
614         {
615                 $j = $jd + 1402;
616                 $k = (int)(($j - 1) / 1461);
617                 $l = $j - 1461 * $k;
618                 $n = (int)(($l - 1) / 365) - (int)($l / 1461);
619                 $i = $l - 365 * $n + 30;
620                 $j = (int)((80 * $i) / 2447);
621                 $d = $i - (int)((2447 * $j) / 80);
622                 $i = (int)($j / 11);
623                 $m = $j + 2 - 12 * $i;
624                 $y = 4 * $k + $n + $i - 4716;
625         }
626         return array($y, $m, $d);
627 }
628 ?>