Document title: SUN UNIX C routines to convert UCLA-IGPP Cline time Project: ISEE1 and ISEE2 NDADS Datatype: MAG_1M_FF and MAG_4S_FF Super-EID: SOFTWARE There may be other documents also identified by this super-EID. NDADS filename: CTIME.C TRF entry: b46639.txt in NSSDC's controlled digital document library, Mar. 1998. Document text follows: ---------------------- /* ------------------------------------------------------------------------- * * * * ctime.c - This file contains Sun/UNIX C versions of functions to convert * * amongst various formats of the UCLA-IGPP time definition called * * "Cline time". This time is a double (real*8) value containing * * the number of seconds since January 1, 1966 at 00:00:00.000. * * These functions convert to and from double and integer arrays * * or character strings. They are callable from C and FORTRAN. * * * * Copyright (c) 1975-94 Regents of the University of California. * * All Rights Reserved. * * * * Redistribution and use in source and binary forms are permitted * * provided that the above copyright notice and this paragraph are * * duplicated in all such forms and that any documentation, advertising * * materials, and other materials related to such distribution and use * * acknowledge that the software was developed by the University of * * California, Los Angeles. The name of the University may not be used * * to endorse or promote products derived from this software without * * specific prior written permission. THIS SOFTWARE IS PROVIDED "AS IS" * * AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT * * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * * FOR A PARTICULAR PURPOSE. * * * * For information about this software please contact: * * * * Principal Investigator: * * Christopher Russell * * UCLA - Institute of Geophysics and Planetary Physics * * 6871 Slichter Hall * * Los Angeles, Ca. 90024-1567 * * INTERNET e-mail: ctrussell@igpp.ucla.edu * * NSI/DECnet e-mail: BRUNET::CTRUSSELL * * Telephone: (310) 825-3188 * * * * Programmer: * * Harry Herbert * * UCLA - Institute of Geophysics and Planetary Physics * * 5833 Slichter Hall * * Los Angeles, Ca. 90024-1567 * * INTERNET e-mail: hherbert@igpp.ucla.edu * * NSI/DECnet e-mail: BRUNET::HARRY * * Telephone: (310) 825-9030 * * * * ------------------------------------------------------------------------- */ #ifndef lint static char sccsid[]="@(#)ctime.c 1.1 3/19/91"; #endif #include #include #ifdef sun #define acont acont_ #define tcona tcona_ #define aconi aconi_ #define icona icona_ #define tconi tconi_ #define icont icont_ #define ccont ccont_ #define tconc tconc_ #define cconi cconi_ #define iconc iconc_ #define tnow tnow_ #define greg_day greg_day_ #define greg_date greg_date_ #define afixt afixt_ #endif void acont(),tcona(),aconi(),icona(),tconi(),icont(), ccont(),tconc(),cconi(),iconc(),greg_date(); int numst(),monst(); double greg_day(); #define DN0 77906. /* Days from Sept 13, 1752 to Jan 1, 1966 */ static char *months[]={" ","JAN","FEB","MAR","APR","MAY","JUN", "JUL","AUG","SEP","OCT","NOV","DEC"}; void acont (l,at,t) int *l; char *at; double *t; { int it[8]; aconi(l,at,it); icont (it,t); return; } void aconi (l,at,it) int *l; char *at; int it[8]; { int i,ll,k=0; ll = *l; it[0] = numst(at,&k,ll,4); /* try for year, up to 4 digits */ it[1] = it[2] = it[3] = 0; if ((it[2] = monst(at,&k,ll)) != 0) goto dom; /* try for character month */ it[1] = numst(at,&k,ll,3); /* no month, try for 3 digit day of year */ if ((it[2] = monst(at,&k,ll)) == 0) goto hour; /* try for character month */ dom: it[3] = numst(at,&k,ll,2); /* day of month */ hour: it[4] = numst(at,&k,ll,2); it[5] = numst(at,&k,ll,2); it[6] = numst(at,&k,ll,2); it[7] = numst(at,&k,ll,3); return; } int numst (a,k,l,w) char *a; /* character time string */ int *k; /* string index, incremented and passed back */ int l; /* length of string */ int w; /* maximum number of digits to scan */ { int d=0; /* number of characters scanned */ int n=0; /* decimal value of characters, returned */ int kk; char p,x='\0'; search: /* search for digit */ p = x; /* save character before digits, might be d.p. */ kk = *k; do { if (kk == l) break; x = a[kk]; if (x == '\0') break; /* don't increment string index */ if (!isdigit(x)) { if (d == 0) { (*k)++; goto search; } /* no digits yet */ break; /* don't increment string index */ } kk++; n *= 10; n += x - '0'; d ++; } while (d < w); if (p == '.') while (d < w) { d++; n *= 10; } ret: *k = kk; return n; } int monst (a,k,l) char *a; /* character time string */ int *k; /* string index, incremented and passed back */ int l; /* length of string */ { char month[4],c; int n = 0; int i,kk; kk = *k; while ( kk < l && isspace (a[kk])) kk++; /* search for non blank */ /* Assume ucb toupper, where one has to check islower first */ for (i = 0; i < 3 && i+kk 0 && strncmp (month,months[n],i); n--); if (n) kk += --i; ret: *k = kk; return n; } void tcona (t,at) double *t; char *at; { int it[8]; tconi(t,it); iconc(it,at,28); return; } void icona (it,at) int it[8]; char *at; { iconc(it,at,28); return; } void icont (it,t) int it[8]; double *t; { int yr; double dn; static int one = 1; yr = it[0]; if (yr < 100) yr += 1900; if (it[1] == 0) dn = greg_day(&it[3],&it[2],&yr); else dn = greg_day(&one,&one,&yr) + it[1] - 1; *t = 86400. * (dn - DN0) + 3600. * it[4] + 60. * it[5] + it[6] + .001 * it[7]; return; } void tconi (tx,it) double *tx; int it[8]; { static float dd=0.; static int ss=0; static int jt[8]={66,1,1,1,0,0,0,0}; double t; float d; int i,s; static int one=1; t = floor (*tx*1000. + .5); /* round time to nearest millisecond */ d = floor (t/86400000.); if (fabs(d-dd) > .1) { dd = d + DN0; greg_date (&dd, &jt[3],&jt[2],&jt[0]); jt[1] = greg_day(&jt[3],&jt[2],&jt[0]) - greg_day(&one,&one,&jt[0]) + 1.; if (1899 < jt[0] && jt[0] < 2000) jt[0] = jt[0] - 1900; dd = d; } s = t - 86400000. * d; /* milliseconds of day */ if (s != ss) { ss = s; jt[7] = s % 1000; s /= 1000; jt[6] = s % 60; s /= 60; jt[5] = s % 60; jt[4] = s / 60; } for (i = 0; i < 8; i++) it[i] = jt[i]; return; } /* ************************************************************ NAME greg_day - convert date to number of days since 13th Sept, 1752. SYNOPSIS SUN C double greg_day(dy,month,year) int *dy, *month, *year; HP9000 C double greg_day(dy,month,year) int *dy, *month, *year; FORTRAN real*8 greg_day integer day, month, year DESCRIPTION RETURN VALUE ERRORS AUTHOR/DATE Neal Cline UCLA Inst. of Geophysics 01/24/80 UPDATES Converted to C: Gordon Maclean 02/89 ************************************************************** */ double greg_day(dy,month,year) int *dy, *month, *year; { double d; int i,k,m; i = *year; m = *month -3; if (m < 0) { m += 12; i--; } k = i / 100 - 16; i %= 100; d = 36524.0 * k + 365.0 * i + k / 4 + i / 4 + (153 * m + 2) / 5 + *dy - 55714.0; return d; } void greg_date (d,dy,month,year) float *d; int *dy, *month, *year; { double dd; int i,k,m; dd = *d + 445711.0 / 8. ; k = (4. * dd) / 146097.; dd += -36524. * k - k / 4 ; i = (4. * dd) / 1461. ; dd += -365. * i - i / 4 ; i += 100 * (k + 16); k = 5. * dd - 1.875; m = k / 153; k = (k - 153 * m + 5) / 5; if (m > 9) { *month = m - 9; i++; } else *month = m + 3; *year = i; *dy = k; return; } #ifdef hpux void ccont (ct,len,t) #else void ccont (ct,t,len) #endif char *ct; int len; double *t; { int it[8]; aconi (&len,ct,it); icont (it,t); return; } #ifdef hpux void cconi (ct,len,it) #else void cconi (ct,it,len) #endif char *ct; int len; int it[8]; { aconi (&len,ct,it); return; } void tconc (t,ct,len) double *t; char *ct; int len; { int it[8]; tconi (t,it); iconc (it,ct,len); return; } #include double tnow() { struct timeval now; struct timezone tzp; struct tm *localtime(),*ptr; void icont(); int it[8],i; double timenow; if (gettimeofday(&now,&tzp) < 0) perror ("Gettimeofday error"); ptr = localtime(&now.tv_sec); it[0] = ptr->tm_year; it[1] = ptr->tm_yday + 1; it[2] = 0; it[3] = 0; it[4] = ptr->tm_hour; it[5] = ptr->tm_min; it[6] = ptr->tm_sec; it[7] = now.tv_usec / 1000; icont (it,&timenow); return timenow; } void iconc(it,at,len) int it[8]; char *at; int len; { int mon,fdy; static int jt[8]={66,1,1,1,0,0,0,0}; static char a[2][29]={" 66 001 JAN 1 00:00:00.000", "1966 001 JAN 1 00:00:00.000"}; static ix1[2][8]={ 1, 4, 8,12,16,19,22,25, 0, 5, 9,13,16,19,22,25}; static ix2[2][8]={ 2, 6,10,13,17,20,23,27, 3, 7,11,14,17,20,23,27}; static int lf=0; int i,k,k1,k2; unsigned int n; /* The following code is an attempt to optimize iconc when it is being repeatedly passed similar times. Rather than call sprintf, on the whole time string, it only formats the string starting a the first portion which needs changing. I tested three codes. The first simply called sprintf to format the entire string for each time. The next code only called sprintf to format the string starting at the first time field which was different than the last. Then this code was tested which uses its own formatting instead of sprintf. Two tests were run for each code. Test1 consists of processing a series of times, each differing by 333.33 seconds spanning 5 years (a total of 475000 calls). The times in test two were 1 second apart for 4 days. Full sprintf Optimized sprintfs Own formatting test1 6:03.54 4:55.84 3:50.99 test2 4:19.33 3:04.25 2.26.33 if (fdy) sprintf (a,"%4.4ld%4.3ld%4.3s%3.1l d%2.2ld:%2.2ld:%2.2ld.%3.3ld", it[0],it[1],months[mon],it[3],it[4],it[5],it[6],it[7]); else sprintf (a,"%3.2ld%4.3ld%4.3s%3.1ld %2.2ld:%2.2ld:%2.2ld.%2.3ld", it[0],it[1],months[mon],it[3],it[4],it[5],it[6],it[7]); */ fdy = (it[0] > 99); mon = it[2]; if (mon < 0 || mon > 12 ) mon = 0; for (i=0; i < 8; i++) { n = it[i]; if (n != jt[i] || fdy != lf) { jt[i] = n; k1 = ix1[fdy][i]; if (i != 2) { k2 = ix2[fdy][i]; k = k2; while (k > k1) { a[fdy][k--] = n % 10 + '0'; n /= 10; } if (n > 9) for (k=k1; k<=k2; k++) a[fdy][k] = '*'; else { a[fdy][k] = n + '0'; if (i == 3 && n == 0) a[fdy][k] = ' '; } } else for (k=0; k < 3; k++) a[fdy][k1+k] = months[mon][k]; } } lf = fdy; memcpy (at,a[fdy],(len > 28 ? 28 : len)); for (k=28; k