TYPO3 CMS  TYPO3_7-6
adodb-time.inc.php
Go to the documentation of this file.
1 <?php
2 /*
3 ADOdb Date Library, part of the ADOdb abstraction library
4 Download: http://adodb.sourceforge.net/#download
5 
6 @version v5.20.3 01-Jan-2016
7 @copyright (c) 2000-2013 John Lim (jlim#natsoft.com). All rights reserved.
8 @copyright (c) 2014 Damien Regad, Mark Newnham and the ADOdb community
9 
10 PHP native date functions use integer timestamps for computations.
11 Because of this, dates are restricted to the years 1901-2038 on Unix
12 and 1970-2038 on Windows due to integer overflow for dates beyond
13 those years. This library overcomes these limitations by replacing the
14 native function's signed integers (normally 32-bits) with PHP floating
15 point numbers (normally 64-bits).
16 
17 Dates from 100 A.D. to 3000 A.D. and later
18 have been tested. The minimum is 100 A.D. as <100 will invoke the
19 2 => 4 digit year conversion. The maximum is billions of years in the
20 future, but this is a theoretical limit as the computation of that year
21 would take too long with the current implementation of adodb_mktime().
22 
23 This library replaces native functions as follows:
24 
25 <pre>
26  getdate() with adodb_getdate()
27  date() with adodb_date()
28  gmdate() with adodb_gmdate()
29  mktime() with adodb_mktime()
30  gmmktime() with adodb_gmmktime()
31  strftime() with adodb_strftime()
32  strftime() with adodb_gmstrftime()
33 </pre>
34 
35 The parameters are identical, except that adodb_date() accepts a subset
36 of date()'s field formats. Mktime() will convert from local time to GMT,
37 and date() will convert from GMT to local time, but daylight savings is
38 not handled currently.
39 
40 This library is independant of the rest of ADOdb, and can be used
41 as standalone code.
42 
43 PERFORMANCE
44 
45 For high speed, this library uses the native date functions where
46 possible, and only switches to PHP code when the dates fall outside
47 the 32-bit signed integer range.
48 
49 GREGORIAN CORRECTION
50 
51 Pope Gregory shortened October of A.D. 1582 by ten days. Thursday,
52 October 4, 1582 (Julian) was followed immediately by Friday, October 15,
53 1582 (Gregorian).
54 
55 Since 0.06, we handle this correctly, so:
56 
57 adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582)
58  == 24 * 3600 (1 day)
59 
60 =============================================================================
61 
62 COPYRIGHT
63 
64 (c) 2003-2014 John Lim and released under BSD-style license except for code by
65 jackbbs, which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year
66 and originally found at http://www.php.net/manual/en/function.mktime.php
67 
68 =============================================================================
69 
70 BUG REPORTS
71 
72 These should be posted to the ADOdb forums at
73 
74  http://phplens.com/lens/lensforum/topics.php?id=4
75 
76 =============================================================================
77 
78 FUNCTION DESCRIPTIONS
79 
80 ** FUNCTION adodb_time()
81 
82 Returns the current time measured in the number of seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) as an unsigned integer.
83 
84 ** FUNCTION adodb_getdate($date=false)
85 
86 Returns an array containing date information, as getdate(), but supports
87 dates greater than 1901 to 2038. The local date/time format is derived from a
88 heuristic the first time adodb_getdate is called.
89 
90 
91 ** FUNCTION adodb_date($fmt, $timestamp = false)
92 
93 Convert a timestamp to a formatted local date. If $timestamp is not defined, the
94 current timestamp is used. Unlike the function date(), it supports dates
95 outside the 1901 to 2038 range.
96 
97 The format fields that adodb_date supports:
98 
99 <pre>
100  a - "am" or "pm"
101  A - "AM" or "PM"
102  d - day of the month, 2 digits with leading zeros; i.e. "01" to "31"
103  D - day of the week, textual, 3 letters; e.g. "Fri"
104  F - month, textual, long; e.g. "January"
105  g - hour, 12-hour format without leading zeros; i.e. "1" to "12"
106  G - hour, 24-hour format without leading zeros; i.e. "0" to "23"
107  h - hour, 12-hour format; i.e. "01" to "12"
108  H - hour, 24-hour format; i.e. "00" to "23"
109  i - minutes; i.e. "00" to "59"
110  j - day of the month without leading zeros; i.e. "1" to "31"
111  l (lowercase 'L') - day of the week, textual, long; e.g. "Friday"
112  L - boolean for whether it is a leap year; i.e. "0" or "1"
113  m - month; i.e. "01" to "12"
114  M - month, textual, 3 letters; e.g. "Jan"
115  n - month without leading zeros; i.e. "1" to "12"
116  O - Difference to Greenwich time in hours; e.g. "+0200"
117  Q - Quarter, as in 1, 2, 3, 4
118  r - RFC 2822 formatted date; e.g. "Thu, 21 Dec 2000 16:01:07 +0200"
119  s - seconds; i.e. "00" to "59"
120  S - English ordinal suffix for the day of the month, 2 characters;
121  i.e. "st", "nd", "rd" or "th"
122  t - number of days in the given month; i.e. "28" to "31"
123  T - Timezone setting of this machine; e.g. "EST" or "MDT"
124  U - seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
125  w - day of the week, numeric, i.e. "0" (Sunday) to "6" (Saturday)
126  Y - year, 4 digits; e.g. "1999"
127  y - year, 2 digits; e.g. "99"
128  z - day of the year; i.e. "0" to "365"
129  Z - timezone offset in seconds (i.e. "-43200" to "43200").
130  The offset for timezones west of UTC is always negative,
131  and for those east of UTC is always positive.
132 </pre>
133 
134 Unsupported:
135 <pre>
136  B - Swatch Internet time
137  I (capital i) - "1" if Daylight Savings Time, "0" otherwise.
138  W - ISO-8601 week number of year, weeks starting on Monday
139 
140 </pre>
141 
142 
143 ** FUNCTION adodb_date2($fmt, $isoDateString = false)
144 Same as adodb_date, but 2nd parameter accepts iso date, eg.
145 
146  adodb_date2('d-M-Y H:i','2003-12-25 13:01:34');
147 
148 
149 ** FUNCTION adodb_gmdate($fmt, $timestamp = false)
150 
151 Convert a timestamp to a formatted GMT date. If $timestamp is not defined, the
152 current timestamp is used. Unlike the function date(), it supports dates
153 outside the 1901 to 2038 range.
154 
155 
156 ** FUNCTION adodb_mktime($hr, $min, $sec[, $month, $day, $year])
157 
158 Converts a local date to a unix timestamp. Unlike the function mktime(), it supports
159 dates outside the 1901 to 2038 range. All parameters are optional.
160 
161 
162 ** FUNCTION adodb_gmmktime($hr, $min, $sec [, $month, $day, $year])
163 
164 Converts a gmt date to a unix timestamp. Unlike the function gmmktime(), it supports
165 dates outside the 1901 to 2038 range. Differs from gmmktime() in that all parameters
166 are currently compulsory.
167 
168 ** FUNCTION adodb_gmstrftime($fmt, $timestamp = false)
169 Convert a timestamp to a formatted GMT date.
170 
171 ** FUNCTION adodb_strftime($fmt, $timestamp = false)
172 
173 Convert a timestamp to a formatted local date. Internally converts $fmt into
174 adodb_date format, then echo result.
175 
176 For best results, you can define the local date format yourself. Define a global
177 variable $ADODB_DATE_LOCALE which is an array, 1st element is date format using
178 adodb_date syntax, and 2nd element is the time format, also in adodb_date syntax.
179 
180  eg. $ADODB_DATE_LOCALE = array('d/m/Y','H:i:s');
181 
182  Supported format codes:
183 
184 <pre>
185  %a - abbreviated weekday name according to the current locale
186  %A - full weekday name according to the current locale
187  %b - abbreviated month name according to the current locale
188  %B - full month name according to the current locale
189  %c - preferred date and time representation for the current locale
190  %d - day of the month as a decimal number (range 01 to 31)
191  %D - same as %m/%d/%y
192  %e - day of the month as a decimal number, a single digit is preceded by a space (range ' 1' to '31')
193  %h - same as %b
194  %H - hour as a decimal number using a 24-hour clock (range 00 to 23)
195  %I - hour as a decimal number using a 12-hour clock (range 01 to 12)
196  %m - month as a decimal number (range 01 to 12)
197  %M - minute as a decimal number
198  %n - newline character
199  %p - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale
200  %r - time in a.m. and p.m. notation
201  %R - time in 24 hour notation
202  %S - second as a decimal number
203  %t - tab character
204  %T - current time, equal to %H:%M:%S
205  %x - preferred date representation for the current locale without the time
206  %X - preferred time representation for the current locale without the date
207  %y - year as a decimal number without a century (range 00 to 99)
208  %Y - year as a decimal number including the century
209  %Z - time zone or name or abbreviation
210  %% - a literal `%' character
211 </pre>
212 
213  Unsupported codes:
214 <pre>
215  %C - century number (the year divided by 100 and truncated to an integer, range 00 to 99)
216  %g - like %G, but without the century.
217  %G - The 4-digit year corresponding to the ISO week number (see %V).
218  This has the same format and value as %Y, except that if the ISO week number belongs
219  to the previous or next year, that year is used instead.
220  %j - day of the year as a decimal number (range 001 to 366)
221  %u - weekday as a decimal number [1,7], with 1 representing Monday
222  %U - week number of the current year as a decimal number, starting
223  with the first Sunday as the first day of the first week
224  %V - The ISO 8601:1988 week number of the current year as a decimal number,
225  range 01 to 53, where week 1 is the first week that has at least 4 days in the
226  current year, and with Monday as the first day of the week. (Use %G or %g for
227  the year component that corresponds to the week number for the specified timestamp.)
228  %w - day of the week as a decimal, Sunday being 0
229  %W - week number of the current year as a decimal number, starting with the
230  first Monday as the first day of the first week
231 </pre>
232 
233 =============================================================================
234 
235 NOTES
236 
237 Useful url for generating test timestamps:
238  http://www.4webhelp.net/us/timestamp.php
239 
240 Possible future optimizations include
241 
242 a. Using an algorithm similar to Plauger's in "The Standard C Library"
243 (page 428, xttotm.c _Ttotm() function). Plauger's algorithm will not
244 work outside 32-bit signed range, so i decided not to implement it.
245 
246 b. Implement daylight savings, which looks awfully complicated, see
247  http://webexhibits.org/daylightsaving/
248 
249 
250 CHANGELOG
251 - 16 Jan 2011 0.36
252 Added adodb_time() which returns current time. If > 2038, will return as float
253 
254 - 7 Feb 2011 0.35
255 Changed adodb_date to be symmetric with adodb_mktime. See $jan1_71. fix for bc.
256 
257 - 13 July 2010 0.34
258 Changed adodb_get_gm_diff to use DateTimeZone().
259 
260 - 11 Feb 2008 0.33
261 * Bug in 0.32 fix for hour handling. Fixed.
262 
263 - 1 Feb 2008 0.32
264 * Now adodb_mktime(0,0,0,12+$m,20,2040) works properly.
265 
266 - 10 Jan 2008 0.31
267 * Now adodb_mktime(0,0,0,24,1,2037) works correctly.
268 
269 - 15 July 2007 0.30
270 Added PHP 5.2.0 compatability fixes.
271  * gmtime behaviour for 1970 has changed. We use the actual date if it is between 1970 to 2038 to get the
272  * timezone, otherwise we use the current year as the baseline to retrieve the timezone.
273  * Also the timezone's in php 5.2.* support historical data better, eg. if timezone today was +8, but
274  in 1970 it was +7:30, then php 5.2 return +7:30, while this library will use +8.
275  *
276 
277 - 19 March 2006 0.24
278 Changed strftime() locale detection, because some locales prepend the day of week to the date when %c is used.
279 
280 - 10 Feb 2006 0.23
281 PHP5 compat: when we detect PHP5, the RFC2822 format for gmt 0000hrs is changed from -0000 to +0000.
282  In PHP4, we will still use -0000 for 100% compat with PHP4.
283 
284 - 08 Sept 2005 0.22
285 In adodb_date2(), $is_gmt not supported properly. Fixed.
286 
287 - 18 July 2005 0.21
288 In PHP 4.3.11, the 'r' format has changed. Leading 0 in day is added. Changed for compat.
289 Added support for negative months in adodb_mktime().
290 
291 - 24 Feb 2005 0.20
292 Added limited strftime/gmstrftime support. x10 improvement in performance of adodb_date().
293 
294 - 21 Dec 2004 0.17
295 In adodb_getdate(), the timestamp was accidentally converted to gmt when $is_gmt is false.
296 Also adodb_mktime(0,0,0) did not work properly. Both fixed thx Mauro.
297 
298 - 17 Nov 2004 0.16
299 Removed intval typecast in adodb_mktime() for secs, allowing:
300  adodb_mktime(0,0,0 + 2236672153,1,1,1934);
301 Suggested by Ryan.
302 
303 - 18 July 2004 0.15
304 All params in adodb_mktime were formerly compulsory. Now only the hour, min, secs is compulsory.
305 This brings it more in line with mktime (still not identical).
306 
307 - 23 June 2004 0.14
308 
309 Allow you to define your own daylights savings function, adodb_daylight_sv.
310 If the function is defined (somewhere in an include), then you can correct for daylights savings.
311 
312 In this example, we apply daylights savings in June or July, adding one hour. This is extremely
313 unrealistic as it does not take into account time-zone, geographic location, current year.
314 
315 function adodb_daylight_sv(&$arr, $is_gmt)
316 {
317  if ($is_gmt) return;
318  $m = $arr['mon'];
319  if ($m == 6 || $m == 7) $arr['hours'] += 1;
320 }
321 
322 This is only called by adodb_date() and not by adodb_mktime().
323 
324 The format of $arr is
325 Array (
326  [seconds] => 0
327  [minutes] => 0
328  [hours] => 0
329  [mday] => 1 # day of month, eg 1st day of the month
330  [mon] => 2 # month (eg. Feb)
331  [year] => 2102
332  [yday] => 31 # days in current year
333  [leap] => # true if leap year
334  [ndays] => 28 # no of days in current month
335  )
336 
337 
338 - 28 Apr 2004 0.13
339 Fixed adodb_date to properly support $is_gmt. Thx to Dimitar Angelov.
340 
341 - 20 Mar 2004 0.12
342 Fixed month calculation error in adodb_date. 2102-June-01 appeared as 2102-May-32.
343 
344 - 26 Oct 2003 0.11
345 Because of daylight savings problems (some systems apply daylight savings to
346 January!!!), changed adodb_get_gmt_diff() to ignore daylight savings.
347 
348 - 9 Aug 2003 0.10
349 Fixed bug with dates after 2038.
350 See http://phplens.com/lens/lensforum/msgs.php?id=6980
351 
352 - 1 July 2003 0.09
353 Added support for Q (Quarter).
354 Added adodb_date2(), which accepts ISO date in 2nd param
355 
356 - 3 March 2003 0.08
357 Added support for 'S' adodb_date() format char. Added constant ADODB_ALLOW_NEGATIVE_TS
358 if you want PHP to handle negative timestamps between 1901 to 1969.
359 
360 - 27 Feb 2003 0.07
361 All negative numbers handled by adodb now because of RH 7.3+ problems.
362 See http://bugs.php.net/bug.php?id=20048&edit=2
363 
364 - 4 Feb 2003 0.06
365 Fixed a typo, 1852 changed to 1582! This means that pre-1852 dates
366 are now correctly handled.
367 
368 - 29 Jan 2003 0.05
369 
370 Leap year checking differs under Julian calendar (pre 1582). Also
371 leap year code optimized by checking for most common case first.
372 
373 We also handle month overflow correctly in mktime (eg month set to 13).
374 
375 Day overflow for less than one month's days is supported.
376 
377 - 28 Jan 2003 0.04
378 
379 Gregorian correction handled. In PHP5, we might throw an error if
380 mktime uses invalid dates around 5-14 Oct 1582. Released with ADOdb 3.10.
381 Added limbo 5-14 Oct 1582 check, when we set to 15 Oct 1582.
382 
383 - 27 Jan 2003 0.03
384 
385 Fixed some more month problems due to gmt issues. Added constant ADODB_DATE_VERSION.
386 Fixed calculation of days since start of year for <1970.
387 
388 - 27 Jan 2003 0.02
389 
390 Changed _adodb_getdate() to inline leap year checking for better performance.
391 Fixed problem with time-zones west of GMT +0000.
392 
393 - 24 Jan 2003 0.01
394 
395 First implementation.
396 */
397 
398 
399 /* Initialization */
400 
401 /*
402  Version Number
403 */
404 define('ADODB_DATE_VERSION',0.35);
405 
406 $ADODB_DATETIME_CLASS = (PHP_VERSION >= 5.2);
407 
408 /*
409  This code was originally for windows. But apparently this problem happens
410  also with Linux, RH 7.3 and later!
411 
412  glibc-2.2.5-34 and greater has been changed to return -1 for dates <
413  1970. This used to work. The problem exists with RedHat 7.3 and 8.0
414  echo (mktime(0, 0, 0, 1, 1, 1960)); // prints -1
415 
416  References:
417  http://bugs.php.net/bug.php?id=20048&edit=2
418  http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html
419 */
420 
421 if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS',1);
422 
423 function adodb_date_test_date($y1,$m,$d=13)
424 {
425  $h = round(rand()% 24);
426  $t = adodb_mktime($h,0,0,$m,$d,$y1);
427  $rez = adodb_date('Y-n-j H:i:s',$t);
428  if ($h == 0) $h = '00';
429  else if ($h < 10) $h = '0'.$h;
430  if ("$y1-$m-$d $h:00:00" != $rez) {
431  print "<b>$y1 error, expected=$y1-$m-$d $h:00:00, adodb=$rez</b><br>";
432  return false;
433  }
434  return true;
435 }
436 
438 {
439  $s1 = strftime($fmt);
440  $s2 = adodb_strftime($fmt);
441 
442  if ($s1 == $s2) return true;
443 
444  echo "error for $fmt, strftime=$s1, adodb=$s2<br>";
445  return false;
446 }
447 
451 function adodb_date_test()
452 {
453 
454  for ($m=-24; $m<=24; $m++)
455  echo "$m :",adodb_date('d-m-Y',adodb_mktime(0,0,0,1+$m,20,2040)),"<br>";
456 
457  error_reporting(E_ALL);
458  print "<h4>Testing adodb_date and adodb_mktime. version=".ADODB_DATE_VERSION.' PHP='.PHP_VERSION."</h4>";
459  @set_time_limit(0);
460  $fail = false;
461 
462  // This flag disables calling of PHP native functions, so we can properly test the code
463  if (!defined('ADODB_TEST_DATES')) define('ADODB_TEST_DATES',1);
464 
465  $t = time();
466 
467 
468  $fmt = 'Y-m-d H:i:s';
469  echo '<pre>';
470  echo 'adodb: ',adodb_date($fmt,$t),'<br>';
471  echo 'php : ',date($fmt,$t),'<br>';
472  echo '</pre>';
473 
474  adodb_date_test_strftime('%Y %m %x %X');
475  adodb_date_test_strftime("%A %d %B %Y");
476  adodb_date_test_strftime("%H %M S");
477 
478  $t = adodb_mktime(0,0,0);
479  if (!(adodb_date('Y-m-d') == date('Y-m-d'))) print 'Error in '.adodb_mktime(0,0,0).'<br>';
480 
481  $t = adodb_mktime(0,0,0,6,1,2102);
482  if (!(adodb_date('Y-m-d',$t) == '2102-06-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>';
483 
484  $t = adodb_mktime(0,0,0,2,1,2102);
485  if (!(adodb_date('Y-m-d',$t) == '2102-02-01')) print 'Error in '.adodb_date('Y-m-d',$t).'<br>';
486 
487 
488  print "<p>Testing gregorian <=> julian conversion<p>";
489  $t = adodb_mktime(0,0,0,10,11,1492);
490  //http://www.holidayorigins.com/html/columbus_day.html - Friday check
491  if (!(adodb_date('D Y-m-d',$t) == 'Fri 1492-10-11')) print 'Error in Columbus landing<br>';
492 
493  $t = adodb_mktime(0,0,0,2,29,1500);
494  if (!(adodb_date('Y-m-d',$t) == '1500-02-29')) print 'Error in julian leap years<br>';
495 
496  $t = adodb_mktime(0,0,0,2,29,1700);
497  if (!(adodb_date('Y-m-d',$t) == '1700-03-01')) print 'Error in gregorian leap years<br>';
498 
499  print adodb_mktime(0,0,0,10,4,1582).' ';
500  print adodb_mktime(0,0,0,10,15,1582);
501  $diff = (adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582));
502  if ($diff != 3600*24) print " <b>Error in gregorian correction = ".($diff/3600/24)." days </b><br>";
503 
504  print " 15 Oct 1582, Fri=".(adodb_dow(1582,10,15) == 5 ? 'Fri' : '<b>Error</b>')."<br>";
505  print " 4 Oct 1582, Thu=".(adodb_dow(1582,10,4) == 4 ? 'Thu' : '<b>Error</b>')."<br>";
506 
507  print "<p>Testing overflow<p>";
508 
509  $t = adodb_mktime(0,0,0,3,33,1965);
510  if (!(adodb_date('Y-m-d',$t) == '1965-04-02')) print 'Error in day overflow 1 <br>';
511  $t = adodb_mktime(0,0,0,4,33,1971);
512  if (!(adodb_date('Y-m-d',$t) == '1971-05-03')) print 'Error in day overflow 2 <br>';
513  $t = adodb_mktime(0,0,0,1,60,1965);
514  if (!(adodb_date('Y-m-d',$t) == '1965-03-01')) print 'Error in day overflow 3 '.adodb_date('Y-m-d',$t).' <br>';
515  $t = adodb_mktime(0,0,0,12,32,1965);
516  if (!(adodb_date('Y-m-d',$t) == '1966-01-01')) print 'Error in day overflow 4 '.adodb_date('Y-m-d',$t).' <br>';
517  $t = adodb_mktime(0,0,0,12,63,1965);
518  if (!(adodb_date('Y-m-d',$t) == '1966-02-01')) print 'Error in day overflow 5 '.adodb_date('Y-m-d',$t).' <br>';
519  $t = adodb_mktime(0,0,0,13,3,1965);
520  if (!(adodb_date('Y-m-d',$t) == '1966-01-03')) print 'Error in mth overflow 1 <br>';
521 
522  print "Testing 2-digit => 4-digit year conversion<p>";
523  if (adodb_year_digit_check(00) != 2000) print "Err 2-digit 2000<br>";
524  if (adodb_year_digit_check(10) != 2010) print "Err 2-digit 2010<br>";
525  if (adodb_year_digit_check(20) != 2020) print "Err 2-digit 2020<br>";
526  if (adodb_year_digit_check(30) != 2030) print "Err 2-digit 2030<br>";
527  if (adodb_year_digit_check(40) != 1940) print "Err 2-digit 1940<br>";
528  if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950<br>";
529  if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990<br>";
530 
531  // Test string formating
532  print "<p>Testing date formating</p>";
533 
534  $fmt = '\d\a\t\e T Y-m-d H:i:s a A d D F g G h H i j l L m M n O \R\F\C2822 r s t U w y Y z Z 2003';
535  $s1 = date($fmt,0);
536  $s2 = adodb_date($fmt,0);
537  if ($s1 != $s2) {
538  print " date() 0 failed<br>$s1<br>$s2<br>";
539  }
540  flush();
541  for ($i=100; --$i > 0; ) {
542 
543  $ts = 3600.0*((rand()%60000)+(rand()%60000))+(rand()%60000);
544  $s1 = date($fmt,$ts);
545  $s2 = adodb_date($fmt,$ts);
546  //print "$s1 <br>$s2 <p>";
547  $pos = strcmp($s1,$s2);
548 
549  if (($s1) != ($s2)) {
550  for ($j=0,$k=strlen($s1); $j < $k; $j++) {
551  if ($s1[$j] != $s2[$j]) {
552  print substr($s1,$j).' ';
553  break;
554  }
555  }
556  print "<b>Error date(): $ts<br><pre>
557 &nbsp; \"$s1\" (date len=".strlen($s1).")
558 &nbsp; \"$s2\" (adodb_date len=".strlen($s2).")</b></pre><br>";
559  $fail = true;
560  }
561 
562  $a1 = getdate($ts);
563  $a2 = adodb_getdate($ts);
564  $rez = array_diff($a1,$a2);
565  if (sizeof($rez)>0) {
566  print "<b>Error getdate() $ts</b><br>";
567  print_r($a1);
568  print "<br>";
569  print_r($a2);
570  print "<p>";
571  $fail = true;
572  }
573  }
574 
575  // Test generation of dates outside 1901-2038
576  print "<p>Testing random dates between 100 and 4000</p>";
577  adodb_date_test_date(100,1);
578  for ($i=100; --$i >= 0;) {
579  $y1 = 100+rand(0,1970-100);
580  $m = rand(1,12);
581  adodb_date_test_date($y1,$m);
582 
583  $y1 = 3000-rand(0,3000-1970);
584  adodb_date_test_date($y1,$m);
585  }
586  print '<p>';
587  $start = 1960+rand(0,10);
588  $yrs = 12;
589  $i = 365.25*86400*($start-1970);
590  $offset = 36000+rand(10000,60000);
591  $max = 365*$yrs*86400;
592  $lastyear = 0;
593 
594  // we generate a timestamp, convert it to a date, and convert it back to a timestamp
595  // and check if the roundtrip broke the original timestamp value.
596  print "Testing $start to ".($start+$yrs).", or $max seconds, offset=$offset: ";
597  $cnt = 0;
598  for ($max += $i; $i < $max; $i += $offset) {
599  $ret = adodb_date('m,d,Y,H,i,s',$i);
600  $arr = explode(',',$ret);
601  if ($lastyear != $arr[2]) {
602  $lastyear = $arr[2];
603  print " $lastyear ";
604  flush();
605  }
606  $newi = adodb_mktime($arr[3],$arr[4],$arr[5],$arr[0],$arr[1],$arr[2]);
607  if ($i != $newi) {
608  print "Error at $i, adodb_mktime returned $newi ($ret)";
609  $fail = true;
610  break;
611  }
612  $cnt += 1;
613  }
614  echo "Tested $cnt dates<br>";
615  if (!$fail) print "<p>Passed !</p>";
616  else print "<p><b>Failed</b> :-(</p>";
617 }
618 
619 function adodb_time()
620 {
621  $d = new DateTime();
622  return $d->format('U');
623 }
624 
629 function adodb_dow($year, $month, $day)
630 {
631 /*
632 Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and
633 proclaimed that from that time onwards 3 days would be dropped from the calendar
634 every 400 years.
635 
636 Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian).
637 */
638  if ($year <= 1582) {
639  if ($year < 1582 ||
640  ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))) $greg_correction = 3;
641  else
642  $greg_correction = 0;
643  } else
644  $greg_correction = 0;
645 
646  if($month > 2)
647  $month -= 2;
648  else {
649  $month += 10;
650  $year--;
651  }
652 
653  $day = floor((13 * $month - 1) / 5) +
654  $day + ($year % 100) +
655  floor(($year % 100) / 4) +
656  floor(($year / 100) / 4) - 2 *
657  floor($year / 100) + 77 + $greg_correction;
658 
659  return $day - 7 * floor($day / 7);
660 }
661 
662 
667 function _adodb_is_leap_year($year)
668 {
669  if ($year % 4 != 0) return false;
670 
671  if ($year % 400 == 0) {
672  return true;
673  // if gregorian calendar (>1582), century not-divisible by 400 is not leap
674  } else if ($year > 1582 && $year % 100 == 0 ) {
675  return false;
676  }
677 
678  return true;
679 }
680 
681 
685 function adodb_is_leap_year($year)
686 {
688 }
689 
695 {
696  if ($y < 100) {
697 
698  $yr = (integer) date("Y");
699  $century = (integer) ($yr /100);
700 
701  if ($yr%100 > 50) {
702  $c1 = $century + 1;
703  $c0 = $century;
704  } else {
705  $c1 = $century;
706  $c0 = $century - 1;
707  }
708  $c1 *= 100;
709  // if 2-digit year is less than 30 years in future, set it to this century
710  // otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
711  if (($y + $c1) < $yr+30) $y = $y + $c1;
712  else $y = $y + $c0*100;
713  }
714  return $y;
715 }
716 
718 {
719  if (0 <= $ts && $ts <= 0x7FFFFFFF) { // check if number in 32-bit signed range) {
720  $arr = getdate($ts);
721  $y = $arr['year'];
722  $m = $arr['mon'];
723  $d = $arr['mday'];
724  return adodb_get_gmt_diff($y,$m,$d);
725  } else {
726  return adodb_get_gmt_diff(false,false,false);
727  }
728 
729 }
730 
734 function adodb_get_gmt_diff($y,$m,$d)
735 {
736 static $TZ,$tzo;
737 global $ADODB_DATETIME_CLASS;
738 
739  if (!defined('ADODB_TEST_DATES')) $y = false;
740  else if ($y < 1970 || $y >= 2038) $y = false;
741 
742  if ($ADODB_DATETIME_CLASS && $y !== false) {
743  $dt = new DateTime();
744  $dt->setISODate($y,$m,$d);
745  if (empty($tzo)) {
746  $tzo = new DateTimeZone(date_default_timezone_get());
747  # $tzt = timezone_transitions_get( $tzo );
748  }
749  return -$tzo->getOffset($dt);
750  } else {
751  if (isset($TZ)) return $TZ;
752  $y = date('Y');
753  /*
754  if (function_exists('date_default_timezone_get') && function_exists('timezone_offset_get')) {
755  $tzonename = date_default_timezone_get();
756  if ($tzonename) {
757  $tobj = new DateTimeZone($tzonename);
758  $TZ = -timezone_offset_get($tobj,new DateTime("now",$tzo));
759  }
760  }
761  */
762  if (empty($TZ)) $TZ = mktime(0,0,0,12,2,$y) - gmmktime(0,0,0,12,2,$y);
763  }
764  return $TZ;
765 }
766 
770 function adodb_getdate($d=false,$fast=false)
771 {
772  if ($d === false) return getdate();
773  if (!defined('ADODB_TEST_DATES')) {
774  if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
775  if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
776  return @getdate($d);
777  }
778  }
779  return _adodb_getdate($d);
780 }
781 
782 /*
783 // generate $YRS table for _adodb_getdate()
784 function adodb_date_gentable($out=true)
785 {
786 
787  for ($i=1970; $i >= 1600; $i-=10) {
788  $s = adodb_gmmktime(0,0,0,1,1,$i);
789  echo "$i => $s,<br>";
790  }
791 }
792 adodb_date_gentable();
793 
794 for ($i=1970; $i > 1500; $i--) {
795 
796 echo "<hr />$i ";
797  adodb_date_test_date($i,1,1);
798 }
799 
800 */
801 
802 
803 $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
804 $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
805 
806 function adodb_validdate($y,$m,$d)
807 {
809 
810  if (_adodb_is_leap_year($y)) $marr = $_month_table_leaf;
811  else $marr = $_month_table_normal;
812 
813  if ($m > 12 || $m < 1) return false;
814 
815  if ($d > 31 || $d < 1) return false;
816 
817  if ($marr[$m] < $d) return false;
818 
819  if ($y < 1000 && $y > 3000) return false;
820 
821  return true;
822 }
823 
829 function _adodb_getdate($origd=false,$fast=false,$is_gmt=false)
830 {
831 static $YRS;
833 
834  $d = $origd - ($is_gmt ? 0 : adodb_get_gmt_diff_ts($origd));
835  $_day_power = 86400;
836  $_hour_power = 3600;
837  $_min_power = 60;
838 
839  if ($d < -12219321600) $d -= 86400*10; // if 15 Oct 1582 or earlier, gregorian correction
840 
841  $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
842  $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
843 
844  $d366 = $_day_power * 366;
845  $d365 = $_day_power * 365;
846 
847  if ($d < 0) {
848 
849  if (empty($YRS)) $YRS = array(
850  1970 => 0,
851  1960 => -315619200,
852  1950 => -631152000,
853  1940 => -946771200,
854  1930 => -1262304000,
855  1920 => -1577923200,
856  1910 => -1893456000,
857  1900 => -2208988800,
858  1890 => -2524521600,
859  1880 => -2840140800,
860  1870 => -3155673600,
861  1860 => -3471292800,
862  1850 => -3786825600,
863  1840 => -4102444800,
864  1830 => -4417977600,
865  1820 => -4733596800,
866  1810 => -5049129600,
867  1800 => -5364662400,
868  1790 => -5680195200,
869  1780 => -5995814400,
870  1770 => -6311347200,
871  1760 => -6626966400,
872  1750 => -6942499200,
873  1740 => -7258118400,
874  1730 => -7573651200,
875  1720 => -7889270400,
876  1710 => -8204803200,
877  1700 => -8520336000,
878  1690 => -8835868800,
879  1680 => -9151488000,
880  1670 => -9467020800,
881  1660 => -9782640000,
882  1650 => -10098172800,
883  1640 => -10413792000,
884  1630 => -10729324800,
885  1620 => -11044944000,
886  1610 => -11360476800,
887  1600 => -11676096000);
888 
889  if ($is_gmt) $origd = $d;
890  // The valid range of a 32bit signed timestamp is typically from
891  // Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT
892  //
893 
894  # old algorithm iterates through all years. new algorithm does it in
895  # 10 year blocks
896 
897  /*
898  # old algo
899  for ($a = 1970 ; --$a >= 0;) {
900  $lastd = $d;
901 
902  if ($leaf = _adodb_is_leap_year($a)) $d += $d366;
903  else $d += $d365;
904 
905  if ($d >= 0) {
906  $year = $a;
907  break;
908  }
909  }
910  */
911 
912  $lastsecs = 0;
913  $lastyear = 1970;
914  foreach($YRS as $year => $secs) {
915  if ($d >= $secs) {
916  $a = $lastyear;
917  break;
918  }
919  $lastsecs = $secs;
920  $lastyear = $year;
921  }
922 
923  $d -= $lastsecs;
924  if (!isset($a)) $a = $lastyear;
925 
926  //echo ' yr=',$a,' ', $d,'.';
927 
928  for (; --$a >= 0;) {
929  $lastd = $d;
930 
931  if ($leaf = _adodb_is_leap_year($a)) $d += $d366;
932  else $d += $d365;
933 
934  if ($d >= 0) {
935  $year = $a;
936  break;
937  }
938  }
939 
940 
941  $secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd;
942 
943  $d = $lastd;
944  $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
945  for ($a = 13 ; --$a > 0;) {
946  $lastd = $d;
947  $d += $mtab[$a] * $_day_power;
948  if ($d >= 0) {
949  $month = $a;
950  $ndays = $mtab[$a];
951  break;
952  }
953  }
954 
955  $d = $lastd;
956  $day = $ndays + ceil(($d+1) / ($_day_power));
957 
958  $d += ($ndays - $day+1)* $_day_power;
959  $hour = floor($d/$_hour_power);
960 
961  } else {
962  for ($a = 1970 ;; $a++) {
963  $lastd = $d;
964 
965  if ($leaf = _adodb_is_leap_year($a)) $d -= $d366;
966  else $d -= $d365;
967  if ($d < 0) {
968  $year = $a;
969  break;
970  }
971  }
972  $secsInYear = $lastd;
973  $d = $lastd;
974  $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
975  for ($a = 1 ; $a <= 12; $a++) {
976  $lastd = $d;
977  $d -= $mtab[$a] * $_day_power;
978  if ($d < 0) {
979  $month = $a;
980  $ndays = $mtab[$a];
981  break;
982  }
983  }
984  $d = $lastd;
985  $day = ceil(($d+1) / $_day_power);
986  $d = $d - ($day-1) * $_day_power;
987  $hour = floor($d /$_hour_power);
988  }
989 
990  $d -= $hour * $_hour_power;
991  $min = floor($d/$_min_power);
992  $secs = $d - $min * $_min_power;
993  if ($fast) {
994  return array(
995  'seconds' => $secs,
996  'minutes' => $min,
997  'hours' => $hour,
998  'mday' => $day,
999  'mon' => $month,
1000  'year' => $year,
1001  'yday' => floor($secsInYear/$_day_power),
1002  'leap' => $leaf,
1003  'ndays' => $ndays
1004  );
1005  }
1006 
1007 
1008  $dow = adodb_dow($year,$month,$day);
1009 
1010  return array(
1011  'seconds' => $secs,
1012  'minutes' => $min,
1013  'hours' => $hour,
1014  'mday' => $day,
1015  'wday' => $dow,
1016  'mon' => $month,
1017  'year' => $year,
1018  'yday' => floor($secsInYear/$_day_power),
1019  'weekday' => gmdate('l',$_day_power*(3+$dow)),
1020  'month' => gmdate('F',mktime(0,0,0,$month,2,1971)),
1021  0 => $origd
1022  );
1023 }
1024 /*
1025  if ($isphp5)
1026  $dates .= sprintf('%s%04d',($gmt<=0)?'+':'-',abs($gmt)/36);
1027  else
1028  $dates .= sprintf('%s%04d',($gmt<0)?'+':'-',abs($gmt)/36);
1029  break;*/
1030 function adodb_tz_offset($gmt,$isphp5)
1031 {
1032  $zhrs = abs($gmt)/3600;
1033  $hrs = floor($zhrs);
1034  if ($isphp5)
1035  return sprintf('%s%02d%02d',($gmt<=0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60);
1036  else
1037  return sprintf('%s%02d%02d',($gmt<0)?'+':'-',floor($zhrs),($zhrs-$hrs)*60);
1038 }
1039 
1040 
1041 function adodb_gmdate($fmt,$d=false)
1042 {
1043  return adodb_date($fmt,$d,true);
1044 }
1045 
1046 // accepts unix timestamp and iso date format in $d
1047 function adodb_date2($fmt, $d=false, $is_gmt=false)
1048 {
1049  if ($d !== false) {
1050  if (!preg_match(
1051  "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ -]?(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|",
1052  ($d), $rr)) return adodb_date($fmt,false,$is_gmt);
1053 
1054  if ($rr[1] <= 100 && $rr[2]<= 1) return adodb_date($fmt,false,$is_gmt);
1055 
1056  // h-m-s-MM-DD-YY
1057  if (!isset($rr[5])) $d = adodb_mktime(0,0,0,$rr[2],$rr[3],$rr[1],false,$is_gmt);
1058  else $d = @adodb_mktime($rr[5],$rr[6],$rr[7],$rr[2],$rr[3],$rr[1],false,$is_gmt);
1059  }
1060 
1061  return adodb_date($fmt,$d,$is_gmt);
1062 }
1063 
1064 
1068 function adodb_date($fmt,$d=false,$is_gmt=false)
1069 {
1070 static $daylight;
1071 global $ADODB_DATETIME_CLASS;
1072 static $jan1_1971;
1073 
1074 
1075  if (!isset($daylight)) {
1076  $daylight = function_exists('adodb_daylight_sv');
1077  if (empty($jan1_1971)) $jan1_1971 = mktime(0,0,0,1,1,1971); // we only use date() when > 1970 as adodb_mktime() only uses mktime() when > 1970
1078  }
1079 
1080  if ($d === false) return ($is_gmt)? @gmdate($fmt): @date($fmt);
1081  if (!defined('ADODB_TEST_DATES')) {
1082  if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
1083 
1084  if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= $jan1_1971) // if windows, must be +ve integer
1085  return ($is_gmt)? @gmdate($fmt,$d): @date($fmt,$d);
1086 
1087  }
1088  }
1089  $_day_power = 86400;
1090 
1091  $arr = _adodb_getdate($d,true,$is_gmt);
1092 
1093  if ($daylight) adodb_daylight_sv($arr, $is_gmt);
1094 
1095  $year = $arr['year'];
1096  $month = $arr['mon'];
1097  $day = $arr['mday'];
1098  $hour = $arr['hours'];
1099  $min = $arr['minutes'];
1100  $secs = $arr['seconds'];
1101 
1102  $max = strlen($fmt);
1103  $dates = '';
1104 
1105  $isphp5 = PHP_VERSION >= 5;
1106 
1107  /*
1108  at this point, we have the following integer vars to manipulate:
1109  $year, $month, $day, $hour, $min, $secs
1110  */
1111  for ($i=0; $i < $max; $i++) {
1112  switch($fmt[$i]) {
1113  case 'e':
1114  $dates .= date('e');
1115  break;
1116  case 'T':
1117  if ($ADODB_DATETIME_CLASS) {
1118  $dt = new DateTime();
1119  $dt->SetDate($year,$month,$day);
1120  $dates .= $dt->Format('T');
1121  } else
1122  $dates .= date('T');
1123  break;
1124  // YEAR
1125  case 'L': $dates .= $arr['leap'] ? '1' : '0'; break;
1126  case 'r': // Thu, 21 Dec 2000 16:01:07 +0200
1127 
1128  // 4.3.11 uses '04 Jun 2004'
1129  // 4.3.8 uses ' 4 Jun 2004'
1130  $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))).', '
1131  . ($day<10?'0'.$day:$day) . ' '.date('M',mktime(0,0,0,$month,2,1971)).' '.$year.' ';
1132 
1133  if ($hour < 10) $dates .= '0'.$hour; else $dates .= $hour;
1134 
1135  if ($min < 10) $dates .= ':0'.$min; else $dates .= ':'.$min;
1136 
1137  if ($secs < 10) $dates .= ':0'.$secs; else $dates .= ':'.$secs;
1138 
1139  $gmt = adodb_get_gmt_diff($year,$month,$day);
1140 
1141  $dates .= ' '.adodb_tz_offset($gmt,$isphp5);
1142  break;
1143 
1144  case 'Y': $dates .= $year; break;
1145  case 'y': $dates .= substr($year,strlen($year)-2,2); break;
1146  // MONTH
1147  case 'm': if ($month<10) $dates .= '0'.$month; else $dates .= $month; break;
1148  case 'Q': $dates .= ($month+3)>>2; break;
1149  case 'n': $dates .= $month; break;
1150  case 'M': $dates .= date('M',mktime(0,0,0,$month,2,1971)); break;
1151  case 'F': $dates .= date('F',mktime(0,0,0,$month,2,1971)); break;
1152  // DAY
1153  case 't': $dates .= $arr['ndays']; break;
1154  case 'z': $dates .= $arr['yday']; break;
1155  case 'w': $dates .= adodb_dow($year,$month,$day); break;
1156  case 'l': $dates .= gmdate('l',$_day_power*(3+adodb_dow($year,$month,$day))); break;
1157  case 'D': $dates .= gmdate('D',$_day_power*(3+adodb_dow($year,$month,$day))); break;
1158  case 'j': $dates .= $day; break;
1159  case 'd': if ($day<10) $dates .= '0'.$day; else $dates .= $day; break;
1160  case 'S':
1161  $d10 = $day % 10;
1162  if ($d10 == 1) $dates .= 'st';
1163  else if ($d10 == 2 && $day != 12) $dates .= 'nd';
1164  else if ($d10 == 3) $dates .= 'rd';
1165  else $dates .= 'th';
1166  break;
1167 
1168  // HOUR
1169  case 'Z':
1170  $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff($year,$month,$day); break;
1171  case 'O':
1172  $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$month,$day);
1173 
1174  $dates .= adodb_tz_offset($gmt,$isphp5);
1175  break;
1176 
1177  case 'H':
1178  if ($hour < 10) $dates .= '0'.$hour;
1179  else $dates .= $hour;
1180  break;
1181  case 'h':
1182  if ($hour > 12) $hh = $hour - 12;
1183  else {
1184  if ($hour == 0) $hh = '12';
1185  else $hh = $hour;
1186  }
1187 
1188  if ($hh < 10) $dates .= '0'.$hh;
1189  else $dates .= $hh;
1190  break;
1191 
1192  case 'G':
1193  $dates .= $hour;
1194  break;
1195 
1196  case 'g':
1197  if ($hour > 12) $hh = $hour - 12;
1198  else {
1199  if ($hour == 0) $hh = '12';
1200  else $hh = $hour;
1201  }
1202  $dates .= $hh;
1203  break;
1204  // MINUTES
1205  case 'i': if ($min < 10) $dates .= '0'.$min; else $dates .= $min; break;
1206  // SECONDS
1207  case 'U': $dates .= $d; break;
1208  case 's': if ($secs < 10) $dates .= '0'.$secs; else $dates .= $secs; break;
1209  // AM/PM
1210  // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM
1211  case 'a':
1212  if ($hour>=12) $dates .= 'pm';
1213  else $dates .= 'am';
1214  break;
1215  case 'A':
1216  if ($hour>=12) $dates .= 'PM';
1217  else $dates .= 'AM';
1218  break;
1219  default:
1220  $dates .= $fmt[$i]; break;
1221  // ESCAPE
1222  case "\\":
1223  $i++;
1224  if ($i < $max) $dates .= $fmt[$i];
1225  break;
1226  }
1227  }
1228  return $dates;
1229 }
1230 
1235 function adodb_gmmktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false)
1236 {
1237  return adodb_mktime($hr,$min,$sec,$mon,$day,$year,$is_dst,true);
1238 }
1239 
1246 function adodb_mktime($hr,$min,$sec,$mon=false,$day=false,$year=false,$is_dst=false,$is_gmt=false)
1247 {
1248  if (!defined('ADODB_TEST_DATES')) {
1249 
1250  if ($mon === false) {
1251  return $is_gmt? @gmmktime($hr,$min,$sec): @mktime($hr,$min,$sec);
1252  }
1253 
1254  // for windows, we don't check 1970 because with timezone differences,
1255  // 1 Jan 1970 could generate negative timestamp, which is illegal
1256  $usephpfns = (1970 < $year && $year < 2038
1257  || !defined('ADODB_NO_NEGATIVE_TS') && (1901 < $year && $year < 2038)
1258  );
1259 
1260 
1261  if ($usephpfns && ($year + $mon/12+$day/365.25+$hr/(24*365.25) >= 2038)) $usephpfns = false;
1262 
1263  if ($usephpfns) {
1264  return $is_gmt ?
1265  @gmmktime($hr,$min,$sec,$mon,$day,$year):
1266  @mktime($hr,$min,$sec,$mon,$day,$year);
1267  }
1268  }
1269 
1270  $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff($year,$mon,$day);
1271 
1272  /*
1273  # disabled because some people place large values in $sec.
1274  # however we need it for $mon because we use an array...
1275  $hr = intval($hr);
1276  $min = intval($min);
1277  $sec = intval($sec);
1278  */
1279  $mon = intval($mon);
1280  $day = intval($day);
1281  $year = intval($year);
1282 
1283 
1284  $year = adodb_year_digit_check($year);
1285 
1286  if ($mon > 12) {
1287  $y = floor(($mon-1)/ 12);
1288  $year += $y;
1289  $mon -= $y*12;
1290  } else if ($mon < 1) {
1291  $y = ceil((1-$mon) / 12);
1292  $year -= $y;
1293  $mon += $y*12;
1294  }
1295 
1296  $_day_power = 86400;
1297  $_hour_power = 3600;
1298  $_min_power = 60;
1299 
1300  $_month_table_normal = array("",31,28,31,30,31,30,31,31,30,31,30,31);
1301  $_month_table_leaf = array("",31,29,31,30,31,30,31,31,30,31,30,31);
1302 
1303  $_total_date = 0;
1304  if ($year >= 1970) {
1305  for ($a = 1970 ; $a <= $year; $a++) {
1306  $leaf = _adodb_is_leap_year($a);
1307  if ($leaf == true) {
1308  $loop_table = $_month_table_leaf;
1309  $_add_date = 366;
1310  } else {
1311  $loop_table = $_month_table_normal;
1312  $_add_date = 365;
1313  }
1314  if ($a < $year) {
1315  $_total_date += $_add_date;
1316  } else {
1317  for($b=1;$b<$mon;$b++) {
1318  $_total_date += $loop_table[$b];
1319  }
1320  }
1321  }
1322  $_total_date +=$day-1;
1323  $ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different;
1324 
1325  } else {
1326  for ($a = 1969 ; $a >= $year; $a--) {
1327  $leaf = _adodb_is_leap_year($a);
1328  if ($leaf == true) {
1329  $loop_table = $_month_table_leaf;
1330  $_add_date = 366;
1331  } else {
1332  $loop_table = $_month_table_normal;
1333  $_add_date = 365;
1334  }
1335  if ($a > $year) { $_total_date += $_add_date;
1336  } else {
1337  for($b=12;$b>$mon;$b--) {
1338  $_total_date += $loop_table[$b];
1339  }
1340  }
1341  }
1342  $_total_date += $loop_table[$mon] - $day;
1343 
1344  $_day_time = $hr * $_hour_power + $min * $_min_power + $sec;
1345  $_day_time = $_day_power - $_day_time;
1346  $ret = -( $_total_date * $_day_power + $_day_time - $gmt_different);
1347  if ($ret < -12220185600) $ret += 10*86400; // if earlier than 5 Oct 1582 - gregorian correction
1348  else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582.
1349  }
1350  //print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret;
1351  return $ret;
1352 }
1353 
1354 function adodb_gmstrftime($fmt, $ts=false)
1355 {
1356  return adodb_strftime($fmt,$ts,true);
1357 }
1358 
1359 // hack - convert to adodb_date
1360 function adodb_strftime($fmt, $ts=false,$is_gmt=false)
1361 {
1362 global $ADODB_DATE_LOCALE;
1363 
1364  if (!defined('ADODB_TEST_DATES')) {
1365  if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
1366  if (!defined('ADODB_NO_NEGATIVE_TS') || $ts >= 0) // if windows, must be +ve integer
1367  return ($is_gmt)? @gmstrftime($fmt,$ts): @strftime($fmt,$ts);
1368 
1369  }
1370  }
1371 
1372  if (empty($ADODB_DATE_LOCALE)) {
1373  /*
1374  $tstr = strtoupper(gmstrftime('%c',31366800)); // 30 Dec 1970, 1 am
1375  $sep = substr($tstr,2,1);
1376  $hasAM = strrpos($tstr,'M') !== false;
1377  */
1378  # see http://phplens.com/lens/lensforum/msgs.php?id=14865 for reasoning, and changelog for version 0.24
1379  $dstr = gmstrftime('%x',31366800); // 30 Dec 1970, 1 am
1380  $sep = substr($dstr,2,1);
1381  $tstr = strtoupper(gmstrftime('%X',31366800)); // 30 Dec 1970, 1 am
1382  $hasAM = strrpos($tstr,'M') !== false;
1383 
1384  $ADODB_DATE_LOCALE = array();
1385  $ADODB_DATE_LOCALE[] = strncmp($tstr,'30',2) == 0 ? 'd'.$sep.'m'.$sep.'y' : 'm'.$sep.'d'.$sep.'y';
1386  $ADODB_DATE_LOCALE[] = ($hasAM) ? 'h:i:s a' : 'H:i:s';
1387 
1388  }
1389  $inpct = false;
1390  $fmtdate = '';
1391  for ($i=0,$max = strlen($fmt); $i < $max; $i++) {
1392  $ch = $fmt[$i];
1393  if ($ch == '%') {
1394  if ($inpct) {
1395  $fmtdate .= '%';
1396  $inpct = false;
1397  } else
1398  $inpct = true;
1399  } else if ($inpct) {
1400 
1401  $inpct = false;
1402  switch($ch) {
1403  case '0':
1404  case '1':
1405  case '2':
1406  case '3':
1407  case '4':
1408  case '5':
1409  case '6':
1410  case '7':
1411  case '8':
1412  case '9':
1413  case 'E':
1414  case 'O':
1415  /* ignore format modifiers */
1416  $inpct = true;
1417  break;
1418 
1419  case 'a': $fmtdate .= 'D'; break;
1420  case 'A': $fmtdate .= 'l'; break;
1421  case 'h':
1422  case 'b': $fmtdate .= 'M'; break;
1423  case 'B': $fmtdate .= 'F'; break;
1424  case 'c': $fmtdate .= $ADODB_DATE_LOCALE[0].$ADODB_DATE_LOCALE[1]; break;
1425  case 'C': $fmtdate .= '\C?'; break; // century
1426  case 'd': $fmtdate .= 'd'; break;
1427  case 'D': $fmtdate .= 'm/d/y'; break;
1428  case 'e': $fmtdate .= 'j'; break;
1429  case 'g': $fmtdate .= '\g?'; break; //?
1430  case 'G': $fmtdate .= '\G?'; break; //?
1431  case 'H': $fmtdate .= 'H'; break;
1432  case 'I': $fmtdate .= 'h'; break;
1433  case 'j': $fmtdate .= '?z'; $parsej = true; break; // wrong as j=1-based, z=0-basd
1434  case 'm': $fmtdate .= 'm'; break;
1435  case 'M': $fmtdate .= 'i'; break;
1436  case 'n': $fmtdate .= "\n"; break;
1437  case 'p': $fmtdate .= 'a'; break;
1438  case 'r': $fmtdate .= 'h:i:s a'; break;
1439  case 'R': $fmtdate .= 'H:i:s'; break;
1440  case 'S': $fmtdate .= 's'; break;
1441  case 't': $fmtdate .= "\t"; break;
1442  case 'T': $fmtdate .= 'H:i:s'; break;
1443  case 'u': $fmtdate .= '?u'; $parseu = true; break; // wrong strftime=1-based, date=0-based
1444  case 'U': $fmtdate .= '?U'; $parseU = true; break;// wrong strftime=1-based, date=0-based
1445  case 'x': $fmtdate .= $ADODB_DATE_LOCALE[0]; break;
1446  case 'X': $fmtdate .= $ADODB_DATE_LOCALE[1]; break;
1447  case 'w': $fmtdate .= '?w'; $parseu = true; break; // wrong strftime=1-based, date=0-based
1448  case 'W': $fmtdate .= '?W'; $parseU = true; break;// wrong strftime=1-based, date=0-based
1449  case 'y': $fmtdate .= 'y'; break;
1450  case 'Y': $fmtdate .= 'Y'; break;
1451  case 'Z': $fmtdate .= 'T'; break;
1452  }
1453  } else if (('A' <= ($ch) && ($ch) <= 'Z' ) || ('a' <= ($ch) && ($ch) <= 'z' ))
1454  $fmtdate .= "\\".$ch;
1455  else
1456  $fmtdate .= $ch;
1457  }
1458  //echo "fmt=",$fmtdate,"<br>";
1459  if ($ts === false) $ts = time();
1460  $ret = adodb_date($fmtdate, $ts, $is_gmt);
1461  return $ret;
1462 }
adodb_get_gmt_diff($y, $m, $d)
adodb_date_test_date($y1, $m, $d=13)
adodb_is_leap_year($year)
adodb_gmmktime($hr, $min, $sec, $mon=false, $day=false, $year=false, $is_dst=false)
$_month_table_normal
adodb_dow($year, $month, $day)
adodb_tz_offset($gmt, $isphp5)
adodb_gmdate($fmt, $d=false)
adodb_date($fmt, $d=false, $is_gmt=false)
$sep
Definition: server.php:44
adodb_gmstrftime($fmt, $ts=false)
adodb_time()
adodb_get_gmt_diff_ts($ts)
adodb_date2($fmt, $d=false, $is_gmt=false)
adodb_date_test()
adodb_validdate($y, $m, $d)
adodb_date_test_strftime($fmt)
adodb_getdate($d=false, $fast=false)
adodb_mktime($hr, $min, $sec, $mon=false, $day=false, $year=false, $is_dst=false, $is_gmt=false)
$ADODB_DATETIME_CLASS
_adodb_is_leap_year($year)
_adodb_getdate($origd=false, $fast=false, $is_gmt=false)
if(!defined( 'ADODB_ALLOW_NEGATIVE_TS')) define( 'ADODB_NO_NEGATIVE_TS'
adodb_strftime($fmt, $ts=false, $is_gmt=false)
adodb_year_digit_check($y)
$_month_table_leaf