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