diff --git a/ChangeLog b/ChangeLog index be5f8ba..4cea15f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2015.213: 2.17 + - Round Fixed Section Data Header start time values to the nearest + tenth of millisecond and restrict the microsecond offset value + to a range between -50 and +49 as recommended in SEED. Previously + start times were truncated at tenths of millisecond resolution + and the microsecond offset value was between 0 and +99. This also + addresses a bug where microsecond offsets were off by 100ms for times + before Jan 1 1970. Thanks to Lion Krischer for reporting. + + Note to future hackers: the definition of HPTMODULUS governing the + time tick interval for high precision time values implies that this + tick interval may be changed. In reality, this should not be changed + from the default, microsecond tick value without thorough testing. + Some logic is know to be dependent on the microsecond tick. + 2015.134: 2.16m - Add defines for needed integer types and macros from inttypes.h missing in older MSVC versions. MSVC 2010 and later appear to have diff --git a/Makefile b/Makefile index 5f6f54d..e7d6852 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ # CFLAGS : Specify compiler options to use MAJOR_VER = 2 -MINOR_VER = 16 +MINOR_VER = 17 CURRENT_VER = $(MAJOR_VER).$(MINOR_VER) COMPAT_VER = $(MAJOR_VER).$(MINOR_VER) diff --git a/genutils.c b/genutils.c index 4258b12..80da70f 100644 --- a/genutils.c +++ b/genutils.c @@ -7,7 +7,7 @@ * ORFEUS/EC-Project MEREDIAN * IRIS Data Management Center * - * modified: 2015.108 + * modified: 2015.213 ***************************************************************************/ #include @@ -589,6 +589,46 @@ ms_btime2seedtimestr (BTime *btime, char *seedtimestr) } /* End of ms_btime2seedtimestr() */ +/*************************************************************************** + * ms_hptime2tomsusecoffset: + * + * Convert a high precision epoch time to a time value in tenths of + * milliseconds (aka toms) and a microsecond offset (aka usecoffset). + * + * The tenths of milliseconds value will be rounded to the nearest + * value having a microsecond offset value between -50 to +49. + * + * Returns 0 on success and -1 on error. + ***************************************************************************/ +int +ms_hptime2tomsusecoffset (hptime_t hptime, hptime_t *toms, int8_t *usecoffset) +{ + if ( toms == NULL || usecoffset == NULL ) + return -1; + + /* Split time into tenths of milliseconds and microseconds */ + *toms = hptime / (HPTMODULUS / 10000); + *usecoffset = hptime - (*toms * (HPTMODULUS / 10000)); + + /* Round tenths and adjust microsecond offset to -50 to +49 range */ + if ( *usecoffset > 49 && *usecoffset < 100 ) + { + *toms += 1; + *usecoffset -= 100; + } + else if ( *usecoffset < -50 && *usecoffset > -100 ) + { + *toms -= 1; + *usecoffset += 100; + } + + /* Convert tenths of milliseconds to be in hptime_t (HPTMODULUS) units */ + *toms *= (HPTMODULUS / 10000); + + return 0; +} /* End of ms_hptime2tomsusecoffset() */ + + /*************************************************************************** * ms_hptime2btime: * diff --git a/libmseed.h b/libmseed.h index 867f343..e6033c4 100644 --- a/libmseed.h +++ b/libmseed.h @@ -30,8 +30,8 @@ extern "C" { #include "lmplatform.h" -#define LIBMSEED_VERSION "2.16m" -#define LIBMSEED_RELEASE "2015.134" +#define LIBMSEED_VERSION "2.17" +#define LIBMSEED_RELEASE "2015.213" #define MINRECLEN 128 /* Minimum Mini-SEED record length, 2^7 bytes */ /* Note: the SEED specification minimum is 256 */ @@ -658,6 +658,7 @@ extern hptime_t ms_btime2hptime (BTime *btime); extern char* ms_btime2isotimestr (BTime *btime, char *isotimestr); extern char* ms_btime2mdtimestr (BTime *btime, char *mdtimestr); extern char* ms_btime2seedtimestr (BTime *btime, char *seedtimestr); +extern int ms_hptime2tomsusecoffset (hptime_t hptime, hptime_t *toms, int8_t *usecoffset); extern int ms_hptime2btime (hptime_t hptime, BTime *btime); extern char* ms_hptime2isotimestr (hptime_t hptime, char *isotimestr, flag subsecond); extern char* ms_hptime2mdtimestr (hptime_t hptime, char *mdtimestr, flag subsecond); diff --git a/msrutils.c b/msrutils.c index a5f36bb..876e9ab 100644 --- a/msrutils.c +++ b/msrutils.c @@ -7,7 +7,7 @@ * ORFEUS/EC-Project MEREDIAN * IRIS Data Management Center * - * modified: 2015.108 + * modified: 2015.213 ***************************************************************************/ #include @@ -257,6 +257,8 @@ int msr_normalize_header ( MSRecord *msr, flag verbose ) { struct blkt_link_s *cur_blkt; + hptime_t hptimems; + int8_t usecoffset; char seqnum[7]; int offset = 0; int blktcnt = 0; @@ -266,6 +268,9 @@ msr_normalize_header ( MSRecord *msr, flag verbose ) if ( ! msr ) return -1; + /* Get start time rounded to tenths of milliseconds and microsecond offset */ + ms_hptime2tomsusecoffset (msr->starttime, &hptimems, &usecoffset); + /* Update values in fixed section of data header */ if ( msr->fsdh ) { @@ -285,7 +290,7 @@ msr_normalize_header ( MSRecord *msr, flag verbose ) ms_strncpopen (msr->fsdh->station, msr->station, 5); ms_strncpopen (msr->fsdh->location, msr->location, 2); ms_strncpopen (msr->fsdh->channel, msr->channel, 3); - ms_hptime2btime (msr->starttime, &(msr->fsdh->start_time)); + ms_hptime2btime (hptimems, &(msr->fsdh->start_time)); /* When the sampling rate is <= 32767 Hertz determine the factor * and multipler through rational approximation. For higher rates @@ -311,7 +316,7 @@ msr_normalize_header ( MSRecord *msr, flag verbose ) msr->fsdh->blockette_offset = 0; } - /* Traverse blockette chain and performs necessary updates*/ + /* Traverse blockette chain and perform necessary updates*/ cur_blkt = msr->blkts; if ( cur_blkt && verbose > 2 ) @@ -352,14 +357,7 @@ msr_normalize_header ( MSRecord *msr, flag verbose ) else if ( cur_blkt->blkt_type == 1001 ) { - hptime_t sec, usec; - - /* Insert microseconds offset */ - sec = msr->starttime / (HPTMODULUS / 10000); - usec = msr->starttime - (sec * (HPTMODULUS / 10000)); - usec /= (HPTMODULUS / 1000000); - - msr->Blkt1001->usec = (int8_t) usec; + msr->Blkt1001->usec = usecoffset; offset += sizeof (struct blkt_1001_s); } diff --git a/pack.c b/pack.c index a64e171..e520cdb 100644 --- a/pack.c +++ b/pack.c @@ -7,7 +7,7 @@ * Written by Chad Trabant, * IRIS Data Management Center * - * modified: 2015.062 + * modified: 2015.213 ***************************************************************************/ #include @@ -847,6 +847,8 @@ msr_update_header ( MSRecord *msr, char *rawrec, flag swapflag, struct blkt_1001_s *blkt1001, flag verbose ) { struct fsdh_s *fsdh; + hptime_t hptimems; + int8_t usecoffset; char seqnum[7]; if ( ! msr || ! rawrec ) @@ -861,8 +863,11 @@ msr_update_header ( MSRecord *msr, char *rawrec, flag swapflag, snprintf (seqnum, 7, "%06d", msr->sequence_number); memcpy (fsdh->sequence_number, seqnum, 6); + /* Get start time rounded to tenths of milliseconds and microsecond offset */ + ms_hptime2tomsusecoffset (msr->starttime, &hptimems, &usecoffset); + /* Update fixed-section start time */ - ms_hptime2btime (msr->starttime, &(fsdh->start_time)); + ms_hptime2btime (hptimems, &(fsdh->start_time)); /* Swap byte order? */ if ( swapflag ) @@ -870,21 +875,14 @@ msr_update_header ( MSRecord *msr, char *rawrec, flag swapflag, MS_SWAPBTIME (&fsdh->start_time); } - /* Update microseconds if Blockette 1001 is present */ + /* Update microsecond offset value if Blockette 1001 is present */ if ( msr->Blkt1001 && blkt1001 ) { - hptime_t sec, usec; - - /* Calculate microseconds offset */ - sec = msr->starttime / (HPTMODULUS / 10000); - usec = msr->starttime - (sec * (HPTMODULUS / 10000)); - usec /= (HPTMODULUS / 1000000); - /* Update microseconds offset in blockette chain entry */ - msr->Blkt1001->usec = (int8_t) usec; + msr->Blkt1001->usec = usecoffset; /* Update microseconds offset in packed header */ - blkt1001->usec = (int8_t) usec; + blkt1001->usec = usecoffset; } return 0;