From b32127c5de8db67a9bcaaba2bf6338a12419cdfd Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 29 Jan 2014 16:52:22 -0600 Subject: [PATCH] libCom: Fix epicsTime::strftime() roll-over bug Fractional seconds could round-up to .000 without incrementing the integer seconds. We can't actually do the latter, so we prevent the roll-over and clamp at all 9's instead. Idea from Eric Norum. --- src/libCom/osi/epicsTime.cpp | 6 ++++-- src/libCom/test/epicsTimeTest.cpp | 14 +++++++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/libCom/osi/epicsTime.cpp b/src/libCom/osi/epicsTime.cpp index ef6437ffa..414bd5d4f 100644 --- a/src/libCom/osi/epicsTime.cpp +++ b/src/libCom/osi/epicsTime.cpp @@ -554,9 +554,11 @@ size_t epicsTime::strftime ( static_cast < unsigned long > ( 1e1 ), static_cast < unsigned long > ( 1e0 ) }; - // round and convert nanosecs to integer of correct range + // round without overflowing into whole seconds unsigned long frac = tmns.nSec + div[fracWid] / 2; - frac %= static_cast < unsigned long > ( 1e9 ); + if (frac >= nSecPerSec) + frac = nSecPerSec - 1; + // convert nanosecs to integer of correct range frac /= div[fracWid]; char fracFormat[32]; sprintf ( fracFormat, "%%0%lulu", fracWid ); diff --git a/src/libCom/test/epicsTimeTest.cpp b/src/libCom/test/epicsTimeTest.cpp index c108eca7f..83d0a8a07 100644 --- a/src/libCom/test/epicsTimeTest.cpp +++ b/src/libCom/test/epicsTimeTest.cpp @@ -48,7 +48,7 @@ MAIN(epicsTimeTest) const int wasteTime = 100000; const int nTimes = 10; - testPlan(12 + nTimes * 18); + testPlan(15 + nTimes * 18); try { const epicsTimeStamp epochTS = {0, 0}; @@ -96,6 +96,10 @@ MAIN(epicsTimeTest) et.strftime(buf, sizeof(buf), pFormat); testOk(strcmp(buf, "1990-01-01 00.098765432") == 0, "'%s' => '%s'", pFormat, buf); + pFormat = "%S.%03f"; + et.strftime(buf, sizeof(buf), pFormat); + testOk(strcmp(buf, "00.099") == 0, "'%s' => '%s'", pFormat, buf); + pFormat = "%S.%04f"; et.strftime(buf, sizeof(buf), pFormat); testOk(strcmp(buf, "00.0988") == 0, "'%s' => '%s'", pFormat, buf); @@ -113,6 +117,14 @@ MAIN(epicsTimeTest) et.strftime(smbuf, sizeof(smbuf), pFormat); testOk(strcmp(smbuf, "00.*") == 0, "'%s' => '%s'", pFormat, smbuf); + pFormat = "%S.%03f"; + (et + 0.9).strftime(buf, sizeof(buf), pFormat); + testOk(strcmp(buf, "00.999") == 0, "0.998765 => '%s'", buf); + + pFormat = "%S.%03f"; + (et + 0.901).strftime(buf, sizeof(buf), pFormat); + testOk(strcmp(buf, "00.999") == 0, "0.999765 => '%s'", buf); + pFormat = "%%S.%%05f"; et.strftime(buf, sizeof(buf), pFormat); testOk(strcmp(buf, "%S.%05f") == 0, "'%s' => '%s'", pFormat, buf);