diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index af7c8bffe..3de7d4b4f 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -13,6 +13,13 @@ +
Simpler versions of the epicsTime_gmtime() and epicsTime_localtime() +routines have been included in the Windows implementations, and a new test +program added. The original versions do not report DST status properly. Fixes +Launchpad bug 1528284.
+If EPICS Base is built with readline support, any IOC that calls epicsExit()
diff --git a/src/libCom/osi/os/WIN32/osdTime.cpp b/src/libCom/osi/os/WIN32/osdTime.cpp
index eb2c7ad9d..239d21a2c 100644
--- a/src/libCom/osi/os/WIN32/osdTime.cpp
+++ b/src/libCom/osi/os/WIN32/osdTime.cpp
@@ -121,148 +121,31 @@ static int osdTimeGetCurrent ( epicsTimeStamp *pDest )
return epicsTimeOK;
}
-inline void UnixTimeToFileTime ( const time_t * pAnsiTime, LPFILETIME pft )
-{
- LONGLONG ll = Int32x32To64 ( *pAnsiTime, 10000000 ) + LL_CONSTANT(116444736000000000);
- pft->dwLowDateTime = static_cast < DWORD > ( ll );
- pft->dwHighDateTime = static_cast < DWORD > ( ll >>32 );
-}
-
-static int daysInMonth[] = { 31, 28, 31, 30, 31, 30, 31,
- 31, 30, 31, 30, 31 };
-
-static bool isLeapYear ( DWORD year )
-{
- if ( (year % 4) == 0 ) {
- return ( ( year % 100 ) != 0 || ( year % 400 ) == 0 );
- } else {
- return false;
- }
-}
-
-static int dayOfYear ( DWORD day, DWORD month, DWORD year )
-{
- DWORD nDays = 0;
- for ( unsigned m = 1; m < month; m++ ) {
- nDays += daysInMonth[m-1];
- if ( m == 2 && isLeapYear(year) ) {
- nDays++;
- }
- }
- return nDays + day;
-}
-
// synthesize a reentrant gmtime on WIN32
int epicsShareAPI epicsTime_gmtime ( const time_t *pAnsiTime, struct tm *pTM )
{
- FILETIME ft;
- UnixTimeToFileTime ( pAnsiTime, &ft );
-
- SYSTEMTIME st;
- BOOL status = FileTimeToSystemTime ( &ft, &st );
- if ( ! status ) {
- return epicsTimeERROR;
+ struct tm * pRet = gmtime ( pAnsiTime );
+ if ( pRet ) {
+ *pTM = *pRet;
+ return epicsTimeOK;
+ }
+ else {
+ return errno;
}
-
- pTM->tm_sec = st.wSecond; // seconds after the minute - [0,59]
- pTM->tm_min = st.wMinute; // minutes after the hour - [0,59]
- pTM->tm_hour = st.wHour; // hours since midnight - [0,23]
- assert ( st.wDay >= 1 && st.wDay <= 31 );
- pTM->tm_mday = st.wDay; // day of the month - [1,31]
- assert ( st.wMonth >= 1 && st.wMonth <= 12 );
- pTM->tm_mon = st.wMonth - 1; // months since January - [0,11]
- assert ( st.wYear >= 1900 );
- pTM->tm_year = st.wYear - 1900; // years since 1900
- pTM->tm_wday = st.wDayOfWeek; // days since Sunday - [0,6]
- pTM->tm_yday = dayOfYear ( st.wDay, st.wMonth, st.wYear ) - 1;
- pTM->tm_isdst = 0;
-
- return epicsTimeOK;
}
// synthesize a reentrant localtime on WIN32
int epicsShareAPI epicsTime_localtime (
const time_t * pAnsiTime, struct tm * pTM )
{
- FILETIME ft;
- UnixTimeToFileTime ( pAnsiTime, & ft );
-
- TIME_ZONE_INFORMATION tzInfo;
- DWORD tzStatus = GetTimeZoneInformation ( & tzInfo );
- if ( tzStatus == TIME_ZONE_ID_INVALID ) {
- return epicsTimeERROR;
+ struct tm * pRet = localtime ( pAnsiTime );
+ if ( pRet ) {
+ *pTM = *pRet;
+ return epicsTimeOK;
}
-
- //
- // There are remarkable weaknessess in the FileTimeToLocalFileTime
- // interface so we dont use it here. Unfortunately, there is no
- // corresponding function that works on file time.
- //
- SYSTEMTIME st;
- BOOL success = FileTimeToSystemTime ( & ft, & st );
- if ( ! success ) {
- return epicsTimeERROR;
+ else {
+ return errno;
}
- SYSTEMTIME lst;
- success = SystemTimeToTzSpecificLocalTime (
- & tzInfo, & st, & lst );
- if ( ! success ) {
- return epicsTimeERROR;
- }
-
- //
- // We must convert back to file time so that we can determine if DST
- // is active...
- //
- FILETIME lft;
- success = SystemTimeToFileTime ( & lst, & lft );
- if ( ! success ) {
- return epicsTimeERROR;
- }
-
- int is_dst = -1; // unknown state of dst
- if ( tzStatus != TIME_ZONE_ID_UNKNOWN &&
- tzInfo.StandardDate.wMonth != 0 &&
- tzInfo.DaylightDate.wMonth != 0) {
- // determine if the specified date is
- // in daylight savings time
- tzInfo.StandardDate.wYear = st.wYear;
- FILETIME StandardDateFT;
- success = SystemTimeToFileTime (
- & tzInfo.StandardDate, & StandardDateFT );
- if ( ! success ) {
- return epicsTimeERROR;
- }
- tzInfo.DaylightDate.wYear = st.wYear;
- FILETIME DaylightDateFT;
- success = SystemTimeToFileTime (
- & tzInfo.DaylightDate, & DaylightDateFT );
- if ( ! success ) {
- return epicsTimeERROR;
- }
- if ( CompareFileTime ( & lft, & DaylightDateFT ) >= 0
- && CompareFileTime ( & lft, & StandardDateFT ) < 0 ) {
- is_dst = 1;
- }
- else {
- is_dst = 0;
- }
- }
-
- pTM->tm_sec = lst.wSecond; // seconds after the minute - [0,59]
- pTM->tm_min = lst.wMinute; // minutes after the hour - [0,59]
- pTM->tm_hour = lst.wHour; // hours since midnight - [0,23]
- assert ( lst.wDay >= 1 && lst.wDay <= 31 );
- pTM->tm_mday = lst.wDay; // day of the month - [1,31]
- assert ( lst.wMonth >= 1 && lst.wMonth <= 12 );
- pTM->tm_mon = lst.wMonth - 1; // months since January - [0,11]
- assert ( lst.wYear >= 1900 );
- pTM->tm_year = lst.wYear - 1900; // years since 1900
- pTM->tm_wday = lst.wDayOfWeek; // days since Sunday - [0,6]
- pTM->tm_yday = dayOfYear ( lst.wDay, lst.wMonth, lst.wYear ) - 1;
- pTM->tm_isdst = is_dst;
-
- return epicsTimeOK;
}
currentTime::currentTime () :
diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile
index e8e94a3e6..7e1b5a020 100644
--- a/src/libCom/test/Makefile
+++ b/src/libCom/test/Makefile
@@ -68,6 +68,10 @@ epicsTimeTest_SRCS += epicsTimeTest.cpp
testHarness_SRCS += epicsTimeTest.cpp
TESTS += epicsTimeTest
+TESTPROD_HOST += epicsTimeZoneTest
+epicsTimeZoneTest_SRCS += epicsTimeZoneTest.c
+TESTS += epicsTimeZoneTest
+
TESTPROD_HOST += epicsThreadTest
epicsThreadTest_SRCS += epicsThreadTest.cpp
testHarness_SRCS += epicsThreadTest.cpp
diff --git a/src/libCom/test/epicsTimeZoneTest.c b/src/libCom/test/epicsTimeZoneTest.c
new file mode 100644
index 000000000..dd12b1acf
--- /dev/null
+++ b/src/libCom/test/epicsTimeZoneTest.c
@@ -0,0 +1,117 @@
+/*************************************************************************\
+* Copyright (c) 2015 Michael Davidsaver
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+#include