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