OSDN Git Service

touched all Tcl files to ease next import.
[pf3gnuchains/pf3gnuchains3x.git] / tcl / unix / tclUnixTime.c
1 /* 
2  * tclUnixTime.c --
3  *
4  *      Contains Unix specific versions of Tcl functions that
5  *      obtain time values from the operating system.
6  *
7  * Copyright (c) 1995 Sun Microsystems, Inc.
8  *
9  * See the file "license.terms" for information on usage and redistribution
10  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11  *
12  * RCS: @(#) $Id$
13  */
14
15 #include "tclInt.h"
16 #include "tclPort.h"
17 #define TM_YEAR_BASE 1900
18 #define IsLeapYear(x)   ((x % 4 == 0) && (x % 100 != 0 || x % 400 == 0))
19 \f
20 /*
21  *-----------------------------------------------------------------------------
22  *
23  * TclpGetSeconds --
24  *
25  *      This procedure returns the number of seconds from the epoch.  On
26  *      most Unix systems the epoch is Midnight Jan 1, 1970 GMT.
27  *
28  * Results:
29  *      Number of seconds from the epoch.
30  *
31  * Side effects:
32  *      None.
33  *
34  *-----------------------------------------------------------------------------
35  */
36
37 unsigned long
38 TclpGetSeconds()
39 {
40     return time((time_t *) NULL);
41 }
42 \f
43 /*
44  *-----------------------------------------------------------------------------
45  *
46  * TclpGetClicks --
47  *
48  *      This procedure returns a value that represents the highest resolution
49  *      clock available on the system.  There are no garantees on what the
50  *      resolution will be.  In Tcl we will call this value a "click".  The
51  *      start time is also system dependant.
52  *
53  * Results:
54  *      Number of clicks from some start time.
55  *
56  * Side effects:
57  *      None.
58  *
59  *-----------------------------------------------------------------------------
60  */
61
62 unsigned long
63 TclpGetClicks()
64 {
65     unsigned long now;
66 #ifdef NO_GETTOD
67     struct tms dummy;
68 #else
69     struct timeval date;
70     struct timezone tz;
71 #endif
72
73 #ifdef NO_GETTOD
74     now = (unsigned long) times(&dummy);
75 #else
76     gettimeofday(&date, &tz);
77     now = date.tv_sec*1000000 + date.tv_usec;
78 #endif
79
80     return now;
81 }
82 \f
83 /*
84  *----------------------------------------------------------------------
85  *
86  * TclpGetTimeZone --
87  *
88  *      Determines the current timezone.  The method varies wildly
89  *      between different platform implementations, so its hidden in
90  *      this function.
91  *
92  * Results:
93  *      The return value is the local time zone, measured in
94  *      minutes away from GMT (-ve for east, +ve for west).
95  *
96  * Side effects:
97  *      None.
98  *
99  *----------------------------------------------------------------------
100  */
101
102 int
103 TclpGetTimeZone (currentTime)
104     unsigned long  currentTime;
105 {
106     /*
107      * Determine how a timezone is obtained from "struct tm".  If there is no
108      * time zone in this struct (very lame) then use the timezone variable.
109      * This is done in a way to make the timezone variable the method of last
110      * resort, as some systems have it in addition to a field in "struct tm".
111      * The gettimeofday system call can also be used to determine the time
112      * zone.
113      */
114     
115 #if defined(HAVE_TM_TZADJ)
116 #   define TCL_GOT_TIMEZONE
117     time_t      curTime = (time_t) currentTime;
118     struct tm  *timeDataPtr = localtime(&curTime);
119     int         timeZone;
120
121     timeZone = timeDataPtr->tm_tzadj  / 60;
122     if (timeDataPtr->tm_isdst) {
123         timeZone += 60;
124     }
125     
126     return timeZone;
127 #endif
128
129 #if defined(HAVE_TM_GMTOFF) && !defined (TCL_GOT_TIMEZONE)
130 #   define TCL_GOT_TIMEZONE
131     time_t     curTime = (time_t) currentTime;
132     struct tm *timeDataPtr = localtime(&curTime);
133     int        timeZone;
134
135     timeZone = -(timeDataPtr->tm_gmtoff / 60);
136     if (timeDataPtr->tm_isdst) {
137         timeZone += 60;
138     }
139     
140     return timeZone;
141 #endif
142
143 #if defined(USE_DELTA_FOR_TZ)
144 #define TCL_GOT_TIMEZONE 1
145     /*
146      * This hack replaces using global var timezone or gettimeofday
147      * in situations where they are buggy such as on AIX when libbsd.a
148      * is linked in.
149      */
150
151     int timeZone;
152     time_t tt;
153     struct tm *stm;
154     tt = 849268800L;      /*    1996-11-29 12:00:00  GMT */
155     stm = localtime(&tt); /* eg 1996-11-29  6:00:00  CST6CDT */
156     /* The calculation below assumes a max of +12 or -12 hours from GMT */
157     timeZone = (12 - stm->tm_hour)*60 + (0 - stm->tm_min);
158     return timeZone;  /* eg +360 for CST6CDT */
159 #endif
160
161     /*
162      * Must prefer timezone variable over gettimeofday, as gettimeofday does
163      * not return timezone information on many systems that have moved this
164      * information outside of the kernel.
165      */
166     
167 #if defined(HAVE_TIMEZONE_VAR) && !defined (TCL_GOT_TIMEZONE)
168 #   define TCL_GOT_TIMEZONE
169     static int setTZ = 0;
170 #ifdef TCL_THREADS
171     static Tcl_Mutex tzMutex;
172 #endif
173     int        timeZone;
174
175     Tcl_MutexLock(&tzMutex);
176     if (!setTZ) {
177         tzset();
178         setTZ = 1;
179     }
180     Tcl_MutexUnlock(&tzMutex);
181
182     /*
183      * Note: this is not a typo in "timezone" below!  See tzset
184      * documentation for details.
185      */
186
187     timeZone = timezone / 60;
188
189     return timeZone;
190 #endif
191
192 #if !defined(NO_GETTOD) && !defined (TCL_GOT_TIMEZONE)
193 #   define TCL_GOT_TIMEZONE
194     struct timeval  tv;
195     struct timezone tz;
196     int timeZone;
197
198     gettimeofday(&tv, &tz);
199     timeZone = tz.tz_minuteswest;
200     if (tz.tz_dsttime) {
201         timeZone += 60;
202     }
203     
204     return timeZone;
205 #endif
206
207 #ifndef TCL_GOT_TIMEZONE
208     /*
209      * Cause compile error, we don't know how to get timezone.
210      */
211     error: autoconf did not figure out how to determine the timezone. 
212 #endif
213
214 }
215 \f
216 /*
217  *----------------------------------------------------------------------
218  *
219  * TclpGetTime --
220  *
221  *      Gets the current system time in seconds and microseconds
222  *      since the beginning of the epoch: 00:00 UCT, January 1, 1970.
223  *
224  * Results:
225  *      Returns the current time in timePtr.
226  *
227  * Side effects:
228  *      None.
229  *
230  *----------------------------------------------------------------------
231  */
232
233 void
234 TclpGetTime(timePtr)
235     Tcl_Time *timePtr;          /* Location to store time information. */
236 {
237     struct timeval tv;
238     struct timezone tz;
239     
240     (void) gettimeofday(&tv, &tz);
241     timePtr->sec = tv.tv_sec;
242     timePtr->usec = tv.tv_usec;
243 }
244 \f
245 /*
246  *----------------------------------------------------------------------
247  *
248  * TclpGetDate --
249  *
250  *      This function converts between seconds and struct tm.  If
251  *      useGMT is true, then the returned date will be in Greenwich
252  *      Mean Time (GMT).  Otherwise, it will be in the local time zone.
253  *
254  * Results:
255  *      Returns a static tm structure.
256  *
257  * Side effects:
258  *      None.
259  *
260  *----------------------------------------------------------------------
261  */
262
263 struct tm *
264 TclpGetDate(time, useGMT)
265     TclpTime_t time;
266     int useGMT;
267 {
268     CONST time_t *tp = (CONST time_t *)time;
269
270     if (useGMT) {
271         return gmtime(tp);
272     } else {
273         return localtime(tp);
274     }
275 }
276 \f
277 /*
278  *----------------------------------------------------------------------
279  *
280  * TclpStrftime --
281  *
282  *      On Unix, we can safely call the native strftime implementation.
283  *
284  * Results:
285  *      The normal strftime result.
286  *
287  * Side effects:
288  *      None.
289  *
290  *----------------------------------------------------------------------
291  */
292
293 size_t
294 TclpStrftime(s, maxsize, format, t)
295     char *s;
296     size_t maxsize;
297     CONST char *format;
298     CONST struct tm *t;
299 {
300     if (format[0] == '%' && format[1] == 'Q') {
301         /* Format as a stardate */
302         sprintf(s, "Stardate %2d%03d.%01d",
303                 (((t->tm_year + TM_YEAR_BASE) + 377) - 2323),
304                 (((t->tm_yday + 1) * 1000) /
305                         (365 + IsLeapYear((t->tm_year + TM_YEAR_BASE)))),
306                 (((t->tm_hour * 60) + t->tm_min)/144));
307         return(strlen(s));
308     }
309     return strftime(s, maxsize, format, t);
310 }