1 /* Copyright (C) 1993 Free Software Foundation, Inc.
2 Contributed by Noel Cragg (noel@cs.oberlin.edu).
4 This file is part of the GNU C Library.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If
18 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19 Cambridge, MA 02139, USA. */
22 #if defined (CONFIG_BROKETS)
23 /* We use <config.h> instead of "config.h" so that a compilation
24 using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
25 (which it would do because it found this file in $srcdir). */
32 #include <sys/types.h> /* Some systems define `time_t' here. */
37 /* Nonzero if YEAR is a leap year (every 4 years,
38 except every 100th isn't, and every 400th is). */
39 #define __isleap(year) \
40 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
44 /* How many days are in each month. */
45 const unsigned short int __mon_lengths[2][12] =
48 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
50 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
54 /* After testing this, the maximum number of iterations that I had on
55 any number that I tried was 3! Not bad.
57 mktime converts a `struct tm' (broken-down local time) into a `time_t';
58 it is the opposite of localtime. It is possible to put the following
59 values out of range and have mktime compensate: tm_sec, tm_min, tm_hour,
60 tm_mday, tm_year. The other values in the structure are ignored. */
64 int debugging_enabled = 0;
66 /* Print the values in a `struct tm'. */
71 printf ("%d/%d/%d %d:%d:%d (%s) yday:%d f:%d o:%ld",
91 unsigned long int v1, v2;
96 #define doit(x, secs) \
103 else if (t1->x > t2->x) \
107 doit (tm_year, 31536000); /* Okay, not all years have 365 days. */
108 doit (tm_mon, 2592000); /* Okay, not all months have 30 days. */
109 doit (tm_mday, 86400);
110 doit (tm_hour, 3600);
118 /* We need this DIFF_FLAG business because it is forseeable that the
119 distance may be zero when, in actuality, the two structures are
120 different. This is usually the case when the dates are 366 days
121 apart and one of the years is a leap year. */
123 if (distance == 0 && diff_flag)
124 distance = 86400 * diff_flag;
130 /* Modified binary search -- make intelligent guesses as to where the time
131 might lie along the timeline, assuming that our target time lies a
132 linear distance (w/o considering time jumps of a particular region).
134 Assume that time does not fluctuate at all along the timeline -- e.g.,
135 assume that a day will always take 86400 seconds, etc. -- and come up
136 with a hypothetical value for the time_t representation of the struct tm
137 TARGET, in relation to the guess variable -- it should be pretty close! */
151 guess_tm = localtime (&guess);
154 if (debugging_enabled)
156 printf ("guess %d == ", guess);
162 /* Are we on the money? */
163 distance = dist_tm (target, guess_tm);
165 } while (distance != 0);
170 /* Since this function will call localtime many times (and the user might
171 be passing their `struct tm *' right from localtime, let's make a copy
172 for ourselves and run the search on the copy.
174 Also, we have to normalize the timeptr because it's possible to call mktime
175 with values that are out of range for a specific item (like 30th Feb). */
181 struct tm private_mktime_struct_tm; /* Yes, users can get a ptr to this. */
185 me = &private_mktime_struct_tm;
189 #define normalize(foo,x,y,bar); \
190 while (me->foo < x) \
193 me->foo = (y - (x - me->foo)); \
195 while (me->foo > y) \
198 me->foo = (x + (me->foo - y)); \
201 normalize (tm_sec, 0, 59, tm_min);
202 normalize (tm_min, 0, 59, tm_hour);
203 normalize (tm_hour, 0, 23, tm_mday);
205 /* Do the month first, so day range can be found. */
206 normalize (tm_mon, 0, 11, tm_year);
207 normalize (tm_mday, 1,
208 __mon_lengths[__isleap (me->tm_year)][me->tm_mon],
211 /* Do the month again, because the day may have pushed it out of range. */
212 normalize (tm_mon, 0, 11, tm_year);
214 /* Do day again, because month may have changed the range. */
215 normalize (tm_mday, 1,
216 __mon_lengths[__isleap (me->tm_year)][me->tm_mon],
220 if (debugging_enabled)
222 printf ("After normalizing: ");
228 result = search (me);
249 printf ("starting long test...\n");
251 for (q = 10000000; q < 1000000000; q++)
253 struct tm *tm = localtime (&q);
254 if ((q % 10000) == 0) { printf ("%ld\n", q); fflush (stdout); }
255 if (q != my_mktime (tm))
256 { printf ("failed for %ld\n", q); fflush (stdout); }
259 printf ("test finished\n");
266 printf ("wrong # of args\n");
270 debugging_enabled = 1; /* we want to see the info */
275 printf ("Time: %d %s\n", time, ctime (&time));
277 tmptr = localtime (&time);
278 printf ("localtime returns: ");
281 printf ("mktime: %d\n\n", mktime (tmptr));
285 tmptr->tm_hour -= 20;
286 tmptr->tm_mday -= 20;
288 tmptr->tm_year -= 20;
289 tmptr->tm_gmtoff -= 20000; /* this has no effect! */
290 tmptr->tm_zone = NULL; /* nor does this! */
291 tmptr->tm_isdst = -1;
293 printf ("changed ranges: ");
297 result_time = mktime (tmptr);
298 printf ("\n mine: %d\n", result_time);