--- G:/sa_eckhardt-neu/boost-trunk/boost/date_time/Kopie (2) von c_time.hpp Mi Feb 1 18:16:41 2012 +++ G:/sa_eckhardt-neu/boost-trunk/boost/date_time/c_time.hpp Do Feb 2 16:18:15 2012 @@ -15,6 +15,11 @@ */ #include + +#if defined(UNDER_CE) +#include +#endif + #include // to be able to convert from string literals to exceptions #include #include @@ -48,6 +53,12 @@ * it will point to the result of the corresponding function. * All functions do proper checking of the C function results and throw * exceptions on error. Therefore the functions will never return NULL. + * + * Another goal here is to provide a workaround for the complete lack of + * functions like time(), gmtime() and localtime() under MS Windows CE. IN + * CE5, these functions were still declared in time.h (and imported into + * namespace std by STLport), but they weren't defined anywhere, leading + * to linker errors. */ struct c_time { public: @@ -92,36 +103,151 @@ #if (defined(_MSC_VER) && (_MSC_VER >= 1400)) #pragma warning(push) // preserve warning settings -#pragma warning(disable : 4996) // disable depricated localtime/gmtime warning on vc8 +#pragma warning(disable : 4996) // disable deprecated localtime/gmtime warning on vc8 #endif // _MSC_VER >= 1400 //! requires a pointer to a user created std::tm struct inline static std::tm* localtime(const std::time_t* t, std::tm* result) { +#if !defined(UNDER_CE) result = std::localtime(t); if (!result) boost::throw_exception(std::runtime_error("could not convert calendar time to local time")); return result; +#else + /* convert... + 0. time_t to int64_t to avoid overflows + 1. epoch beginning 1970 to one beginning 1601 + 2. seconds to 100ns + 3. int64_t to FILETIME */ + int64_t t64 = static_cast(*t); + t64 += 11644473600; + t64 *= 10000000; + FILETIME utc_time; + utc_time.dwLowDateTime = static_cast(t64 & 0xFFFFFFFF); + utc_time.dwHighDateTime= static_cast(t64 >> 32); + // convert to local time + FILETIME local_time; + if(!FileTimeToLocalFileTime(&utc_time, &local_time)) + boost::throw_exception(std::runtime_error("could not convert calendar time to local time")); + // split into year, month, day etc + SYSTEMTIME st; + if(!FileTimeToSystemTime(&local_time, &st)) + boost::throw_exception(std::runtime_error("could not convert calendar time to local time")); + systime_to_tm(result, st); + /* I'm not sure if MS Windows CE actually supports things like DST, at + least I haven't found a way to retrieve the info. For that reason, use + -1 to mark the info as not available. */ + result->tm_isdst = -1; + return result; +#endif } //! requires a pointer to a user created std::tm struct inline static std::tm* gmtime(const std::time_t* t, std::tm* result) { +#if !defined(UNDER_CE) result = std::gmtime(t); if (!result) boost::throw_exception(std::runtime_error("could not convert calendar time to UTC time")); return result; +#else + /* convert... + 0. time_t to int64_t to avoid overflows + 1. epoch beginning 1970 to one beginning 1601 + 2. seconds to 100ns + 3. int64_t to FILETIME */ + int64_t t64 = static_cast(*t); + t64 += 11644473600; + t64 *= 10000000; + FILETIME utc_time; + utc_time.dwLowDateTime = static_cast(t64 & 0xFFFFFFFF); + utc_time.dwHighDateTime= static_cast(t64 >> 32); + // split into year, month, day etc + SYSTEMTIME st; + if(!FileTimeToSystemTime(&utc_time, &st)) + boost::throw_exception(std::runtime_error("could not convert calendar time to local time")); + systime_to_tm(result, st); + /* MSVC8 implementation always sets tm_isdst=0 in gmtime(), using a + German MS Windows XP, not sure if that is correct... */ + result->tm_isdst = 0; + return result; +#endif } #if (defined(_MSC_VER) && (_MSC_VER >= 1400)) #pragma warning(pop) // restore warnings to previous state #endif // _MSC_VER >= 1400 #endif - - std::time_t time(std::time_t* t) + /* This wrapper for time() is to work around systems (i.e. MS Windows CE) + that lack a working time() function. */ + inline static std::time_t time(time_t* p) { - return std::time(t); +#if !defined(UNDER_CE) + return std::time(p); +#else + SYSTEMTIME systime; + GetSystemTime(&systime); + FILETIME ft; + if(!SystemTimeToFileTime(&systime, &ft)) + boost::throw_exception(std::runtime_error("could not convert local time to file time")); + /* convert + 1. FILETIME to int64_t + 2. 100ns to seconds + 3. epoch beginning 1601 to one beginning 1970 + 4. int64_t to time_t */ + int64_t t64 = (static_cast(ft.dwHighDateTime) << 32) + ft.dwLowDateTime; + t64 = (t64 + 5000000) / 10000000; + t64 -= 11644473600; + std::time_t res = static_cast(t64); + // make sure the static cast didn't truncate the result + if(res != t64) + boost::throw_exception(std::runtime_error("could not convert t64 to time_t")); + if(p) + *p = res; + return res; +#endif } +#if defined(UNDER_CE) + private: + /* utility function to convert a SYSTIME to a std::tm + Most fields are equal or similar, but the day of the year requires some + computations. */ + inline static void systime_to_tm(std::tm* result, SYSTEMTIME const& st) + { + // assign the common values + result->tm_sec = st.wSecond; + result->tm_min = st.wMinute; + result->tm_hour = st.wHour; + result->tm_mday = st.wDay; + result->tm_mon = st.wMonth - 1; + result->tm_year = st.wYear - 1900; + result->tm_wday = st.wDayOfWeek; + // compute day of year + bool leapyear; + if((st.wYear % 1000) == 0) + leapyear = true; + else if((st.wYear % 100) == 0) + leapyear = false; + else if((st.wYear % 4) == 0) + leapyear = true; + else + leapyear = false; + result->tm_yday = result->tm_mday - 1; + if(leapyear) + { + int const dpm[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + for(int i=0; i!=result->tm_mon; ++i) + result->tm_yday += dpm[i]; + } + else + { + int const dpm[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + for(int i=0; i!=result->tm_mon; ++i) + result->tm_yday += dpm[i]; + } + } +#endif }; }} // namespaces