Merged Ralph's add-epicstime-from-gmtm branch

This commit is contained in:
Andrew Johnson
2016-10-04 18:04:26 -05:00
3 changed files with 118 additions and 12 deletions

View File

@@ -278,20 +278,100 @@ epicsTime::operator gm_tm_nano_sec () const
//
epicsTime::epicsTime (const local_tm_nano_sec &tm)
{
static const time_t mktimeFailure = static_cast <time_t> (-1);
time_t_wrapper ansiTimeTicks;
struct tm tmp = tm.ansi_tm;
time_t_wrapper ansiTimeTicks = { mktime (&tmp) };
ansiTimeTicks.ts = mktime (&tmp);
if (ansiTimeTicks.ts == mktimeFailure) {
static const time_t mktimeError = static_cast <time_t> (-1);
if (ansiTimeTicks.ts == mktimeError) {
throwWithLocation ( formatProblemWithStructTM () );
}
*this = epicsTime (ansiTimeTicks);
unsigned long nSec = tm.nSec;
// Handle nSec overflows
if (nSec >= nSecPerSec) {
ansiTimeTicks.ts += nSec / nSecPerSec;
nSec %= nSecPerSec;
}
unsigned long nSecAdj = tm.nSec % nSecPerSec;
unsigned long secAdj = tm.nSec / nSecPerSec;
*this = epicsTime ( this->secPastEpoch+secAdj, this->nSec+nSecAdj );
// Do the epoch conversion
*this = epicsTime (ansiTimeTicks);
// Set the nSec part
this->nSec = nSec;
}
//
// epicsTime (const gm_tm_nano_sec &tm)
//
// do conversion avoiding the timezone mechanism
static inline int is_leap(int year)
{
if (year % 400 == 0)
return 1;
if (year % 100 == 0)
return 0;
if (year % 4 == 0)
return 1;
return 0;
}
static inline int days_from_0(int year)
{
year--;
return 365 * year + (year / 400) - (year / 100) + (year / 4);
}
static inline int days_from_1970(int year)
{
static const int days_from_0_to_1970 = days_from_0(1970);
return days_from_0(year) - days_from_0_to_1970;
}
static inline int days_from_1jan(int year, int month, int day)
{
static const int days[2][12] =
{
{ 0,31,59,90,120,151,181,212,243,273,304,334},
{ 0,31,60,91,121,152,182,213,244,274,305,335}
};
return days[is_leap(year)][month-1] + day - 1;
}
epicsTime::epicsTime (const gm_tm_nano_sec &tm)
{
int year = tm.ansi_tm.tm_year + 1900;
int month = tm.ansi_tm.tm_mon;
if (month > 11) {
year += month / 12;
month %= 12;
} else if (month < 0) {
int years_diff = (-month + 11) / 12;
year -= years_diff;
month += 12 * years_diff;
}
month++;
int day = tm.ansi_tm.tm_mday;
int day_of_year = days_from_1jan(year, month, day);
int days_since_epoch = days_from_1970(year) + day_of_year;
time_t_wrapper ansiTimeTicks;
ansiTimeTicks.ts = ((days_since_epoch
* 24 + tm.ansi_tm.tm_hour)
* 60 + tm.ansi_tm.tm_min)
* 60 + tm.ansi_tm.tm_sec;
unsigned long nSec = tm.nSec;
// Handle nSec overflows
if (nSec >= nSecPerSec) {
ansiTimeTicks.ts += nSec / nSecPerSec;
nSec %= nSecPerSec;
}
// Do the epoch conversion
*this = epicsTime(ansiTimeTicks);
// Set the nSec part
this->nSec = nSec;
}
//
@@ -905,6 +985,19 @@ extern "C" {
}
return epicsTimeOK;
}
epicsShareFunc int epicsShareAPI epicsTimeFromGMTM (epicsTimeStamp *pDest, const struct tm *pSrc, unsigned long nSecSrc)
{
try {
gm_tm_nano_sec tmns;
tmns.ansi_tm = *pSrc;
tmns.nSec = nSecSrc;
*pDest = epicsTime (tmns);
}
catch (...) {
return epicsTimeERROR;
}
return epicsTimeOK;
}
epicsShareFunc int epicsShareAPI epicsTimeToTimespec (struct timespec *pDest, const epicsTimeStamp *pSrc)
{
try {
@@ -1036,4 +1129,3 @@ extern "C" {
}
}
}

View File

@@ -105,10 +105,12 @@ public:
epicsTime & operator = ( const local_tm_nano_sec & );
/*
* convert to ANSI Cs "struct tm" (with nano seconds)
* convert to and from ANSI Cs "struct tm" (with nano seconds)
* adjusted for GM time (UTC)
*/
operator gm_tm_nano_sec () const;
epicsTime ( const gm_tm_nano_sec & );
epicsTime & operator = ( const gm_tm_nano_sec & );
/* convert to and from POSIX RTs "struct timespec" */
operator struct timespec () const;
@@ -194,13 +196,15 @@ epicsShareFunc int epicsShareAPI epicsTimeToTime_t (
epicsShareFunc int epicsShareAPI epicsTimeFromTime_t (
epicsTimeStamp * pDest, time_t src );
/*convert to and from ANSI C's "struct tm" with nano seconds */
/* convert to and from ANSI C's "struct tm" with nano seconds */
epicsShareFunc int epicsShareAPI epicsTimeToTM (
struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc );
epicsShareFunc int epicsShareAPI epicsTimeToGMTM (
struct tm * pDest, unsigned long * pNSecDest, const epicsTimeStamp * pSrc );
epicsShareFunc int epicsShareAPI epicsTimeFromTM (
epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc );
epicsShareFunc int epicsShareAPI epicsTimeFromGMTM (
epicsTimeStamp * pDest, const struct tm * pSrc, unsigned long nSecSrc );
/* convert to and from POSIX RT's "struct timespec" */
epicsShareFunc int epicsShareAPI epicsTimeToTimespec (
@@ -312,6 +316,11 @@ inline epicsTime & epicsTime::operator = ( const local_tm_nano_sec & rhs )
return *this = epicsTime ( rhs );
}
inline epicsTime & epicsTime::operator = ( const gm_tm_nano_sec & rhs )
{
return *this = epicsTime ( rhs );
}
inline epicsTime & epicsTime::operator = ( const struct timespec & rhs )
{
*this = epicsTime ( rhs );

View File

@@ -48,7 +48,7 @@ MAIN(epicsTimeTest)
const int wasteTime = 100000;
const int nTimes = 10;
testPlan(15 + nTimes * 18);
testPlan(15 + nTimes * 19);
try {
const epicsTimeStamp epochTS = {0, 0};
@@ -205,6 +205,11 @@ MAIN(epicsTimeTest)
epicsTime beginANSI = ansiDate;
testOk1(beginANSI + diff == now);
// test struct gmtm round-trip conversion
gm_tm_nano_sec ansiGmDate = begin;
epicsTime beginGMANSI = ansiGmDate;
testOk1(beginGMANSI + diff == now);
// test struct timespec round-trip conversion
struct timespec ts = begin;
epicsTime beginTS = ts;