home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OS9000 / APPS / rcs.lzh / rcs1 / maketime.c < prev    next >
Text File  |  1996-04-20  |  8KB  |  280 lines

  1. /*
  2.  * MAKETIME        derive 32-bit time value from TM structure.
  3.  *
  4.  * Usage:
  5.  *    long t,maketime();
  6.  *    struct tm *tp;    Pointer to TM structure from <time.h>
  7.  *            NOTE: this must be extended version!!!
  8.  *    t = maketime(tp);
  9.  *
  10.  * Returns:
  11.  *    0 if failure; parameter out of range or nonsensical.
  12.  *    else long time-value.
  13.  * Notes:
  14.  *    This code is quasi-public; it may be used freely in like software.
  15.  *    It is not to be sold, nor used in licensed software without
  16.  *    permission of the author.
  17.  *    For everyone's benefit, please report bugs and improvements!
  18.  *     Copyright 1981 by Ken Harrenstien, SRI International.
  19.  *    (ARPANET: KLH @ SRI)
  20.  */
  21. #ifndef lint
  22. static char rcsid[]= "$Id: maketime.c_v 1.2 96/04/21 01:08:00 hiro Exp $";
  23. #endif
  24. /* $Log:    maketime.c_v $
  25.  * Revision 1.2  96/04/21  01:08:00  hiro
  26.  * #ifdef'd OSK.
  27.  * 
  28.  * Revision 1.1  93/04/02  01:26:09  hiro
  29.  * Initial revision
  30.  * 
  31.  * Revision 1.1  90/07/19  15:20:11  momo
  32.  * Initial revision
  33.  * 
  34.  * Revision 1.8  88/11/08  13:54:53  narten
  35.  * allow negative timezones (-24h <= x <= 24h)
  36.  * 
  37.  * Revision 1.7  88/11/08  12:02:24  narten
  38.  * changes from  eggert@sm.unisys.com (Paul Eggert)
  39.  * 
  40.  * Revision 1.7  88/08/28  14:47:52  eggert
  41.  * Allow cc -R.  Remove unportable "#endif XXX"s.
  42.  * 
  43.  * Revision 1.6  87/12/18  17:05:58  narten
  44.  * include rcsparam.h
  45.  * 
  46.  * Revision 1.5  87/12/18  11:35:51  narten
  47.  * maketime.c: fixed USG code - you have tgo call "tzset" in order to have
  48.  * "timezone" set. ("localtime" calls it, but it's probably better not to 
  49.  * count on "localtime" having been called.)
  50.  * 
  51.  * Revision 1.4  87/10/18  10:26:57  narten
  52.  * Updating version numbers. Changes relative to 1.0 are actually 
  53.  * relative to 1.2
  54.  * 
  55.  * Revision 1.3  87/09/24  13:58:45  narten
  56.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  57.  * warnings)
  58.  * 
  59.  * Revision 1.2  87/03/27  14:21:48  jenkins
  60.  * Port to suns
  61.  * 
  62.  * Revision 1.1  84/01/23  14:50:04  kcs
  63.  * Initial revision
  64.  * 
  65.  * Revision 1.2  83/12/05  10:12:56  wft
  66.  * added cond. compilation for USG Unix; long timezone;
  67.  * 
  68.  * Revision 1.1  82/05/06  11:38:00  wft
  69.  * Initial revision
  70.  * 
  71.  */
  72.  
  73.  
  74. #include "rcsbase.h"
  75. #include "time.h"
  76.  
  77. int daytb[] = {   /* # days in year thus far, indexed by month (0-12!!) */
  78.     0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
  79. };
  80.  
  81. #ifndef _time
  82. struct tm *localtime();
  83. long    time();
  84. #endif
  85. long maketime(atm)
  86. struct tm *atm;
  87. {    register struct tm *tp;
  88.     register int i;
  89.     int year, yday, mon, day, hour, min, sec, zone, dst, leap;
  90.     long tres, curtim;
  91.  
  92.     VOID time(&curtim);
  93.     tp = localtime(&curtim);        /* Get breakdowns of current time */
  94.     year = tp->tm_year;        /* Use to set up defaults */
  95.     mon = tp->tm_mon;
  96.     day = tp->tm_mday;
  97.  
  98.  
  99. #ifdef DEBUG
  100. printf("first YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
  101. #endif
  102.     tp = atm;
  103.  
  104.     /* First must find date, using specified year, month, day.
  105.      * If one of these is unspecified, it defaults either to the
  106.      * current date (if no more global spec was given) or to the
  107.      * zero-value for that spec (i.e. a more global spec was seen).
  108.      * Start with year... note 32 bits can only handle 135 years.
  109.      */
  110.     if(tp->tm_year != TMNULL)
  111.       {    if((year = tp->tm_year) >= 1900)    /* Allow full yr # */
  112.               year -= 1900;            /* by making kosher */
  113.         mon = 0;        /* Since year was given, default */
  114.         day = 1;        /* for remaining specs is zero */
  115.       }
  116.     if(year < 70 || 70+134 < year )    /* Check range */
  117.         return(0);        /* ERR: year out of range */
  118.     leap = year&03 ? 0 : 1;        /* See if leap year */
  119.     year -= 70;            /* UNIX time starts at 1970 */
  120.  
  121.     /*
  122.      * Find day of year.
  123.      * YDAY is used only if it exists and either the month or day-of-month
  124.      * is missing.
  125.      */
  126.     if (tp->tm_yday != TMNULL
  127.      && (tp->tm_mon == TMNULL || tp->tm_mday == TMNULL))
  128.         yday = tp->tm_yday;
  129.     else
  130.       {    if(tp->tm_mon  != TMNULL)
  131.           {    mon = tp->tm_mon;    /* Month was specified */
  132.             day = 1;        /* so set remaining default */
  133.           }
  134.         if(mon < 0 || 11 < mon) return(0);    /* ERR: bad month */
  135.         if(tp->tm_mday != TMNULL) day = tp->tm_mday;
  136.         if(day < 1
  137.          || (((daytb[mon+1]-daytb[mon]) < day)
  138.             && (day!=29 || mon!=1 || !leap) ))
  139.                 return(0);        /* ERR: bad day */
  140.         yday = daytb[mon]    /* Add # of days in months so far */
  141.           + ((leap        /* Leap year, and past Feb?  If */
  142.               && mon>1)? 1:0)    /* so, add leap day for this year */
  143.           + day-1;        /* And finally add # days this mon */
  144.  
  145.                 if (tp->tm_yday != TMNULL       /* Confirm that YDAY correct */
  146.                  && tp->tm_yday != yday) return(0);     /* ERR: conflict */
  147.       }
  148.     if(yday < 0 || (leap?366:365) <= yday)
  149.         return(0);        /* ERR: bad YDAY or maketime bug */
  150.  
  151.     tres = year*365            /* Get # days of years so far */
  152.         + ((year+1)>>2)        /* plus # of leap days since 1970 */
  153.         + yday;            /* and finally add # days this year */
  154.  
  155.         if((i = tp->tm_wday) != TMNULL) /* Check WDAY if present */
  156.                 if(i < 0 || 6 < i       /* Ensure within range */
  157.                   || i != (tres+4)%7)   /* Matches? Jan 1,1970 was Thu = 4 */
  158.                         return(0);      /* ERR: bad WDAY */
  159.  
  160. #ifdef DEBUG
  161. printf("YMD: %d %d %d, T=%ld\n",year,mon,day,tres);
  162. #endif
  163.     /*
  164.      * Now determine time.  If not given, default to zeros
  165.      * (since time is always the least global spec)
  166.      */
  167.     tres *= 86400L;            /* Get # seconds (24*60*60) */
  168.     hour = min = sec = 0;
  169.     if(tp->tm_hour != TMNULL) hour = tp->tm_hour;
  170.     if(tp->tm_min  != TMNULL) min  = tp->tm_min;
  171.     if(tp->tm_sec  != TMNULL) sec  = tp->tm_sec;
  172.     if( min < 0 || 60 <= min
  173.      || sec < 0 || 60 <= sec) return(0);    /* ERR: MS out of range */
  174.     if(hour < 0 || 24 <= hour)
  175.         if(hour != 24 || (min+sec) !=0)    /* Allow 24:00 */
  176.             return(0);        /* ERR: H out of range */
  177.  
  178. #ifndef OSK
  179.     /* confirm AM/PM if there */
  180.     switch(tp->tm_ampm)
  181.       {    case 0: case TMNULL:    /* Ignore these values */
  182.             break;
  183.         case 1:            /* AM */
  184.         case 2:            /* PM */
  185.             if(hour > 12) return(0);  /* ERR: hrs 13-23 bad */
  186.             if(hour ==12) hour = 0;    /* Modulo 12 */
  187.             if(tp->tm_ampm == 2)    /* If PM, then */
  188.                 hour += 12;    /*   get 24-hour time */
  189.             break;
  190.         default: return(0);    /* ERR: illegal TM_AMPM value */
  191.       }
  192. #endif
  193.  
  194.     tres += sec + 60L*(min + 60L*hour);    /* Add in # secs of time */
  195.  
  196. #ifdef DEBUG
  197. printf("HMS: %d %d %d T=%ld\n",hour,min,sec,tres);
  198. #endif
  199.     /*
  200.      * We now have the GMT date/time and must make final
  201.      * adjustment for the specified time zone.  If none is specified,
  202.      * the local time-zone is assumed.
  203.      */
  204. #ifdef OSK
  205.     zone = localzone();
  206. #else
  207.     if((zone = tp->tm_zon) == TMNULL    /* If unspecified */
  208.      || (zone == 1))            /* or local-zone requested */
  209.         zone = localzone();        /* then set to local zone */
  210. #endif
  211.     if(zone < -24*60 || 24*60 <= zone)
  212.         return(0);            /* ERR: zone out of range */
  213.  
  214.     /* See if must apply Daylight Saving Time shift.
  215.      * Note that if DST is specified, validity is not checked.
  216.      */
  217.     if((dst = tp->tm_isdst) == TMNULL)    /* Must we figure it out? */
  218.       {    curtim = tres +localzone()*60L;    /* Yuck.  Get equiv local */
  219.         dst = localtime(&curtim)->tm_isdst;     /* time, and ask. */
  220.       }
  221.     tres += zone*60L -(dst?3600:0);    /* Add in # seconds of zone adj */
  222.  
  223.     return(tres);
  224. }
  225.  
  226.  
  227. /* LOCALZONE        return local timezone in # mins west of GMT
  228.  *
  229.  */
  230.  
  231. #ifdef OSK
  232. struct timeb {
  233.     short dstflg;
  234.     int millitm;
  235.     double time;
  236.     long timezone;
  237. };
  238.  
  239. ftime( tb )
  240. struct timeb *tb;
  241. {
  242.     char *p , *getenv();
  243.  
  244.     if ( (p=getenv("TZ"))==NULL ) {
  245.         p="GMT+540:no";
  246.     }
  247. /*    if ( strncmp("GMT",p,3)==0 ) tb.timezone=0; */
  248.     tb->timezone=0;
  249.     tb->timezone+=atoi(p+3);    /* timezone only set ... */
  250. /*    fprintf(stderr,"%s timezone=%d\n",p,timezone); */
  251. }
  252.  
  253. #else
  254. #    if defined(V6) || defined(USG)
  255.         extern long timezone;
  256. #    else
  257. #        include <sys/types.h>
  258. #        include <sys/timeb.h>
  259. #    endif
  260. #endif
  261.  
  262. static int lclzon;
  263. localzone()
  264. {
  265.     if (!lclzon) {
  266. #if defined(V6) || defined(USG)
  267. #ifdef USG
  268.     tzset();
  269. #endif
  270.     lclzon = timezone/60 + 1;
  271. #else
  272.     struct timeb tb;
  273.  
  274.     ftime(&tb);
  275.     lclzon = tb.timezone + 1;
  276. #endif
  277.     }
  278.     return lclzon - 1;
  279. }
  280.