[3ae31e9] | 1 | /*
|
---|
| 2 | =============================================================================
|
---|
| 3 | lctime.c -- a Unix(tm)-like time and date package
|
---|
| 4 | Version 1 -- 1988-01-14 -- D.N. Lynx Crowe
|
---|
| 5 |
|
---|
| 6 | These are similar in function to the Unix functions, but are
|
---|
| 7 | able to be used in re-entrant code.
|
---|
| 8 | =============================================================================
|
---|
| 9 | */
|
---|
| 10 |
|
---|
| 11 | #include "stddefs.h"
|
---|
| 12 | #include "time.h"
|
---|
| 13 |
|
---|
| 14 | #define void int /* define to handle lack of 'void's */
|
---|
| 15 |
|
---|
| 16 | #define HASENV 0 /* non-zero if getenv() is available */
|
---|
| 17 |
|
---|
| 18 | #if HASENV
|
---|
| 19 | extern char *getenv();
|
---|
| 20 | #endif
|
---|
| 21 |
|
---|
| 22 | long timezn = 8*60*60; /* PST offset from GMT */
|
---|
| 23 | int daylite = 1; /* daylight savings time = ON */
|
---|
| 24 | char *ltzname[] = {"PST", "PDT"};
|
---|
| 25 |
|
---|
| 26 | /*
|
---|
| 27 | =============================================================================
|
---|
| 28 | These routines convert time as follows:
|
---|
| 29 |
|
---|
| 30 | The epoch is 0000 Jan 1 1970 GMT.
|
---|
| 31 | The argument time is in seconds since then.
|
---|
| 32 |
|
---|
| 33 | struct tm *
|
---|
| 34 | lcltime(tim, tmsp)
|
---|
| 35 | long *tim;
|
---|
| 36 | struct tm *tmsp;
|
---|
| 37 |
|
---|
| 38 | returns a pointer to a filled in structure containing:
|
---|
| 39 |
|
---|
| 40 | tm_sec seconds (0..59)
|
---|
| 41 | tm_min minutes (0..59)
|
---|
| 42 | tm_hour hours (0..23)
|
---|
| 43 | tm_mday day of month (1..31)
|
---|
| 44 | tm_mon month (0..11)
|
---|
| 45 | tm_year year - 1900
|
---|
| 46 | tm_wday weekday (0..6, Sun is 0)
|
---|
| 47 | tm_yday day of the year
|
---|
| 48 | tm_dst daylight savings time flag
|
---|
| 49 |
|
---|
| 50 | The routine corrects for daylight savings time and will work in
|
---|
| 51 | any time zone provided "timezn" is adjusted to the difference
|
---|
| 52 | between Greenwich and local standard time (measured in seconds).
|
---|
| 53 |
|
---|
| 54 | In places like Michigan "daylite" must be initialized to 0
|
---|
| 55 | to prevent the conversion to daylight time.
|
---|
| 56 |
|
---|
| 57 | There is a table which accounts for the peculiarities
|
---|
| 58 | undergone by daylight savings time in 1974-1975.
|
---|
| 59 |
|
---|
| 60 | The routine does not work in Saudi Arabia,
|
---|
| 61 | which runs on Solar time.
|
---|
| 62 |
|
---|
| 63 | char *
|
---|
| 64 | latime(t, cbuf)
|
---|
| 65 | struct tm *t;
|
---|
| 66 | char *cbuf;
|
---|
| 67 |
|
---|
| 68 | Where t is produced by lcltime(), and cbuf points to a
|
---|
| 69 | character string of at least 26 bytes.
|
---|
| 70 |
|
---|
| 71 | Fills in a character string with the ascii time in the form:
|
---|
| 72 |
|
---|
| 73 | Thu Jan 01 00:00:00 1970\n\0
|
---|
| 74 | 012345678901234567890123
|
---|
| 75 | 0 1 2
|
---|
| 76 |
|
---|
| 77 | The string is terminated with a new-line and a zero byte.
|
---|
| 78 |
|
---|
| 79 | struct tm *
|
---|
| 80 | lgmtime(tim, xtime)
|
---|
| 81 | long *tim;
|
---|
| 82 | struct tm *xtime;
|
---|
| 83 |
|
---|
| 84 | Fills in a tm structure with GMT and returns a pointer to it.
|
---|
| 85 |
|
---|
| 86 | char *
|
---|
| 87 | lctime(t, tmsp, cbuf)
|
---|
| 88 | long *t;
|
---|
| 89 | struct tm *tmsp;
|
---|
| 90 | char *cbuf;
|
---|
| 91 |
|
---|
| 92 | Fills in a tm structure and a character string with the
|
---|
| 93 | current local time.
|
---|
| 94 |
|
---|
| 95 | void
|
---|
| 96 | ltzset()
|
---|
| 97 |
|
---|
| 98 | Looks for an environment variable named TZ.
|
---|
| 99 |
|
---|
| 100 | It should be in the form "ESTn" or "ESTnEDT",
|
---|
| 101 | where "n" represents a string of digits with an optional
|
---|
| 102 | negative sign (for locations east of Greenwich, England).
|
---|
| 103 |
|
---|
| 104 | If the variable is present, it will set the external
|
---|
| 105 | variables "timezn", "daylite", and "ltzname"
|
---|
| 106 | appropriately. It is called by lcltime(), and
|
---|
| 107 | may also be called explicitly by the user.
|
---|
| 108 | =============================================================================
|
---|
| 109 | */
|
---|
| 110 |
|
---|
| 111 | /* |
---|
| 112 | */
|
---|
| 113 |
|
---|
| 114 | #define dysize(A) (((A) % 4) ? 365 : 366)
|
---|
| 115 |
|
---|
| 116 | static int xdmsize[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
---|
| 117 |
|
---|
| 118 | /*
|
---|
| 119 | Daylight savings time change table:
|
---|
| 120 |
|
---|
| 121 | The following table is used for 1974 and 1975 and gives the day number
|
---|
| 122 | of the first day after the Sunday of the change.
|
---|
| 123 | */
|
---|
| 124 |
|
---|
| 125 | static struct {
|
---|
| 126 |
|
---|
| 127 | int daylb;
|
---|
| 128 | int dayle;
|
---|
| 129 |
|
---|
| 130 | } daytab[] = {
|
---|
| 131 |
|
---|
| 132 | 5, 333, /* 1974: Jan 6 - last Sun. in Nov */
|
---|
| 133 | 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */
|
---|
| 134 | };
|
---|
| 135 |
|
---|
| 136 | /* |
---|
| 137 | */
|
---|
| 138 |
|
---|
| 139 | /*
|
---|
| 140 | =============================================================================
|
---|
| 141 | ct_numb(cp, n) -- convert n to a 2 character string at cp (RJBF)
|
---|
| 142 | =============================================================================
|
---|
| 143 | */
|
---|
| 144 |
|
---|
| 145 | static char *
|
---|
| 146 | ct_numb(cp, n)
|
---|
| 147 | register char *cp;
|
---|
| 148 | int n;
|
---|
| 149 | {
|
---|
| 150 | cp++;
|
---|
| 151 |
|
---|
| 152 | if (n GE 10)
|
---|
| 153 | *cp++ = (n / 10) % 10 + '0';
|
---|
| 154 | else
|
---|
| 155 | *cp++ = ' ';
|
---|
| 156 |
|
---|
| 157 | *cp++ = n % 10 + '0';
|
---|
| 158 |
|
---|
| 159 | return(cp);
|
---|
| 160 | }
|
---|
| 161 |
|
---|
| 162 | /* |
---|
| 163 | */
|
---|
| 164 |
|
---|
| 165 | /*
|
---|
| 166 | =============================================================================
|
---|
| 167 | sunday(t, d)
|
---|
| 168 |
|
---|
| 169 | The argument d is a 0-origin day number.
|
---|
| 170 | The value is the day number of the first Sunday on or after the day.
|
---|
| 171 | =============================================================================
|
---|
| 172 | */
|
---|
| 173 |
|
---|
| 174 | static
|
---|
| 175 | int
|
---|
| 176 | sunday(t, d)
|
---|
| 177 | register struct tm *t;
|
---|
| 178 | register int d;
|
---|
| 179 | {
|
---|
| 180 | if (d GE 58)
|
---|
| 181 | d += dysize(t->tm_year) - 365;
|
---|
| 182 |
|
---|
| 183 | return(d - (d - t->tm_yday + t->tm_wday + 700) % 7);
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | /* |
---|
| 187 | */
|
---|
| 188 |
|
---|
| 189 | /*
|
---|
| 190 | =============================================================================
|
---|
| 191 | ltzset() -- set time variables based on TZ environment variable
|
---|
| 192 | =============================================================================
|
---|
| 193 | */
|
---|
| 194 |
|
---|
| 195 | void
|
---|
| 196 | ltzset()
|
---|
| 197 | {
|
---|
| 198 | register char *p, *q;
|
---|
| 199 | register int n;
|
---|
| 200 | int sign;
|
---|
| 201 |
|
---|
| 202 | #if HASENV
|
---|
| 203 |
|
---|
| 204 | if ((p = getenv("TZ")) AND *p) {
|
---|
| 205 |
|
---|
| 206 | n = 3;
|
---|
| 207 | q = ltzname[0];
|
---|
| 208 |
|
---|
| 209 | do {
|
---|
| 210 |
|
---|
| 211 | *q++ = *p ? *p++ : ' ';
|
---|
| 212 |
|
---|
| 213 | } while (--n);
|
---|
| 214 |
|
---|
| 215 | if (sign = *p EQ '-')
|
---|
| 216 | p++;
|
---|
| 217 |
|
---|
| 218 | n = 0;
|
---|
| 219 |
|
---|
| 220 | while (*p GE '0' AND *p LE '9')
|
---|
| 221 | n = (n * 10) + *p++ - '0';
|
---|
| 222 |
|
---|
| 223 | if (sign)
|
---|
| 224 | n = -n;
|
---|
| 225 |
|
---|
| 226 | timezn = ((long)(n * 60)) * 60;
|
---|
| 227 |
|
---|
| 228 | if (daylite = *p NE '\0') {
|
---|
| 229 |
|
---|
| 230 | q = ltzname[1];
|
---|
| 231 | n = 3;
|
---|
| 232 |
|
---|
| 233 | do {
|
---|
| 234 |
|
---|
| 235 | *q++ = *p ? *p++ : ' ';
|
---|
| 236 |
|
---|
| 237 | } while (--n);
|
---|
| 238 | }
|
---|
| 239 | }
|
---|
| 240 |
|
---|
| 241 | #endif
|
---|
| 242 | }
|
---|
| 243 |
|
---|
| 244 | /* |
---|
| 245 | */
|
---|
| 246 |
|
---|
| 247 | /*
|
---|
| 248 | =============================================================================
|
---|
| 249 | lgmtime(tim, xtime) -- get Greenwich Mean Time from system time
|
---|
| 250 | =============================================================================
|
---|
| 251 | */
|
---|
| 252 |
|
---|
| 253 | struct tm *
|
---|
| 254 | lgmtime(tim, xtime)
|
---|
| 255 | register long *tim;
|
---|
| 256 | register struct tm *xtime;
|
---|
| 257 | {
|
---|
| 258 | register int d0, d1, i;
|
---|
| 259 | register long hms, day;
|
---|
| 260 | int dmsize[12];
|
---|
| 261 |
|
---|
| 262 | /* break initial number into days */
|
---|
| 263 |
|
---|
| 264 | hms = *tim % 86400L;
|
---|
| 265 | day = *tim / 86400L;
|
---|
| 266 |
|
---|
| 267 | if (hms < 0) {
|
---|
| 268 |
|
---|
| 269 | hms += 86400L;
|
---|
| 270 | day -= 1;
|
---|
| 271 | }
|
---|
| 272 |
|
---|
| 273 | /* generate hours:minutes:seconds */
|
---|
| 274 |
|
---|
| 275 | xtime->tm_sec = hms % 60;
|
---|
| 276 | d1 = hms / 60;
|
---|
| 277 | xtime->tm_min = d1 % 60;
|
---|
| 278 | d1 /= 60;
|
---|
| 279 | xtime->tm_hour = d1;
|
---|
| 280 |
|
---|
| 281 | /*
|
---|
| 282 | day is the day number.
|
---|
| 283 | generate day of the week.
|
---|
| 284 | The addend is 4 mod 7 (1/1/1970 was Thursday)
|
---|
| 285 | */
|
---|
| 286 |
|
---|
| 287 | xtime->tm_wday = (day + 7340036L) % 7;
|
---|
| 288 |
|
---|
| 289 | /* year number */
|
---|
| 290 |
|
---|
| 291 | if (day GE 0)
|
---|
| 292 | for (d1 = 70; day GE dysize(d1); d1++)
|
---|
| 293 | day -= dysize(d1);
|
---|
| 294 | else
|
---|
| 295 | for (d1 = 70; day < 0; d1--)
|
---|
| 296 | day += dysize(d1 - 1);
|
---|
| 297 |
|
---|
| 298 | xtime->tm_year = d1;
|
---|
| 299 | xtime->tm_yday = d0 = day;
|
---|
| 300 |
|
---|
| 301 | /* generate month */
|
---|
| 302 |
|
---|
| 303 | for (i = 0; i < 12; i++)
|
---|
| 304 | xdmsize[i] = dmsize[i];
|
---|
| 305 |
|
---|
| 306 | if (dysize(d1) EQ 366)
|
---|
| 307 | xdmsize[1] = 29;
|
---|
| 308 | else
|
---|
| 309 | xdmsize[1] = 28;
|
---|
| 310 |
|
---|
| 311 | for (d1 = 0; d0 GE xdmsize[d1]; d1++)
|
---|
| 312 | d0 -= xdmsize[d1];
|
---|
| 313 |
|
---|
| 314 | xtime->tm_mday = d0+1;
|
---|
| 315 | xtime->tm_mon = d1;
|
---|
| 316 | xtime->tm_dst = 0;
|
---|
| 317 |
|
---|
| 318 | return(xtime);
|
---|
| 319 | }
|
---|
| 320 |
|
---|
| 321 | /* |
---|
| 322 | */
|
---|
| 323 |
|
---|
| 324 | /*
|
---|
| 325 | =============================================================================
|
---|
| 326 | lcltime(tim, tmsp) -- get local time from system time
|
---|
| 327 | =============================================================================
|
---|
| 328 | */
|
---|
| 329 |
|
---|
| 330 | struct tm *
|
---|
| 331 | lcltime(tim, tmsp)
|
---|
| 332 | long *tim;
|
---|
| 333 | struct tm *tmsp;
|
---|
| 334 | {
|
---|
| 335 | register int dayno, daylbgn, daylend;
|
---|
| 336 | int daylbtm, dayletm;
|
---|
| 337 | register struct tm *ct;
|
---|
| 338 | long copyt;
|
---|
| 339 |
|
---|
| 340 | ltzset();
|
---|
| 341 | copyt = *tim - timezn;
|
---|
| 342 | ct = lgmtime(©t, tmsp);
|
---|
| 343 |
|
---|
| 344 | dayno = ct->tm_yday;
|
---|
| 345 |
|
---|
| 346 | daylbgn = 119; /* Last Sun in Apr */
|
---|
| 347 | daylend = 303; /* Last Sun in Oct */
|
---|
| 348 | daylbtm = 2; /* 02:00 */
|
---|
| 349 | dayletm = 1; /* 01:00 */
|
---|
| 350 |
|
---|
| 351 | if (ct->tm_year EQ 74 OR ct->tm_year EQ 75) {
|
---|
| 352 |
|
---|
| 353 | daylbgn = daytab[ct->tm_year-74].daylb;
|
---|
| 354 | daylend = daytab[ct->tm_year-74].dayle;
|
---|
| 355 | }
|
---|
| 356 |
|
---|
| 357 | if (ct->tm_year EQ 88) {
|
---|
| 358 |
|
---|
| 359 | /* NOTE: this will need to accomodate the change
|
---|
| 360 | to the first sunday in Apr in 1988 */
|
---|
| 361 |
|
---|
| 362 | dayletm = 2;
|
---|
| 363 | }
|
---|
| 364 |
|
---|
| 365 | daylbgn = sunday(ct, daylbgn);
|
---|
| 366 | daylend = sunday(ct, daylend);
|
---|
| 367 |
|
---|
| 368 | if (daylite AND
|
---|
| 369 | (dayno > daylbgn OR (dayno EQ daylbgn AND ct->tm_hour GE daylbtm)) AND
|
---|
| 370 | (dayno < daylend OR (dayno EQ daylend AND ct->tm_hour < dayletm))) {
|
---|
| 371 |
|
---|
| 372 | copyt += 1 * 60 * 60;
|
---|
| 373 | ct = lgmtime(©t, tmsp);
|
---|
| 374 | ct->tm_dst++;
|
---|
| 375 | }
|
---|
| 376 |
|
---|
| 377 | return(ct);
|
---|
| 378 | }
|
---|
| 379 |
|
---|
| 380 | /* |
---|
| 381 | */
|
---|
| 382 |
|
---|
| 383 | /*
|
---|
| 384 | =============================================================================
|
---|
| 385 | latime(t, cbuf) -- convert a tm structure to an ASCII string
|
---|
| 386 | =============================================================================
|
---|
| 387 | */
|
---|
| 388 |
|
---|
| 389 | char *
|
---|
| 390 | latime(t, cbuf)
|
---|
| 391 | struct tm *t;
|
---|
| 392 | char *cbuf;
|
---|
| 393 | {
|
---|
| 394 | register char *cp, *ncp;
|
---|
| 395 | register int *tp;
|
---|
| 396 |
|
---|
| 397 | cp = cbuf;
|
---|
| 398 |
|
---|
| 399 | for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++; );
|
---|
| 400 |
|
---|
| 401 | ncp = &"SunMonTueWedThuFriSat"[3 * t->tm_wday];
|
---|
| 402 | cp = cbuf;
|
---|
| 403 | *cp++ = *ncp++;
|
---|
| 404 | *cp++ = *ncp++;
|
---|
| 405 | *cp++ = *ncp++;
|
---|
| 406 | cp++;
|
---|
| 407 | tp = &t->tm_mon;
|
---|
| 408 | ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp) * 3];
|
---|
| 409 | *cp++ = *ncp++;
|
---|
| 410 | *cp++ = *ncp++;
|
---|
| 411 | *cp++ = *ncp++;
|
---|
| 412 | cp = ct_numb(cp, *--tp);
|
---|
| 413 | cp = ct_numb(cp, *--tp + 100);
|
---|
| 414 | cp = ct_numb(cp, *--tp + 100);
|
---|
| 415 | cp = ct_numb(cp, *--tp + 100);
|
---|
| 416 |
|
---|
| 417 | if (t->tm_year GE 100) {
|
---|
| 418 |
|
---|
| 419 | cp[1] = '2';
|
---|
| 420 | cp[2] = '0';
|
---|
| 421 | }
|
---|
| 422 |
|
---|
| 423 | cp += 2;
|
---|
| 424 | cp = ct_numb(cp, t->tm_year + 100);
|
---|
| 425 |
|
---|
| 426 | return(cbuf);
|
---|
| 427 | }
|
---|
| 428 |
|
---|
| 429 | /* |
---|
| 430 | */
|
---|
| 431 |
|
---|
| 432 | /*
|
---|
| 433 | =============================================================================
|
---|
| 434 | lctime() -- get the current time as a tm structure and an ASCII string
|
---|
| 435 | =============================================================================
|
---|
| 436 | */
|
---|
| 437 |
|
---|
| 438 | char *
|
---|
| 439 | lctime(t, tmsp, cbuf)
|
---|
| 440 | long *t;
|
---|
| 441 | struct tm *tmsp;
|
---|
| 442 | char *cbuf;
|
---|
| 443 | {
|
---|
| 444 | return(latime(lcltime(t, tmsp), cbuf));
|
---|
| 445 | }
|
---|