Main Page Class Hierarchy Compound List File List Compound Members File Members

# chron3.c

Go to the documentation of this file.

    00001
    00002 /*
    00003  *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
    00004  *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
    00005  *
    00006  *    $Id: chron3_8c-source.html 2161 2006-05-19 16:55:03Z paulf $
    00007  *
    00008  *    Revision history:
    00009  *     $Log$
    00009  *     Revision 1.1  2006/05/19 16:55:01  paulf
    00009  *     first inclusion
    00009  *
    00010  *     Revision 1.1  2000/02/14 18:51:48  lucky
    00011  *     Initial revision
    00012  *
    00013  *
    00014  */
    00015
    00016 #include <stdio.h>
    00017 #include <time.h>
    00018 #include <sys/types.h>
    00019 #include <chron3.h>
    00020 /*
    00021    chron3.c : Time/date conversion routines.
    00022
    00023    91May07 CEJ Version 1.0 - chron.c, chron.h
    00024
    00025    Modified by W. Kohler, March 8, 1993.
    00026    Source file name changed from chron.c to chron2.c.
    00027    Include file name changed from chron.h to chron2.h.
    00028    Routine datime added to calculate gregorian date and time from
    00029    julian seconds.  Seconds added to structure Greg in file chron2.h.
    00030
    00031    Modified by L. Dietz,  March 30, 1995.
    00032    Source file name changed from chron2.c to chron3.c.
    00033    Include file name changed from chron2.h to chron3.h.
    00034    Routines date15 and julsec15 added to convert between time in
    00035    julian seconds and character strings.
    00036    Added a define statement to set the century (#define CENTURY 1900)
    00037
    00038    Modified by L. Dietz, January 30, 1995.
    00039    Added routine epochsec15 to convert from time given in a
    00040    15-character string and seconds since 1970-01-01 00:00:00.0 GMT.
    00041
    00042    Modified by L. Dietz, October, 1998.
    00043    Changed make the library Y2K-compliant.
    00044    + Removed the CENTURY definition from chron3.h!
    00045    + Removed all functions that dealt with 2-digit-year date strings
    00046      and replaced them with 4-digit-year counterparts.
    00047         date15     -> date17
    00048         date18     -> date20
    00049         julsec15   -> julsec17
    00050         epochsec15 -> epochsec17
    00051         timegm     -> timegm (fixed to call epochsec17)
    00052
    00053    Modified by L. Dietz, November, 1998.
    00054    Changed to make function MT-safe.
    00055    Eliminated the file-global "struct Greg G" workspace and had each function
    00056    declare its own "struct Greg" variable, if needed.  Changed function
    00057    arguments for grg(), gregor(), and datime() to include a pointer to
    00058    struct Greg for returning information to calling function.
    00059
    00060 */
    00061
    00062 /*********************C O P Y R I G H T   N O T I C E ***********************/
    00063 /* Copyright 1991 by Carl Johnson.  All rights are reserved. Permission     */
    00064 /* is hereby granted for the use of this product for nonprofit, commercial, */
    00065 /* or noncommercial publications that contain appropriate acknowledgement   */
    00066 /* of the author. Modification of this code is permitted as long as this    */
    00067 /* notice is included in each resulting source module.                      */
    00068 /****************************************************************************/
    00069
    00070 int mo[] = {   0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334,
    00071                0,  31,  60,  91, 121, 152, 182, 213, 244, 274, 305, 335};
    00072 char *cmo[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
    00073                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
    00074
    00075 /*
    00076  * Calculate julian minute from gregorian date and time.
    00077  */
    00078 long julmin( struct Greg *pg )
    00079 {
    00080         return(1440L * (julian(pg) - 2305448L) + 60L * pg->hour + pg->minute);
    00081 }
    00082
    00083 /*
    00084  * Calculate gregorian date and time from julian minutes.
    00085  */
    00086 struct Greg *grg( long min, struct Greg *pg )
    00087 {
    00088         long j;
    00089         long m;
    00090
    00091         j = min/1440L;
    00092         m = min-1440L*j;
    00093         j += 2305448L;
    00094         gregor(j,pg);
    00095         pg->hour = m/60;
    00096         pg->minute = m - 60 * pg->hour;
    00097         return(pg);
    00098 }
    00099
    00100 /*
    00101  * julian : Calculate julian date from gregorian date.
    00102  */
    00103 long julian( struct Greg *pg )
    00104 {
    00105         long jul;
    00106         int leap;
    00107         int year;
    00108         int n;
    00109
    00110         jul = 0;
    00111         year = pg->year;
    00112         if(year < 1) goto x110;
    00113         year--;
    00114         jul = 365;
    00115
    00116 /* four hundred year rule */
    00117         n = year / 400;
    00118         jul += n * 146097L;
    00119         year -= n * 400;
    00120
    00121 /* hundred year rule */
    00122         n = year / 100;
    00123         jul += n * 36524L;
    00124         year -= n * 100;
    00125
    00126 /* four year rule */
    00127         n = year / 4;
    00128         jul += n * 1461L;
    00129         year -= n * 4;
    00130
    00131 /* one year rule */
    00132         jul += year * 365L;
    00133
    00134 /* Handle days in current year */
    00135 x110:
    00136         leap = 0;
    00137         if(pg->year % 4   == 0) leap = 12;
    00138         if(pg->year % 100 == 0) leap = 0;
    00139         if(pg->year % 400 == 0) leap = 12;
    00140         jul += mo[pg->month + leap - 1] + pg->day + 1721060L;
    00141         return(jul);
    00142 }
    00143
    00144 /*
    00145  * gregor : Calculate gregorian date from julian date.
    00146  */
    00147 struct Greg *gregor( long min, struct Greg *pg )
    00148 {
    00149         long test;
    00150         long check;
    00151         int leap;
    00152         int left;
    00153         int imo;
    00154
    00155         pg->year = (min - 1721061L) / 365L;
    00156         pg->month = 1;
    00157         pg->day = 1;
    00158         test = julian(pg);
    00159         if(test <= min) goto x110;
    00160
    00161 x20:
    00162         pg->year--;
    00163         test = julian(pg);
    00164         if(test > min) goto x20;
    00165         goto x210;
    00166
    00167 x105:
    00168         pg->year++;
    00169         test = julian(pg);
    00170
    00171 x110:
    00172         check = test - min - 366L;
    00173         if(check < 0) goto x210;
    00174         if(check > 0) goto x105;
    00175
    00176         if(pg->year % 400 == 0) goto x210;
    00177         if(pg->year % 100 == 0) goto x105;
    00178         if(pg->year %   4 == 0) goto x210;
    00179         goto x105;
    00180
    00181 x210:
    00182         left = min - test;
    00183         leap = 0;
    00184         if(pg->year %   4 == 0) leap = 12;
    00185         if(pg->year % 100 == 0) leap = 0;
    00186         if(pg->year % 400 == 0) leap = 12;
    00187         for(imo=1; imo<12; imo++) {
    00188                 if(mo[imo+leap] <= left)
    00189                         continue;
    00190                 pg->month = imo;
    00191                 pg->day = left - mo[imo+leap-1] + 1;
    00192                 return(pg);
    00193         }
    00194         pg->month = 12;
    00195         pg->day = left - mo[11+leap] + 1;
    00196         return(pg);
    00197 }
    00198
    00199 /*
    00200  * date20 : Create 20 char date string in the form 1988Jan23 1234 12.21
    00201  *          from the julian seconds.  Remember to leave space for the
    00202  *          string termination (NULL).
    00203  *          Replaces non-Y2K-compliant date18() function
    00204  *          Added to chron3.c 10/28/98 by LDD.
    00205  */
    00206 void date20( double secs, char *c20)
    00207 {
    00208         struct Greg g;
    00209         long minute;
    00210         double sex;
    00211         int hrmn;
    00212
    00213         minute = (long) (secs / 60.0);
    00214         sex = secs - 60.0 * minute;
    00215         grg(minute, &g);
    00216         hrmn = 100 * g.hour + g.minute;
    00217         sprintf(c20, "%04d%3s%2d %4d%6.2f",
    00218                 g.year, cmo[g.month-1], g.day, hrmn, sex);
    00219 }
    00220
    00221 /*
    00222  * tnow : Returns current system time for time stamping
    00223  */
    00224 double tnow( void )
    00225 {
    00226         struct Greg g;
    00227 /*      struct timeb q; */
    00228         time_t tsecs;
    00229         double secs;
    00230
    00231         g.year   = 1970;
    00232         g.month  = 1;
    00233         g.day    = 1;
    00234         g.hour   = 0;
    00235         g.minute = 0;
    00236 /* original code by Carl; ftime() not supported on Sparc C compiler 3.0.1 */
    00237 /*      ftime(&q);                                              */
    00238 /*      secs = 60.0 * julmin(&g) + q.time +  0.001 * q.millitm; */
    00239         time(&tsecs);                                   /*950501:ldd.*/
    00240         secs = 60.0 * julmin(&g) + (double) tsecs;      /*950501:ldd.*/
    00241         return secs;
    00242 }
    00243
    00244 /*
    00245  * Calculate gregorian date and time from julian seconds.
    00246  */
    00247 struct Greg *datime( double secs, struct Greg *pg )
    00248 {
    00249         long j, m, min;
    00250
    00251         min = (long) (secs / 60.0);
    00252         j = min/1440L;
    00253         m = min-1440L*j;
    00254         j += 2305448L;
    00255         gregor(j,pg);
    00256         pg->hour = m/60;
    00257         pg->minute = m - 60 * pg->hour;
    00258         pg->second = (float) (secs - 60.0 * min);
    00259         return(pg);
    00260 }
    00261
    00262 /*
    00263  * date17 : Build a 17 char date string in the form 19880123123412.21
    00264  *          from the julian seconds.  Remember to leave space for the
    00265  *          string termination (NULL).
    00266  *          Replaces the non-Y2K-compliant date15() function.
    00267  *          Added to chron3.c on 10/28/98 by LDD
    00268  */
    00269 void date17( double secs, char *c17 )
    00270 {
    00271         struct Greg g;
    00272         long minute;
    00273         double sex;
    00274
    00275         minute = (long) (secs / 60.0);
    00276         sex = secs - 60.0 * (double) minute;
    00277         grg(minute,&g);
    00278         sprintf(c17, "%04d%02d%02d%02d%02d%05.2f\0",
    00279                 g.year, g.month, g.day, g.hour, g.minute, sex);
    00280 }
    00281
    00282 /*
    00283  * julsec17 : Calculate time in julian seconds from a character string
    00284  *            of the form 19880123123412.21
    00285  *            Replaces the non-Y2K-compliant julsec15() function.
    00286  *            Added to chron3.c on 10/28/98 by LDD
    00287  */
    00288 double julsec17( char *c17 )
    00289 {
    00290         struct Greg  g;
    00291         double       jsecs;
    00292         int          narg, i;
    00293         int          isec, hsec;
    00294
    00295 /*** Make sure there are no blanks in the time part of the pick ***/
    00296         for(i=0; i<17; i++)
    00297         {
    00298                 if( c17[i] == ' ' )  c17[i] = '0';
    00299         }
    00300
    00301 /***  Read character string  ***/
    00302         narg = sscanf( c17, "%4d%2d%2d%2d%2d%2d.%2d",
    00303                         &g.year, &g.month, &g.day,
    00304                         &g.hour, &g.minute, &isec, &hsec);
    00305
    00306         if ( narg < 7 )  return( 0.0 );
    00307
    00308
    00309 /***  Calculate julian seconds ***/
    00310         jsecs   = 60.0 * (double) julmin(&g) +
    00311                          (double) isec +
    00312                          (double) hsec / 100.0;
    00313
    00314         return( jsecs );
    00315 }
    00316
    00317 /*
    00318  * epochsec17 :  Convert time in a character string form of
    00319  *               ccyymmddhhmmss.ff (19880231010155.23) to
    00320  *               seconds since 1970-01-01 00:00:00.0
    00321  *               Replaces the non-Y2K-compliant epochsec15() function.
    00322  *               Added to chron3.c on 10/28/98 by LDD
    00323  */
    00324 int epochsec17( double *sec, char *tstr )
    00325 {
    00326    double jsec;
    00327
    00328    jsec = julsec17( tstr );
    00329    if( jsec==0.0 )
    00330    {
    00331       *sec=0.0;
    00332       return ( -1 );
    00333    }
    00334
    00335    *sec = jsec-GSEC1970;
    00336    return ( 0 );
    00337 }
    00338
    00339 /*
    00340  * timegm :  Convert time as a struct tm to seconds since 1970-01-01 00:00:00.0
    00341  *           This function is equivalent to timegm() in SunOS 4.x.
    00342  *           Added to chron3.c on 2/27/98 by WMK
    00343  *           Modified to be Y2K compliant 10/28/98 by LDD
    00344  */
    00345 time_t timegm( struct tm *tm )
    00346 {
    00347    char   tstr[18];
    00348    double dsec;
    00349
    00350    sprintf( tstr, "%04d%02d%02d%02d%02d%02d.00",
    00351             tm->tm_year + 1900,
    00352             tm->tm_mon + 1,
    00353             tm->tm_mday,
    00354             tm->tm_hour,
    00355             tm->tm_min,
    00356             tm->tm_sec );
    00357
    00358    epochsec17( &dsec, tstr );
    00359    return( (time_t)dsec );
    00360 }
    00361