3 ADOdb Date Library, part of the ADOdb abstraction library
4 Download: http://php.weblogs.com/adodb_date_time_library
6 PHP native date functions use integer timestamps for computations.
7 Because of this, dates are restricted to the years 1901-2038 on Unix
8 and 1970-2038 on Windows due to integer overflow for dates beyond
9 those years. This library overcomes these limitations by replacing the
10 native function's signed integers (normally 32-bits) with PHP floating
11 point numbers (normally 64-bits).
13 Dates from 100 A.D. to 3000 A.D. and later
14 have been tested. The minimum is 100 A.D. as <100 will invoke the
15 2 => 4 digit year conversion. The maximum is billions of years in the
16 future, but this is a theoretical limit as the computation of that year
17 would take too long with the current implementation of adodb_mktime().
19 This library replaces native functions as follows:
22 getdate() with adodb_getdate()
23 date() with adodb_date()
24 gmdate() with adodb_gmdate()
25 mktime() with adodb_mktime()
26 gmmktime() with adodb_gmmktime()
29 The parameters are identical, except that adodb_date() accepts a subset
30 of date()'s field formats. Mktime() will convert from local time to GMT,
31 and date() will convert from GMT to local time, but daylight savings is
32 not handled currently.
34 This library is independant of the rest of ADOdb, and can be used
39 For high speed, this library uses the native date functions where
40 possible, and only switches to PHP code when the dates fall outside
41 the 32-bit signed integer range.
45 Pope Gregory shortened October of A.D. 1582 by ten days. Thursday,
46 October 4, 1582 (Julian) was followed immediately by Friday, October 15,
49 Since 0.06, we handle this correctly, so:
51 adodb_mktime(0,0,0,10,15,1582) - adodb_mktime(0,0,0,10,4,1582)
54 =============================================================================
58 (c) 2003 John Lim and released under BSD-style license except for code by jackbbs,
59 which includes adodb_mktime, adodb_get_gmt_diff, adodb_is_leap_year
60 and originally found at http://www.php.net/manual/en/function.mktime.php
62 =============================================================================
66 These should be posted to the ADOdb forums at
68 http://phplens.com/lens/lensforum/topics.php?id=4
70 =============================================================================
74 FUNCTION adodb_getdate($date=false)
76 Returns an array containing date information, as getdate(), but supports
77 dates greater than 1901 to 2038.
79 FUNCTION adodb_date($fmt, $timestamp = false)
81 Convert a timestamp to a formatted local date. If $timestamp is not defined, the
82 current timestamp is used. Unlike the function date(), it supports dates
83 outside the 1901 to 2038 range.
85 The format fields that adodb_date supports:
90 d - day of the month, 2 digits with leading zeros; i.e. "01" to "31"
91 D - day of the week, textual, 3 letters; e.g. "Fri"
92 F - month, textual, long; e.g. "January"
93 g - hour, 12-hour format without leading zeros; i.e. "1" to "12"
94 G - hour, 24-hour format without leading zeros; i.e. "0" to "23"
95 h - hour, 12-hour format; i.e. "01" to "12"
96 H - hour, 24-hour format; i.e. "00" to "23"
97 i - minutes; i.e. "00" to "59"
98 j - day of the month without leading zeros; i.e. "1" to "31"
99 l (lowercase 'L') - day of the week, textual, long; e.g. "Friday"
100 L - boolean for whether it is a leap year; i.e. "0" or "1"
101 m - month; i.e. "01" to "12"
102 M - month, textual, 3 letters; e.g. "Jan"
103 n - month without leading zeros; i.e. "1" to "12"
104 O - Difference to Greenwich time in hours; e.g. "+0200"
105 Q - Quarter, as in 1, 2, 3, 4
106 r - RFC 822 formatted date; e.g. "Thu, 21 Dec 2000 16:01:07 +0200"
107 s - seconds; i.e. "00" to "59"
108 S - English ordinal suffix for the day of the month, 2 characters;
109 i.e. "st", "nd", "rd" or "th"
110 t - number of days in the given month; i.e. "28" to "31"
111 T - Timezone setting of this machine; e.g. "EST" or "MDT"
112 U - seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
113 w - day of the week, numeric, i.e. "0" (Sunday) to "6" (Saturday)
114 Y - year, 4 digits; e.g. "1999"
115 y - year, 2 digits; e.g. "99"
116 z - day of the year; i.e. "0" to "365"
117 Z - timezone offset in seconds (i.e. "-43200" to "43200").
118 The offset for timezones west of UTC is always negative,
119 and for those east of UTC is always positive.
124 B - Swatch Internet time
125 I (capital i) - "1" if Daylight Savings Time, "0" otherwise.
126 W - ISO-8601 week number of year, weeks starting on Monday
130 FUNCTION adodb_date2($fmt, $isoDateString = false)
131 Same as adodb_date, but 2nd parameter accepts iso date, eg.
133 adodb_date2('d-M-Y H:i','2003-12-25 13:01:34');
135 FUNCTION adodb_gmdate($fmt, $timestamp = false)
137 Convert a timestamp to a formatted GMT date. If $timestamp is not defined, the
138 current timestamp is used. Unlike the function date(), it supports dates
139 outside the 1901 to 2038 range.
141 FUNCTION adodb_mktime($hr, $min, $sec, $month, $day, $year)
143 Converts a local date to a unix timestamp. Unlike the function mktime(), it supports
144 dates outside the 1901 to 2038 range. Differs from mktime() in that all parameters
145 are currently compulsory.
147 FUNCTION adodb_gmmktime($hr, $min, $sec, $month, $day, $year)
149 Converts a gmt date to a unix timestamp. Unlike the function gmmktime(), it supports
150 dates outside the 1901 to 2038 range. Differs from gmmktime() in that all parameters
151 are currently compulsory.
153 =============================================================================
157 Useful url for generating test timestamps:
158 http://www.4webhelp.net/us/timestamp.php
160 Possible future optimizations include
162 a. Using an algorithm similar to Plauger's in "The Standard C Library"
163 (page 428, xttotm.c _Ttotm() function). Plauger's algorithm will not
164 work outside 32-bit signed range, so i decided not to implement it.
166 b. Iterate over a block of years (say 12) when searching for the
169 c. Implement daylight savings, which looks awfully complicated, see
170 http://webexhibits.org/daylightsaving/
174 Fixed month calculation error in adodb_date. 2102-June-01 appeared as 2102-May-32.
177 Because of daylight savings problems (some systems apply daylight savings to
178 January!!!), changed adodb_get_gmt_diff() to ignore daylight savings.
181 Fixed bug with dates after 2038.
182 See http://phplens.com/lens/lensforum/msgs.php?id=6980
185 Added support for Q (Quarter).
186 Added adodb_date2(), which accepts ISO date in 2nd param
189 Added support for 'S' adodb_date() format char. Added constant ADODB_ALLOW_NEGATIVE_TS
190 if you want PHP to handle negative timestamps between 1901 to 1969.
193 All negative numbers handled by adodb now because of RH 7.3+ problems.
194 See http://bugs.php.net/bug.php?id=20048&edit=2
197 Fixed a typo, 1852 changed to 1582! This means that pre-1852 dates
198 are now correctly handled.
202 Leap year checking differs under Julian calendar (pre 1582). Also
203 leap year code optimized by checking for most common case first.
205 We also handle month overflow correctly in mktime (eg month set to 13).
207 Day overflow for less than one month's days is supported.
211 Gregorian correction handled. In PHP5, we might throw an error if
212 mktime uses invalid dates around 5-14 Oct 1582. Released with ADOdb 3.10.
213 Added limbo 5-14 Oct 1582 check, when we set to 15 Oct 1582.
217 Fixed some more month problems due to gmt issues. Added constant ADODB_DATE_VERSION.
218 Fixed calculation of days since start of year for <1970.
222 Changed _adodb_getdate() to inline leap year checking for better performance.
223 Fixed problem with time-zones west of GMT +0000.
227 First implementation.
236 define('ADODB_DATE_VERSION', 0.12);
239 We check for Windows as only +ve ints are accepted as dates on Windows.
241 Apparently this problem happens also with Linux, RH 7.3 and later!
243 glibc-2.2.5-34 and greater has been changed to return -1 for dates <
244 1970. This used to work. The problem exists with RedHat 7.3 and 8.0
245 echo (mktime(0, 0, 0, 1, 1, 1960)); // prints -1
248 http://bugs.php.net/bug.php?id=20048&edit=2
249 http://lists.debian.org/debian-glibc/2002/debian-glibc-200205/msg00010.html
252 if (!defined('ADODB_ALLOW_NEGATIVE_TS')) define('ADODB_NO_NEGATIVE_TS', 1);
254 function adodb_date_test_date($y1, $m)
257 $t = adodb_mktime(0, 0, 0, $m, 13, $y1);
258 if ("$y1-$m-13 00:00:00" != adodb_date('Y-n-d H:i:s', $t)) {
259 print "<b>$y1 error</b><br>";
268 function adodb_date_test()
271 error_reporting(E_ALL);
272 print "<h4>Testing adodb_date and adodb_mktime. version=" . ADODB_DATE_VERSION . "</h4>";
276 // This flag disables calling of PHP native functions, so we can properly test the code
277 if (!defined('ADODB_TEST_DATES')) define('ADODB_TEST_DATES', 1);
279 $t = adodb_mktime(0, 0, 0, 6, 1, 2102);
280 if (!(adodb_date('Y-m-d', $t) == '2102-06-01')) print 'Error in ' . adodb_date('Y-m-d', $t) . '<br>';
282 $t = adodb_mktime(0, 0, 0, 2, 1, 2102);
283 if (!(adodb_date('Y-m-d', $t) == '2102-02-01')) print 'Error in ' . adodb_date('Y-m-d', $t) . '<br>';
286 print "<p>Testing gregorian <=> julian conversion<p>";
287 $t = adodb_mktime(0, 0, 0, 10, 11, 1492);
288 //http://www.holidayorigins.com/html/columbus_day.html - Friday check
289 if (!(adodb_date('D Y-m-d', $t) == 'Fri 1492-10-11')) print 'Error in Columbus landing<br>';
291 $t = adodb_mktime(0, 0, 0, 2, 29, 1500);
292 if (!(adodb_date('Y-m-d', $t) == '1500-02-29')) print 'Error in julian leap years<br>';
294 $t = adodb_mktime(0, 0, 0, 2, 29, 1700);
295 if (!(adodb_date('Y-m-d', $t) == '1700-03-01')) print 'Error in gregorian leap years<br>';
297 print adodb_mktime(0, 0, 0, 10, 4, 1582) . ' ';
298 print adodb_mktime(0, 0, 0, 10, 15, 1582);
299 $diff = (adodb_mktime(0, 0, 0, 10, 15, 1582) - adodb_mktime(0, 0, 0, 10, 4, 1582));
300 if ($diff != 3600 * 24) print " <b>Error in gregorian correction = " . ($diff / 3600 / 24) . " days </b><br>";
302 print " 15 Oct 1582, Fri=" . (adodb_dow(1582, 10, 15) == 5 ? 'Fri' : '<b>Error</b>') . "<br>";
303 print " 4 Oct 1582, Thu=" . (adodb_dow(1582, 10, 4) == 4 ? 'Thu' : '<b>Error</b>') . "<br>";
305 print "<p>Testing overflow<p>";
307 $t = adodb_mktime(0, 0, 0, 3, 33, 1965);
308 if (!(adodb_date('Y-m-d', $t) == '1965-04-02')) print 'Error in day overflow 1 <br>';
309 $t = adodb_mktime(0, 0, 0, 4, 33, 1971);
310 if (!(adodb_date('Y-m-d', $t) == '1971-05-03')) print 'Error in day overflow 2 <br>';
311 $t = adodb_mktime(0, 0, 0, 1, 60, 1965);
312 if (!(adodb_date('Y-m-d', $t) == '1965-03-01')) print 'Error in day overflow 3 ' . adodb_date('Y-m-d', $t) . ' <br>';
313 $t = adodb_mktime(0, 0, 0, 12, 32, 1965);
314 if (!(adodb_date('Y-m-d', $t) == '1966-01-01')) print 'Error in day overflow 4 ' . adodb_date('Y-m-d', $t) . ' <br>';
315 $t = adodb_mktime(0, 0, 0, 12, 63, 1965);
316 if (!(adodb_date('Y-m-d', $t) == '1966-02-01')) print 'Error in day overflow 5 ' . adodb_date('Y-m-d', $t) . ' <br>';
317 $t = adodb_mktime(0, 0, 0, 13, 3, 1965);
318 if (!(adodb_date('Y-m-d', $t) == '1966-01-03')) print 'Error in mth overflow 1 <br>';
320 print "Testing 2-digit => 4-digit year conversion<p>";
321 if (adodb_year_digit_check(00) != 2000) print "Err 2-digit 2000<br>";
322 if (adodb_year_digit_check(10) != 2010) print "Err 2-digit 2010<br>";
323 if (adodb_year_digit_check(20) != 2020) print "Err 2-digit 2020<br>";
324 if (adodb_year_digit_check(30) != 2030) print "Err 2-digit 2030<br>";
325 if (adodb_year_digit_check(40) != 1940) print "Err 2-digit 1940<br>";
326 if (adodb_year_digit_check(50) != 1950) print "Err 2-digit 1950<br>";
327 if (adodb_year_digit_check(90) != 1990) print "Err 2-digit 1990<br>";
329 // Test string formating
330 print "<p>Testing date formating</p>";
331 $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\C822 r s t U w y Y z Z 2003';
333 $s2 = adodb_date($fmt, 0);
335 print " date() 0 failed<br>$s1<br>$s2<br>";
338 for ($i = 100; --$i > 0;) {
340 $ts = 3600.0 * ((rand() % 60000) + (rand() % 60000)) + (rand() % 60000);
341 $s1 = date($fmt, $ts);
342 $s2 = adodb_date($fmt, $ts);
343 //print "$s1 <br>$s2 <p>";
344 $pos = strcmp($s1, $s2);
346 if (($s1) != ($s2)) {
347 for ($j = 0, $k = strlen($s1); $j < $k; $j++) {
348 if ($s1[$j] != $s2[$j]) {
349 print substr($s1, $j) . ' ';
353 print "<b>Error date(): $ts<br><pre>
354 \"$s1\" (date len=" . strlen($s1) . ")
355 \"$s2\" (adodb_date len=" . strlen($s2) . ")</b></pre><br>";
360 $a2 = adodb_getdate($ts);
361 $rez = array_diff($a1, $a2);
362 if (sizeof($rez) > 0) {
363 print "<b>Error getdate() $ts</b><br>";
372 // Test generation of dates outside 1901-2038
373 print "<p>Testing random dates between 100 and 4000</p>";
374 adodb_date_test_date(100, 1);
375 for ($i = 100; --$i >= 0;) {
376 $y1 = 100 + rand(0, 1970 - 100);
378 adodb_date_test_date($y1, $m);
380 $y1 = 3000 - rand(0, 3000 - 1970);
381 adodb_date_test_date($y1, $m);
384 $start = 1960 + rand(0, 10);
386 $i = 365.25 * 86400 * ($start - 1970);
387 $offset = 36000 + rand(10000, 60000);
388 $max = 365 * $yrs * 86400;
391 // we generate a timestamp, convert it to a date, and convert it back to a timestamp
392 // and check if the roundtrip broke the original timestamp value.
393 print "Testing $start to " . ($start + $yrs) . ", or $max seconds, offset=$offset: ";
395 for ($max += $i; $i < $max; $i += $offset) {
396 $ret = adodb_date('m,d,Y,H,i,s', $i);
397 $arr = explode(',', $ret);
398 if ($lastyear != $arr[2]) {
403 $newi = adodb_mktime($arr[3], $arr[4], $arr[5], $arr[0], $arr[1], $arr[2]);
405 print "Error at $i, adodb_mktime returned $newi ($ret)";
411 if (!$fail) print "<p>Passed !</p>";
412 else print "<p><b>Failed</b> :-(</p>";
416 Returns day of week, 0 = Sunday,... 6=Saturday.
417 Algorithm from PEAR::Date_Calc
419 function adodb_dow($year, $month, $day)
422 Pope Gregory removed 10 days - October 5 to October 14 - from the year 1582 and
423 proclaimed that from that time onwards 3 days would be dropped from the calendar
426 Thursday, October 4, 1582 (Julian) was followed immediately by Friday, October 15, 1582 (Gregorian).
430 ($year == 1582 && ($month < 10 || ($month == 10 && $day < 15)))
431 ) $greg_correction = 3;
433 $greg_correction = 0;
435 $greg_correction = 0;
444 $day = (floor((13 * $month - 1) / 5) +
445 $day + ($year % 100) +
446 floor(($year % 100) / 4) +
447 floor(($year / 100) / 4) - 2 *
448 floor($year / 100) + 77);
450 return (($day - 7 * floor($day / 7))) + $greg_correction;
455 Checks for leap year, returns true if it is. No 2-digit year check. Also
456 handles julian calendar correctly.
458 function _adodb_is_leap_year($year)
460 if ($year % 4 != 0) return false;
462 if ($year % 400 == 0) {
464 // if gregorian calendar (>1582), century not-divisible by 400 is not leap
465 } elseif ($year > 1582 && $year % 100 == 0) {
473 checks for leap year, returns true if it is. Has 2-digit year check
475 function adodb_is_leap_year($year)
477 return _adodb_is_leap_year(adodb_year_digit_check($year));
481 Fix 2-digit years. Works for any century.
482 Assumes that if 2-digit is more than 30 years in future, then previous century.
484 function adodb_year_digit_check($y)
488 $yr = (integer)date("Y");
489 $century = (integer)($yr / 100);
491 if ($yr % 100 > 50) {
499 // if 2-digit year is less than 30 years in future, set it to this century
500 // otherwise if more than 30 years in future, then we set 2-digit year to the prev century.
501 if (($y + $c1) < $yr + 30) $y = $y + $c1;
502 else $y = $y + $c0 * 100;
508 get local time zone offset from GMT
510 function adodb_get_gmt_diff()
513 if (isset($TZ)) return $TZ;
515 $TZ = mktime(0, 0, 0, 1, 2, 1970, 0) - gmmktime(0, 0, 0, 1, 2, 1970, 0);
520 Returns an array with date info.
522 function adodb_getdate($d = false, $fast = false)
524 if ($d === false) return getdate();
525 if (!defined('ADODB_TEST_DATES')) {
526 if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
527 if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
531 return _adodb_getdate($d);
535 Low-level function that returns the getdate() array. We have a special
536 $fast flag, which if set to true, will return fewer array values,
537 and is much faster as it does not calculate dow, etc.
539 function _adodb_getdate($origd = false, $fast = false, $is_gmt = false)
541 $d = $origd - ($is_gmt ? 0 : adodb_get_gmt_diff());
547 if ($d < -12219321600) $d -= 86400 * 10; // if 15 Oct 1582 or earlier, gregorian correction
549 $_month_table_normal = array("", 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
550 $_month_table_leaf = array("", 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
554 // The valid range of a 32bit signed timestamp is typically from
555 // Fri, 13 Dec 1901 20:45:54 GMT to Tue, 19 Jan 2038 03:14:07 GMT
556 for ($a = 1970; --$a >= 0;) {
559 if ($leaf = _adodb_is_leap_year($a)) {
560 $d += $_day_power * 366;
562 $d += $_day_power * 365;
569 $secsInYear = 86400 * ($leaf ? 366 : 365) + $lastd;
572 $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
573 for ($a = 13; --$a > 0;) {
575 $d += $mtab[$a] * $_day_power;
584 $day = $ndays + ceil(($d + 1) / ($_day_power));
586 $d += ($ndays - $day + 1) * $_day_power;
587 $hour = floor($d / $_hour_power);
591 for ($a = 1970; ; $a++) {
594 if ($leaf = _adodb_is_leap_year($a)) {
595 $d -= $_day_power * 366;
597 $d -= $_day_power * 365;
603 $secsInYear = $lastd;
605 $mtab = ($leaf) ? $_month_table_leaf : $_month_table_normal;
606 for ($a = 1; $a <= 12; $a++) {
608 $d -= $mtab[$a] * $_day_power;
616 $day = ceil(($d + 1) / $_day_power);
617 $d = $d - ($day - 1) * $_day_power;
618 $hour = floor($d / $_hour_power);
621 $d -= $hour * $_hour_power;
622 $min = floor($d / $_min_power);
623 $secs = $d - $min * $_min_power;
632 'yday' => floor($secsInYear / $_day_power),
639 $dow = adodb_dow($year, $month, $day);
649 'yday' => floor($secsInYear / $_day_power),
650 'weekday' => gmdate('l', $_day_power * (3 + $dow)),
651 'month' => gmdate('F', mktime(0, 0, 0, $month, 2, 1971)),
656 function adodb_gmdate($fmt, $d = false)
658 return adodb_date($fmt, $d, true);
661 function adodb_date2($fmt, $d = false, $is_gmt = false)
665 "|^([0-9]{4})[-/\.]?([0-9]{1,2})[-/\.]?([0-9]{1,2})[ -]?(([0-9]{1,2}):?([0-9]{1,2}):?([0-9\.]{1,4}))?|",
667 ) return adodb_date($fmt, false, $is_gmt);
669 if ($rr[1] <= 100 && $rr[2] <= 1) return adodb_date($fmt, false, $is_gmt);
672 if (!isset($rr[5])) $d = adodb_mktime(0, 0, 0, $rr[2], $rr[3], $rr[1]);
673 else $d = @adodb_mktime($rr[5], $rr[6], $rr[7], $rr[2], $rr[3], $rr[1]);
676 return adodb_date($fmt, $d, $is_gmt);
680 Return formatted date based on timestamp $d
682 function adodb_date($fmt, $d = false, $is_gmt = false)
684 if ($d === false) return date($fmt);
685 if (!defined('ADODB_TEST_DATES')) {
686 if ((abs($d) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
687 if (!defined('ADODB_NO_NEGATIVE_TS') || $d >= 0) // if windows, must be +ve integer
688 return @date($fmt, $d);
693 $arr = _adodb_getdate($d, true, $is_gmt);
694 $year = $arr['year'];
695 $month = $arr['mon'];
697 $hour = $arr['hours'];
698 $min = $arr['minutes'];
699 $secs = $arr['seconds'];
705 at this point, we have the following integer vars to manipulate:
706 $year, $month, $day, $hour, $min, $secs
708 for ($i = 0; $i < $max; $i++) {
715 $dates .= $arr['leap'] ? '1' : '0';
717 case 'r': // Thu, 21 Dec 2000 16:01:07 +0200
719 $dates .= gmdate('D', $_day_power * (3 + adodb_dow($year, $month, $day))) . ', '
720 . ($day < 10 ? ' ' . $day : $day) . ' ' . date('M', mktime(0, 0, 0, $month, 2, 1971)) . ' ' . $year . ' ';
722 if ($hour < 10) $dates .= '0' . $hour; else $dates .= $hour;
724 if ($min < 10) $dates .= ':0' . $min; else $dates .= ':' . $min;
726 if ($secs < 10) $dates .= ':0' . $secs; else $dates .= ':' . $secs;
728 $gmt = adodb_get_gmt_diff();
729 $dates .= sprintf(' %s%04d', ($gmt < 0) ? '+' : '-', abs($gmt) / 36);
736 $dates .= substr($year, strlen($year) - 2, 2);
740 if ($month < 10) $dates .= '0' . $month; else $dates .= $month;
743 $dates .= ($month + 3) >> 2;
749 $dates .= date('M', mktime(0, 0, 0, $month, 2, 1971));
752 $dates .= date('F', mktime(0, 0, 0, $month, 2, 1971));
756 $dates .= $arr['ndays'];
759 $dates .= $arr['yday'];
762 $dates .= adodb_dow($year, $month, $day);
765 $dates .= gmdate('l', $_day_power * (3 + adodb_dow($year, $month, $day)));
768 $dates .= gmdate('D', $_day_power * (3 + adodb_dow($year, $month, $day)));
774 if ($day < 10) $dates .= '0' . $day; else $dates .= $day;
778 if ($d10 == 1) $dates .= 'st';
779 else if ($d10 == 2) $dates .= 'nd';
780 else if ($d10 == 3) $dates .= 'rd';
786 $dates .= ($is_gmt) ? 0 : -adodb_get_gmt_diff();
789 $gmt = ($is_gmt) ? 0 : adodb_get_gmt_diff();
790 $dates .= sprintf('%s%04d', ($gmt < 0) ? '+' : '-', abs($gmt) / 36);
794 if ($hour < 10) $dates .= '0' . $hour;
795 else $dates .= $hour;
798 if ($hour > 12) $hh = $hour - 12;
800 if ($hour == 0) $hh = '12';
804 if ($hh < 10) $dates .= '0' . $hh;
813 if ($hour > 12) $hh = $hour - 12;
815 if ($hour == 0) $hh = '12';
822 if ($min < 10) $dates .= '0' . $min; else $dates .= $min;
829 if ($secs < 10) $dates .= '0' . $secs; else $dates .= $secs;
832 // Note 00:00 to 11:59 is AM, while 12:00 to 23:59 is PM
834 if ($hour >= 12) $dates .= 'pm';
838 if ($hour >= 12) $dates .= 'PM';
847 if ($i < $max) $dates .= $fmt[$i];
855 Returns a timestamp given a GMT/UTC time.
856 Note that $is_dst is not implemented and is ignored.
858 function adodb_gmmktime($hr, $min, $sec, $mon, $day, $year, $is_dst = false)
860 return adodb_mktime($hr, $min, $sec, $mon, $day, $year, $is_dst, true);
864 Return a timestamp given a local time. Originally by jackbbs.
865 Note that $is_dst is not implemented and is ignored.
867 function adodb_mktime($hr, $min, $sec, $mon, $day, $year, $is_dst = false, $is_gmt = false)
869 if (!defined('ADODB_TEST_DATES')) {
870 // for windows, we don't check 1970 because with timezone differences,
871 // 1 Jan 1970 could generate negative timestamp, which is illegal
872 if (!defined('ADODB_NO_NEGATIVE_TS') || ($year >= 1971))
873 if (1901 < $year && $year < 2038)
874 return @mktime($hr, $min, $sec, $mon, $day, $year);
877 $gmt_different = ($is_gmt) ? 0 : adodb_get_gmt_diff();
884 $year = intval($year);
886 $year = adodb_year_digit_check($year);
889 $y = floor($mon / 12);
898 $_month_table_normal = array("", 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
899 $_month_table_leaf = array("", 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
903 for ($a = 1970; $a <= $year; $a++) {
904 $leaf = _adodb_is_leap_year($a);
906 $loop_table = $_month_table_leaf;
909 $loop_table = $_month_table_normal;
913 $_total_date += $_add_date;
915 for ($b = 1; $b < $mon; $b++) {
916 $_total_date += $loop_table[$b];
920 $_total_date += $day - 1;
921 $ret = $_total_date * $_day_power + $hr * $_hour_power + $min * $_min_power + $sec + $gmt_different;
924 for ($a = 1969; $a >= $year; $a--) {
925 $leaf = _adodb_is_leap_year($a);
927 $loop_table = $_month_table_leaf;
930 $loop_table = $_month_table_normal;
934 $_total_date += $_add_date;
936 for ($b = 12; $b > $mon; $b--) {
937 $_total_date += $loop_table[$b];
941 $_total_date += $loop_table[$mon] - $day;
943 $_day_time = $hr * $_hour_power + $min * $_min_power + $sec;
944 $_day_time = $_day_power - $_day_time;
945 $ret = -($_total_date * $_day_power + $_day_time - $gmt_different);
946 if ($ret < -12220185600) $ret += 10 * 86400; // if earlier than 5 Oct 1582 - gregorian correction
947 else if ($ret < -12219321600) $ret = -12219321600; // if in limbo, reset to 15 Oct 1582.
949 //print " dmy=$day/$mon/$year $hr:$min:$sec => " .$ret;