📄 genutils.c
字号:
* ms_hptime2mdtimestr: * * Build a time string in month-day format from a high precision * epoch time. * * The provided mdtimestr must have enough room for the resulting time * string of 27 characters, i.e. '2001-07-29 12:38:00.000000' + NULL. * * The 'subseconds' flag controls whenther the sub second portion of the * time is included or not. * * Returns a pointer to the resulting string or NULL on error. ***************************************************************************/char *ms_hptime2mdtimestr (hptime_t hptime, char *mdtimestr, flag subseconds){ struct tm *tm; int isec; int ifract; int ret; time_t tsec; if ( mdtimestr == NULL ) return NULL; /* Reduce to Unix/POSIX epoch time and fractional seconds */ isec = MS_HPTIME2EPOCH(hptime); ifract = (hptime_t) hptime - (isec * HPTMODULUS); /* Adjust for negative epoch times */ if ( hptime < 0 && ifract != 0 ) { isec -= 1; ifract = HPTMODULUS - (-ifract); } tsec = (time_t) isec; if ( ! (tm = gmtime ( &tsec )) ) return NULL; if ( subseconds ) /* Assuming ifract has at least microsecond precision */ ret = snprintf (mdtimestr, 27, "%4d-%02d-%02d %02d:%02d:%02d.%06d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, ifract); else ret = snprintf (mdtimestr, 20, "%4d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); if ( ret != 26 && ret != 19 ) return NULL; else return mdtimestr;} /* End of ms_hptime2mdtimestr() *//*************************************************************************** * ms_hptime2seedtimestr: * * Build a SEED time string from a high precision epoch time. * * The provided seedtimestr must have enough room for the resulting time * string of 25 characters, i.e. '2001,195,12:38:00.000000\n'. * * The 'subseconds' flag controls whenther the sub second portion of the * time is included or not. * * Returns a pointer to the resulting string or NULL on error. ***************************************************************************/char *ms_hptime2seedtimestr (hptime_t hptime, char *seedtimestr, flag subseconds){ struct tm *tm; int isec; int ifract; int ret; time_t tsec; if ( seedtimestr == NULL ) return NULL; /* Reduce to Unix/POSIX epoch time and fractional seconds */ isec = MS_HPTIME2EPOCH(hptime); ifract = (hptime_t) hptime - (isec * HPTMODULUS); /* Adjust for negative epoch times */ if ( hptime < 0 && ifract != 0 ) { isec -= 1; ifract = HPTMODULUS - (-ifract); } tsec = (time_t) isec; if ( ! (tm = gmtime ( &tsec )) ) return NULL; if ( subseconds ) /* Assuming ifract has at least microsecond precision */ ret = snprintf (seedtimestr, 25, "%4d,%03d,%02d:%02d:%02d.%06d", tm->tm_year + 1900, tm->tm_yday + 1, tm->tm_hour, tm->tm_min, tm->tm_sec, ifract); else /* Assuming ifract has at least microsecond precision */ ret = snprintf (seedtimestr, 18, "%4d,%03d,%02d:%02d:%02d", tm->tm_year + 1900, tm->tm_yday + 1, tm->tm_hour, tm->tm_min, tm->tm_sec); if ( ret != 24 && ret != 17 ) return NULL; else return seedtimestr;} /* End of ms_hptime2seedtimestr() *//*************************************************************************** * ms_time2hptime_int: * * Convert specified time values to a high precision epoch time. This * is an internal version which does no range checking, it is assumed * that checking the range for each value has already been done. * * Returns epoch time on success and HPTERROR on error. ***************************************************************************/static hptime_tms_time2hptime_int (int year, int day, int hour, int min, int sec, int usec){ BTime btime; hptime_t hptime; memset (&btime, 0, sizeof(BTime)); btime.day = 1; /* Convert integer seconds using ms_btime2hptime */ btime.year = (int16_t) year; btime.day = (int16_t) day; btime.hour = (uint8_t) hour; btime.min = (uint8_t) min; btime.sec = (uint8_t) sec; btime.fract = 0; hptime = ms_btime2hptime (&btime); if ( hptime == HPTERROR ) { ms_log (2, "ms_time2hptime(): Error converting with ms_btime2hptime()\n"); return HPTERROR; } /* Add the microseconds */ hptime += (hptime_t) usec * (1000000 / HPTMODULUS); return hptime;} /* End of ms_time2hptime_int() *//*************************************************************************** * ms_time2hptime: * * Convert specified time values to a high precision epoch time. This * is essentially a frontend for ms_time2hptime that does range * checking for each input value. * * Expected ranges: * year : 1900 - 2100 * day : 1 - 366 * hour : 0 - 23 * min : 0 - 59 * sec : 0 - 60 * usec : 0 - 999999 * * Returns epoch time on success and HPTERROR on error. ***************************************************************************/hptime_tms_time2hptime (int year, int day, int hour, int min, int sec, int usec){ if ( year < 1900 || year > 2100 ) { ms_log (2, "ms_time2hptime(): Error with year value: %d\n", year); return HPTERROR; } if ( day < 1 || day > 366 ) { ms_log (2, "ms_time2hptime(): Error with day value: %d\n", day); return HPTERROR; } if ( hour < 0 || hour > 23 ) { ms_log (2, "ms_time2hptime(): Error with hour value: %d\n", hour); return HPTERROR; } if ( min < 0 || min > 59 ) { ms_log (2, "ms_time2hptime(): Error with minute value: %d\n", min); return HPTERROR; } if ( sec < 0 || sec > 60 ) { ms_log (2, "ms_time2hptime(): Error with second value: %d\n", sec); return HPTERROR; } if ( usec < 0 || usec > 999999 ) { ms_log (2, "ms_time2hptime(): Error with microsecond value: %d\n", usec); return HPTERROR; } return ms_time2hptime_int (year, day, hour, min, sec, usec);} /* End of ms_time2hptime() *//*************************************************************************** * ms_seedtimestr2hptime: * * Convert a SEED time string to a high precision epoch time. SEED * time format is "YYYY[,DDD,HH,MM,SS.FFFFFF]", the delimiter can be a * comma [,], colon [:] or period [.] except for the fractional * seconds which must start with a period [.]. * * The time string can be "short" in which case the omitted values are * assumed to be zero (with the exception of DDD which is assumed to * be 1): "YYYY,DDD,HH" assumes MM, SS and FFFF are 0. The year is * required, otherwise there wouldn't be much for a date. * * Ranges are checked for each value. * * Returns epoch time on success and HPTERROR on error. ***************************************************************************/hptime_tms_seedtimestr2hptime (char *seedtimestr){ int fields; int year = 0; int day = 1; int hour = 0; int min = 0; int sec = 0; float fusec = 0.0; int usec = 0; fields = sscanf (seedtimestr, "%d%*[,:.]%d%*[,:.]%d%*[,:.]%d%*[,:.]%d%f", &year, &day, &hour, &min, &sec, &fusec); /* Convert fractional seconds to microseconds */ if ( fusec != 0.0 ) { usec = (int) (fusec * 1000000.0 + 0.5); } if ( fields < 1 ) { ms_log (2, "ms_seedtimestr2hptime(): Error converting time string: %s\n", seedtimestr); return HPTERROR; } if ( year < 1900 || year > 3000 ) { ms_log (2, "ms_seedtimestr2hptime(): Error with year value: %d\n", year); return HPTERROR; } if ( day < 1 || day > 366 ) { ms_log (2, "ms_seedtimestr2hptime(): Error with day value: %d\n", day); return HPTERROR; } if ( hour < 0 || hour > 23 ) { ms_log (2, "ms_seedtimestr2hptime(): Error with hour value: %d\n", hour); return HPTERROR; } if ( min < 0 || min > 59 ) { ms_log (2, "ms_seedtimestr2hptime(): Error with minute value: %d\n", min); return HPTERROR; } if ( sec < 0 || sec > 60 ) { ms_log (2, "ms_seedtimestr2hptime(): Error with second value: %d\n", sec); return HPTERROR; } if ( usec < 0 || usec > 999999 ) { ms_log (2, "ms_seedtimestr2hptime(): Error with fractional second value: %d\n", usec); return HPTERROR; } return ms_time2hptime_int (year, day, hour, min, sec, usec);} /* End of ms_seedtimestr2hptime() *//*************************************************************************** * ms_timestr2hptime: * * Convert a generic time string to a high precision epoch time. * SEED time format is "YYYY[/MM/DD HH:MM:SS.FFFF]", the delimiter can * be a dash [-], slash [/], colon [:], or period [.] and between the * date and time a 'T' or a space may be used. The fracttional * seconds must begin with a period [.]. * * The time string can be "short" in which case the omitted values are * assumed to be zero (with the exception of month and day which are * assumed to be 1): "YYYY/MM/DD" assumes HH, MM, SS and FFFF are 0. * The year is required, otherwise there wouldn't be much for a date. * * Ranges are checked for each value. * * Returns epoch time on success and HPTERROR on error. ***************************************************************************/hptime_tms_timestr2hptime (char *timestr){ int fields; int year = 0; int mon = 1; int mday = 1; int day = 1; int hour = 0; int min = 0; int sec = 0; float fusec = 0.0; int usec = 0; fields = sscanf (timestr, "%d%*[-/:.]%d%*[-/:.]%d%*[-/:.T ]%d%*[-/:.]%d%*[- /:.]%d%f", &year, &mon, &mday, &hour, &min, &sec, &fusec); /* Convert fractional seconds to microseconds */ if ( fusec != 0.0 ) { usec = (int) (fusec * 1000000.0 + 0.5); } if ( fields < 1 ) { ms_log (2, "ms_timestr2hptime(): Error converting time string: %s\n", timestr); return HPTERROR; } if ( year < 1900 || year > 3000 ) { ms_log (2, "ms_timestr2hptime(): Error with year value: %d\n", year); return HPTERROR; } if ( mon < 1 || mon > 12 ) { ms_log (2, "ms_timestr2hptime(): Error with month value: %d\n", mon); return HPTERROR; } if ( mday < 1 || mday > 31 ) { ms_log (2, "ms_timestr2hptime(): Error with day value: %d\n", mday); return HPTERROR; } /* Convert month and day-of-month to day-of-year */ if ( ms_md2doy (year, mon, mday, &day) ) { return HPTERROR; } if ( hour < 0 || hour > 23 ) { ms_log (2, "ms_timestr2hptime(): Error with hour value: %d\n", hour); return HPTERROR; } if ( min < 0 || min > 59 ) { ms_log (2, "ms_timestr2hptime(): Error with minute value: %d\n", min); return HPTERROR; } if ( sec < 0 || sec > 60 ) { ms_log (2, "ms_timestr2hptime(): Error with second value: %d\n", sec); return HPTERROR; } if ( usec < 0 || usec > 999999 ) { ms_log (2, "ms_timestr2hptime(): Error with fractional second value: %d\n", usec); return HPTERROR; } return ms_time2hptime_int (year, day, hour, min, sec, usec);} /* End of ms_timestr2hptime() *//*************************************************************************** * ms_genfactmult: * * Generate an approriate SEED sample rate factor and multiplier from * a double precision sample rate. * * Returns 0 on success and -1 on error. ***************************************************************************/intms_genfactmult (double samprate, int16_t *factor, int16_t *multiplier){ int num, den; /* This routine does not support very high or negative sample rates, even though high rates are possible in Mini-SEED */ if ( samprate > 32727.0 || samprate < 0.0 ) { ms_log (2, "ms_genfactmult(): samprate out of range: %g\n", samprate); return -1; } /* If the sample rate is integer set the factor and multipler in the obvious way, otherwise derive a (potentially approximate) numerator and denominator for the given samprate */ if ( (samprate - (int16_t) samprate) < 0.000001 ) { *factor = (int16_t) samprate; if ( *factor ) *multiplier = 1; } else { ms_ratapprox (samprate, &num, &den, 32727, 1e-12); /* Negate the multiplier to denote a division factor */ *factor = (int16_t ) num; *multiplier = (int16_t) -den; } return 0;} /* End of ms_genfactmult() *//*************************************************************************** * ms_ratapprox: * * Find an approximate rational number for a real through continued * fraction expansion. Given a double precsion 'real' find a * numerator (num) and denominator (den) whose absolute values are not * larger than 'maxval' while trying to reach a specified 'precision'. * * Returns the number of iterations performed. ***************************************************************************/intms_ratapprox (double real, int *num, int *den, int maxval, double precision){ double realj, preal; char pos; int pnum, pden; int iterations = 1; int Aj1, Aj2, Bj1, Bj2; int bj = 0; int Aj = 0; int Bj = 1; if ( real >= 0.0 ) { pos = 1; realj = real; } else { pos = 0; realj = -real; } preal = realj; bj = (int) (realj + precision); realj = 1 / (realj - bj); Aj = bj; Aj1 = 1; Bj = 1; Bj1 = 0; *num = pnum = Aj; *den = pden = Bj; if ( !pos ) *num = -*num; while ( ms_dabs(preal - (double)Aj/(double)Bj) > precision && Aj < maxval && Bj < maxval ) { Aj2 = Aj1; Aj1 = Aj; Bj2 = Bj1; Bj1 = Bj; bj = (int) (realj + precision); realj = 1 / (realj - bj); Aj = bj * Aj1 + Aj2; Bj = bj * Bj1 + Bj2; *num = pnum; *den = pden; if ( !pos ) *num = -*num; pnum = Aj; pden = Bj; iterations++; } if ( pnum < maxval && pden < maxval ) { *num = pnum; *den = pden; if ( !pos ) *num = -*num; } return iterations;}/*************************************************************************** * ms_bigendianhost: * * Determine the byte order of the host machine. Due to the lack of * portable defines to determine host byte order this run-time test is * provided. The code below actually tests for little-endianess, the * only other alternative is assumed to be big endian. * * Returns 0 if the host is little endian, otherwise 1. ***************************************************************************/intms_bigendianhost (){ int16_t host = 1; return !(*((int8_t *)(&host)));} /* End of ms_bigendianhost() *//*************************************************************************** * ms_dabs: * * Determine the absolute value of an input double, actually just test * if the input double is positive multiplying by -1.0 if not and * return it. * * Returns the positive value of input double. ***************************************************************************/doublems_dabs (double val){ if ( val < 0.0 ) val *= -1.0; return val;} /* End of ms_dabs() */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -