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