> On Jan 31, 2008, at 05:22 , Denison, PN (Peter) asked:
>>
>> Can I replace this code in epicsTimeLoadTimeInit with a constant?
Kay-Uwe Kasemir wrote:
Yes, make it a constant.
No, don't. Apply the attached patch instead, which is a diff between
R3.14.9 and the current head of the R3.14 branch and should work in all
timezones.
The Posix spec apparently does not require that a time_t be expressed in
seconds, although Unix historically has used that. The existing
(broken) code does not make that assumption, and neither does my patched
version (which I did tell Peter about several months ago), but a using
constant probably does.
- Andrew
--
When a distinguished but elderly scientist states that something is
possible, he is almost certainly right. When he states that something
is impossible, he is very probably wrong. -- Arthur C. Clarke
Index: epicsTime.cpp
===================================================================
RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/libCom/osi/epicsTime.cpp,v
retrieving revision 1.25.2.15
retrieving revision 1.25.2.18
diff -u -b -r1.25.2.15 -r1.25.2.18
--- epicsTime.cpp 2 Jan 2007 19:37:57 -0000 1.25.2.15
+++ epicsTime.cpp 13 Nov 2007 22:54:20 -0000 1.25.2.18
@@ -1,10 +1,9 @@
/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* Copyright (c) 2007 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* epicsTime.cpp */
@@ -44,17 +43,19 @@
// useful public constants
//
static const unsigned mSecPerSec = 1000u;
-static const unsigned uSecPerSec = 1000u * mSecPerSec;
-static const unsigned nSecPerSec = 1000u * uSecPerSec;
+static const unsigned uSecPerMSec = 1000u;
+static const unsigned uSecPerSec = uSecPerMSec * mSecPerSec;
static const unsigned nSecPerUSec = 1000u;
-static const unsigned secPerMin = 60u;
+static const unsigned nSecPerSec = nSecPerUSec * uSecPerSec;
static const unsigned nSecFracDigits = 9u;
-static const unsigned tmStructEpochYear = 1900;
-
+static const unsigned tmEpochYear = 1900;
+static const unsigned ansiEpochYear = 1970;
static const unsigned epicsEpochYear = 1990;
-static const unsigned epicsEpocMonth = 0; // January
-static const unsigned epicsEpocDayOfTheMonth = 1; // the 1st day of the month
+
+static const unsigned epochMonth = 0; // January
+static const unsigned epochDayOfTheMonth = 1; // the 1st
+
//
// epicsTime (const unsigned long secIn, const unsigned long nSecIn)
@@ -81,53 +82,47 @@
//
epicsTimeLoadTimeInit::epicsTimeLoadTimeInit ()
{
- static const time_t ansiEpoch = 0;
- double secWest;
-
- {
- time_t current = time ( NULL );
- time_t error;
- struct tm date; // vxWorks 6.0 requires "struct" here
-
- int status = epicsTime_gmtime ( ¤t, &date );
- assert ( status == epicsTimeOK );
- error = mktime ( &date );
- assert ( error != (time_t) - 1 );
- secWest = difftime ( error, current );
- }
-
- {
- time_t first = static_cast<time_t> (0);
- time_t last = static_cast<time_t> (1);
- this->time_tSecPerTick = difftime (last, first);
- }
-
- {
- struct tm tmEpicsEpoch;
- time_t epicsEpoch;
-
- tmEpicsEpoch.tm_sec = 0;
- tmEpicsEpoch.tm_min = 0;
- tmEpicsEpoch.tm_hour = 0;
- tmEpicsEpoch.tm_mday = epicsEpocDayOfTheMonth;
- tmEpicsEpoch.tm_mon = epicsEpocMonth;
- tmEpicsEpoch.tm_year = epicsEpochYear - tmStructEpochYear;
- // must not correct for DST because secWest does
- // not include a DST offset
- tmEpicsEpoch.tm_isdst = 0;
-
- epicsEpoch = mktime (&tmEpicsEpoch);
- assert (epicsEpoch!=(time_t)-1);
- this->epicsEpochOffset = difftime ( epicsEpoch, ansiEpoch ) - secWest;
- }
-
- if ( this->time_tSecPerTick == 1.0 && this->epicsEpochOffset <= ULONG_MAX &&
- this->epicsEpochOffset >= 0 ) {
+ // All we know about time_t is that it is an arithmetic type.
+ time_t t_zero = static_cast<time_t> (0);
+ time_t t_one = static_cast<time_t> (1);
+ this->time_tSecPerTick = difftime (t_one, t_zero);
+
+ /* We calculate the difference in seconds between the ANSI and EPICS
+ * epochs (1970-1-1, 1990-1-1). However mktime() takes a local time
+ * and adds a timezone-specified Daylight Savings Time offset to the
+ * result it returns. Luckily we only need the time difference in
+ * seconds between the two epochs, so the two DST corrections cancel
+ * each other out. We offset the local time used by 12 hours so the
+ * ANSI result can never go negative whatever timezone we're in.
+ */
+
+ struct tm tmEpoch;
+ tmEpoch.tm_sec = 0;
+ tmEpoch.tm_min = 0;
+ tmEpoch.tm_hour = 12;
+ tmEpoch.tm_mday = epochDayOfTheMonth;
+ tmEpoch.tm_mon = epochMonth;
+ tmEpoch.tm_isdst = 0;
+
+ tmEpoch.tm_year = ansiEpochYear - tmEpochYear;
+ time_t ansiEpoch = mktime(&tmEpoch);
+ assert(ansiEpoch != (time_t) -1);
+
+ tmEpoch.tm_year = epicsEpochYear - tmEpochYear;
+ time_t epicsEpoch = mktime(&tmEpoch);
+ assert(epicsEpoch != (time_t) -1);
+
+ this->epicsEpochOffset = difftime (epicsEpoch, ansiEpoch);
+
+ if (this->time_tSecPerTick == 1.0 &&
+ this->epicsEpochOffset <= ULONG_MAX &&
+ this->epicsEpochOffset >= 0) {
+ // We can use simpler code on Posix-compliant systems
this->useDiffTimeOptimization = true;
this->epicsEpochOffsetAsAnUnsignedLong =
- static_cast < unsigned long > ( this->epicsEpochOffset );
- }
- else {
+ static_cast<unsigned long>(this->epicsEpochOffset);
+ } else {
+ // Forced to use the slower but correct code
this->useDiffTimeOptimization = false;
this->epicsEpochOffsetAsAnUnsignedLong = 0;
}
@@ -205,7 +200,8 @@
}
}
-epicsTime::epicsTime () : secPastEpoch(0u), nSec(0u) {}
+epicsTime::epicsTime () :
+ secPastEpoch(0u), nSec(0u) {}
epicsTime::epicsTime (const epicsTime &t) :
secPastEpoch (t.secPastEpoch), nSec (t.nSec) {}
@@ -230,7 +226,7 @@
return epicsTime ( current );
}
-void epicsTime::synchronize () {} // depricated
+void epicsTime::synchronize () {} // deprecated
//
// operator time_t_wrapper ()
@@ -268,7 +264,7 @@
int status = epicsTime_localtime ( &ansiTimeTicks.ts, &tm.ansi_tm );
if ( status != epicsTimeOK ) {
- throw std::logic_error ( "epicsTime_gmtime failed" );
+ throw std::logic_error ( "epicsTime_localtime failed" );
}
tm.nSec = this->nSec;
@@ -583,7 +579,7 @@
frac %= static_cast < unsigned long > ( 1e9 );
frac /= div[fracWid];
char fracFormat[32];
- sprintf ( fracFormat, "%%0%uu", fracWid );
+ sprintf ( fracFormat, "%%0%lulu", fracWid );
int status = epicsSnprintf ( pBufCur, bufLenLeft, fracFormat, frac );
if ( status > 0 ) {
unsigned long nChar = static_cast < unsigned long > ( status );
- Replies:
- Re: Problems within epicsTime.cpp Andrew Johnson
- RE: Problems within epicsTime.cpp Denison, PN (Peter)
- References:
- Problems within epicsTime.cpp Denison, PN (Peter)
- Re: Problems within epicsTime.cpp Kay-Uwe Kasemir
- Navigate by Date:
- Prev:
Re: Problems within epicsTime.cpp Kay-Uwe Kasemir
- Next:
Re: Problems within epicsTime.cpp Andrew Johnson
- Index:
2002
2003
2004
2005
2006
2007
<2008>
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
- Navigate by Thread:
- Prev:
Re: Problems within epicsTime.cpp Kay-Uwe Kasemir
- Next:
Re: Problems within epicsTime.cpp Andrew Johnson
- Index:
2002
2003
2004
2005
2006
2007
<2008>
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
|