1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #if defined(LIBC_SCCS) && !defined(lint)
   8: static char sccsid[] = "@(#)ctime.c	5.5 (Berkeley) 3/9/86";
   9: #endif LIBC_SCCS and not lint
  10: 
  11: /*
  12:  * This routine converts time as follows.
  13:  * The epoch is 0000 Jan 1 1970 GMT.
  14:  * The argument time is in seconds since then.
  15:  * The localtime(t) entry returns a pointer to an array
  16:  * containing
  17:  *  seconds (0-59)
  18:  *  minutes (0-59)
  19:  *  hours (0-23)
  20:  *  day of month (1-31)
  21:  *  month (0-11)
  22:  *  year-1970
  23:  *  weekday (0-6, Sun is 0)
  24:  *  day of the year
  25:  *  daylight savings flag
  26:  *
  27:  * The routine calls the system to determine the local
  28:  * timezone and whether Daylight Saving Time is permitted locally.
  29:  * (DST is then determined by the current local rules)
  30:  *
  31:  * The routine does not work
  32:  * in Saudi Arabia which runs on Solar time.
  33:  *
  34:  * asctime(tvec))
  35:  * where tvec is produced by localtime
  36:  * returns a ptr to a character string
  37:  * that has the ascii time in the form
  38:  *	Thu Jan 01 00:00:00 1970\n\0
  39:  *	0123456789012345678901234 5
  40:  *	0	  1	    2
  41:  *
  42:  * ctime(t) just calls localtime, then asctime.
  43:  */
  44: 
  45: #include <sys/time.h>
  46: #include <sys/types.h>
  47: #include <sys/timeb.h>
  48: 
  49: static  char    cbuf[26];
  50: static  int dmsize[12] =
  51: {
  52:     31,
  53:     28,
  54:     31,
  55:     30,
  56:     31,
  57:     30,
  58:     31,
  59:     31,
  60:     30,
  61:     31,
  62:     30,
  63:     31
  64: };
  65: 
  66: /*
  67:  * The following table is used for 1974 and 1975 and
  68:  * gives the day number of the first day after the Sunday of the
  69:  * change.
  70:  */
  71: struct dstab {
  72:     int dayyr;
  73:     int daylb;
  74:     int dayle;
  75: };
  76: 
  77: static struct dstab usdaytab[] = {
  78:     1974,   5,  333,    /* 1974: Jan 6 - last Sun. in Nov */
  79:     1975,   58, 303,    /* 1975: Last Sun. in Feb - last Sun in Oct */
  80:     0,  119,    303,    /* all other years: end Apr - end Oct */
  81: };
  82: static struct dstab ausdaytab[] = {
  83:     1970,   400,    0,  /* 1970: no daylight saving at all */
  84:     1971,   303,    0,  /* 1971: daylight saving from Oct 31 */
  85:     1972,   303,    58, /* 1972: Jan 1 -> Feb 27 & Oct 31 -> dec 31 */
  86:     0,  303,    65, /* others: -> Mar 7, Oct 31 -> */
  87: };
  88: 
  89: /*
  90:  * The European tables ... based on hearsay
  91:  * Believed correct for:
  92:  *	WE:	Great Britain, Portugal?
  93:  *	ME:	Belgium, Luxembourg, Netherlands, Denmark, Norway,
  94:  *		Austria, Poland, Czechoslovakia, Sweden, Switzerland,
  95:  *		DDR, DBR, France, Spain, Hungary, Italy, Jugoslavia
  96:  *		Finland (EE timezone, but ME dst rules)
  97:  * Eastern European dst is unknown, we'll make it ME until someone speaks up.
  98:  *	EE:	Bulgaria, Greece, Rumania, Turkey, Western Russia
  99:  *
 100:  * Ireland is unpredictable.  (Years when Easter Sunday just happens ...)
 101:  * Years before 1983 are suspect.
 102:  */
 103: static struct dstab wedaytab[] = {
 104:     1983,   89, 296,    /* 1983: end March - end Oct */
 105:     0,  89, 303,    /* others: end March - end Oct */
 106: };
 107: 
 108: static struct dstab medaytab[] = {
 109:     1983,   89, 296,    /* 1983: end March - end Oct */
 110:     0,  89, 272,    /* others: end March - end Sep */
 111: };
 112: 
 113: /*
 114:  * Canada, same as the US, except no early 70's fluctuations.
 115:  * Can this really be right ??
 116:  */
 117: static struct dstab candaytab[] = {
 118:     0,  119,    303,    /* all years: end Apr - end Oct */
 119: };
 120: 
 121: static struct dayrules {
 122:     int     dst_type;   /* number obtained from system */
 123:     int     dst_hrs;    /* hours to add when dst on */
 124:     struct  dstab * dst_rules;  /* one of the above */
 125:     enum {STH,NTH}  dst_hemi;   /* southern, northern hemisphere */
 126: } dayrules [] = {
 127:     DST_USA,    1,  usdaytab,   NTH,
 128:     DST_AUST,   1,  ausdaytab,  STH,
 129:     DST_WET,    1,  wedaytab,   NTH,
 130:     DST_MET,    1,  medaytab,   NTH,
 131:     DST_EET,    1,  medaytab,   NTH,    /* XXX */
 132:     DST_CAN,    1,  candaytab,  NTH,
 133:     -1,
 134: };
 135: 
 136: struct tm   *gmtime();
 137: char        *ct_numb();
 138: struct tm   *localtime();
 139: char    *ctime();
 140: char    *ct_num();
 141: char    *asctime();
 142: 
 143: char *
 144: ctime(t)
 145: time_t *t;
 146: {
 147:     return(asctime(localtime(t)));
 148: }
 149: 
 150: struct tm *
 151: localtime(tim)
 152: time_t *tim;
 153: {
 154:     register int dayno;
 155:     register struct tm *ct;
 156:     register dalybeg, daylend;
 157:     register struct dayrules *dr;
 158:     register struct dstab *ds;
 159:     int year;
 160:     time_t copyt;
 161:     struct timeval curtime;
 162:     static struct timezone zone;
 163:     static int init = 0;
 164: 
 165:     if (!init) {
 166:         gettimeofday(&curtime, &zone);
 167:         init++;
 168:     }
 169:     copyt = *tim - (time_t)zone.tz_minuteswest*60;
 170:     ct = gmtime(&copyt);
 171:     dayno = ct->tm_yday;
 172:     for (dr = dayrules; dr->dst_type >= 0; dr++)
 173:         if (dr->dst_type == zone.tz_dsttime)
 174:             break;
 175:     if (dr->dst_type >= 0) {
 176:         year = ct->tm_year + 1900;
 177:         for (ds = dr->dst_rules; ds->dayyr; ds++)
 178:             if (ds->dayyr == year)
 179:                 break;
 180:         dalybeg = ds->daylb;    /* first Sun after dst starts */
 181:         daylend = ds->dayle;    /* first Sun after dst ends */
 182:         dalybeg = sunday(ct, dalybeg);
 183:         daylend = sunday(ct, daylend);
 184:         switch (dr->dst_hemi) {
 185:         case NTH:
 186:             if (!(
 187:                (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) &&
 188:                (dayno<daylend || (dayno==daylend && ct->tm_hour<1))
 189:             ))
 190:                 return(ct);
 191:             break;
 192:         case STH:
 193:             if (!(
 194:                (dayno>dalybeg || (dayno==dalybeg && ct->tm_hour>=2)) ||
 195:                (dayno<daylend || (dayno==daylend && ct->tm_hour<2))
 196:             ))
 197:                 return(ct);
 198:             break;
 199:         default:
 200:             return(ct);
 201:         }
 202:             copyt += dr->dst_hrs*60*60;
 203:         ct = gmtime(&copyt);
 204:         ct->tm_isdst++;
 205:     }
 206:     return(ct);
 207: }
 208: 
 209: /*
 210:  * The argument is a 0-origin day number.
 211:  * The value is the day number of the last
 212:  * Sunday on or before the day.
 213:  */
 214: static
 215: sunday(t, d)
 216: register struct tm *t;
 217: register int d;
 218: {
 219:     if (d >= 58)
 220:         d += dysize(t->tm_year) - 365;
 221:     return(d - (d - t->tm_yday + t->tm_wday + 700) % 7);
 222: }
 223: 
 224: struct tm *
 225: gmtime(tim)
 226: time_t *tim;
 227: {
 228:     register int d0, d1;
 229:     long hms, day;
 230:     register int *tp;
 231:     static struct tm xtime;
 232: 
 233:     /*
 234: 	 * break initial number into days
 235: 	 */
 236:     hms = *tim % 86400;
 237:     day = *tim / 86400;
 238:     if (hms<0) {
 239:         hms += 86400;
 240:         day -= 1;
 241:     }
 242:     tp = (int *)&xtime;
 243: 
 244:     /*
 245: 	 * generate hours:minutes:seconds
 246: 	 */
 247:     *tp++ = hms%60;
 248:     d1 = hms/60;
 249:     *tp++ = d1%60;
 250:     d1 /= 60;
 251:     *tp++ = d1;
 252: 
 253:     /*
 254: 	 * day is the day number.
 255: 	 * generate day of the week.
 256: 	 * The addend is 4 mod 7 (1/1/1970 was Thursday)
 257: 	 */
 258: 
 259:     xtime.tm_wday = (day+7340036)%7;
 260: 
 261:     /*
 262: 	 * year number
 263: 	 */
 264:     if (day>=0) for(d1=70; day >= dysize(d1); d1++)
 265:         day -= dysize(d1);
 266:     else for (d1=70; day<0; d1--)
 267:         day += dysize(d1-1);
 268:     xtime.tm_year = d1;
 269:     xtime.tm_yday = d0 = day;
 270: 
 271:     /*
 272: 	 * generate month
 273: 	 */
 274: 
 275:     if (dysize(d1)==366)
 276:         dmsize[1] = 29;
 277:     for(d1=0; d0 >= dmsize[d1]; d1++)
 278:         d0 -= dmsize[d1];
 279:     dmsize[1] = 28;
 280:     *tp++ = d0+1;
 281:     *tp++ = d1;
 282:     xtime.tm_isdst = 0;
 283:     return(&xtime);
 284: }
 285: 
 286: char *
 287: asctime(t)
 288: struct tm *t;
 289: {
 290:     register char *cp, *ncp;
 291:     register int *tp;
 292: 
 293:     cp = cbuf;
 294:     for (ncp = "Day Mon 00 00:00:00 1900\n"; *cp++ = *ncp++;);
 295:     ncp = &"SunMonTueWedThuFriSat"[3*t->tm_wday];
 296:     cp = cbuf;
 297:     *cp++ = *ncp++;
 298:     *cp++ = *ncp++;
 299:     *cp++ = *ncp++;
 300:     cp++;
 301:     tp = &t->tm_mon;
 302:     ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(*tp)*3];
 303:     *cp++ = *ncp++;
 304:     *cp++ = *ncp++;
 305:     *cp++ = *ncp++;
 306:     cp = ct_numb(cp, *--tp);
 307:     cp = ct_numb(cp, *--tp+100);
 308:     cp = ct_numb(cp, *--tp+100);
 309:     cp = ct_numb(cp, *--tp+100);
 310:     if (t->tm_year>=100) {
 311:         cp[1] = '2';
 312:         cp[2] = '0' + (t->tm_year-100) / 100;
 313:     }
 314:     cp += 2;
 315:     cp = ct_numb(cp, t->tm_year+100);
 316:     return(cbuf);
 317: }
 318: 
 319: dysize(y)
 320: {
 321:     if((y%4) == 0)
 322:         return(366);
 323:     return(365);
 324: }
 325: 
 326: static char *
 327: ct_numb(cp, n)
 328: register char *cp;
 329: {
 330:     cp++;
 331:     if (n>=10)
 332:         *cp++ = (n/10)%10 + '0';
 333:     else
 334:         *cp++ = ' ';
 335:     *cp++ = n%10 + '0';
 336:     return(cp);
 337: }

Defined functions

ct_numb defined in line 326; used 6 times
ctime defined in line 143; used 253 times
dysize defined in line 319; used 11 times
localtime defined in line 150; used 152 times
sunday defined in line 214; used 2 times

Defined variables

ausdaytab defined in line 82; used 1 times
candaytab defined in line 117; used 1 times
cbuf defined in line 49; used 3 times
dayrules defined in line 126; used 1 times
dmsize defined in line 50; used 4 times
medaytab defined in line 108; used 2 times
sccsid defined in line 8; never used
usdaytab defined in line 77; used 1 times
wedaytab defined in line 103; used 1 times

Defined struct's

dayrules defined in line 121; used 2 times
  • in line 157(2)
dstab defined in line 71; used 14 times
Last modified: 1986-03-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1868
Valid CSS Valid XHTML 1.0 Strict