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