Ticket #5428: boost time functions for CE.patch

File boost time functions for CE.patch, 7.0 KB (added by Ulrich Eckhardt <ulrich.eckhardt@…>, 11 years ago)

implementations of time(), localtime(), gmtime() for CE

  • G:/sa_eckhardt-neu/boost-trunk/boost/date_time/

    old new  
    1515*/
    1616
    1717#include <ctime>
     18
     19#if defined(UNDER_CE)
     20#include <windows.h>
     21#endif
     22
    1823#include <string> // to be able to convert from string literals to exceptions
    1924#include <stdexcept>
    2025#include <boost/throw_exception.hpp>
     
    4853   * it will point to the result of the corresponding function.
    4954   * All functions do proper checking of the C function results and throw
    5055   * exceptions on error. Therefore the functions will never return NULL.
     56   *
     57   * Another goal here is to provide a workaround for the complete lack of
     58   * functions like time(), gmtime() and localtime() under MS Windows CE. IN
     59   * CE5, these functions were still declared in time.h (and imported into
     60   * namespace std by STLport), but they weren't defined anywhere, leading
     61   * to linker errors.
    5162   */
    5263  struct c_time {
    5364    public:
     
    92103
    93104#if (defined(_MSC_VER) && (_MSC_VER >= 1400))
    94105#pragma warning(push) // preserve warning settings
    95 #pragma warning(disable : 4996) // disable depricated localtime/gmtime warning on vc8
     106#pragma warning(disable : 4996) // disable deprecated localtime/gmtime warning on vc8
    96107#endif // _MSC_VER >= 1400
    97108      //! requires a pointer to a user created std::tm struct
    98109      inline
    99110      static std::tm* localtime(const std::time_t* t, std::tm* result)
    100111      {
     112#if !defined(UNDER_CE)
    101113        result = std::localtime(t);
    102114        if (!result)
    103115          boost::throw_exception(std::runtime_error("could not convert calendar time to local time"));
    104116        return result;
     117#else
     118        /* convert...
     119         0. time_t to int64_t to avoid overflows
     120         1. epoch beginning 1970 to one beginning 1601
     121         2. seconds to 100ns
     122         3. int64_t to FILETIME */
     123        int64_t t64 = static_cast<int64_t>(*t);
     124        t64 += 11644473600;
     125        t64 *= 10000000;
     126        FILETIME utc_time;
     127        utc_time.dwLowDateTime = static_cast<DWORD>(t64 & 0xFFFFFFFF);
     128        utc_time.dwHighDateTime= static_cast<DWORD>(t64 >> 32);
     129        // convert to local time
     130        FILETIME  local_time;
     131        if(!FileTimeToLocalFileTime(&utc_time, &local_time))
     132          boost::throw_exception(std::runtime_error("could not convert calendar time to local time"));
     133        // split into year, month, day etc
     134        SYSTEMTIME st;
     135        if(!FileTimeToSystemTime(&local_time, &st))
     136          boost::throw_exception(std::runtime_error("could not convert calendar time to local time"));
     137        systime_to_tm(result, st);
     138        /* I'm not sure if MS Windows CE actually supports things like DST, at
     139        least I haven't found a way to retrieve the info. For that reason, use
     140        -1 to mark the info as not available. */
     141        result->tm_isdst = -1;
     142        return result;
     143#endif
    105144      }
    106145      //! requires a pointer to a user created std::tm struct
    107146      inline
    108147      static std::tm* gmtime(const std::time_t* t, std::tm* result)
    109148      {
     149#if !defined(UNDER_CE)
    110150        result = std::gmtime(t);
    111151        if (!result)
    112152          boost::throw_exception(std::runtime_error("could not convert calendar time to UTC time"));
    113153        return result;
     154#else
     155        /* convert...
     156         0. time_t to int64_t to avoid overflows
     157         1. epoch beginning 1970 to one beginning 1601
     158         2. seconds to 100ns
     159         3. int64_t to FILETIME */
     160        int64_t t64 = static_cast<int64_t>(*t);
     161        t64 += 11644473600;
     162        t64 *= 10000000;
     163        FILETIME utc_time;
     164        utc_time.dwLowDateTime = static_cast<DWORD>(t64 & 0xFFFFFFFF);
     165        utc_time.dwHighDateTime= static_cast<DWORD>(t64 >> 32);
     166        // split into year, month, day etc
     167        SYSTEMTIME st;
     168        if(!FileTimeToSystemTime(&utc_time, &st))
     169          boost::throw_exception(std::runtime_error("could not convert calendar time to local time"));
     170        systime_to_tm(result, st);
     171        /* MSVC8 implementation always sets tm_isdst=0 in gmtime(), using a
     172        German MS Windows XP, not sure if that is correct... */
     173        result->tm_isdst = 0;
     174        return result;
     175#endif
    114176      }
    115177#if (defined(_MSC_VER) && (_MSC_VER >= 1400))
    116178#pragma warning(pop) // restore warnings to previous state
    117179#endif // _MSC_VER >= 1400
    118180
    119181#endif
    120 
    121       std::time_t time(std::time_t* t)
     182      /* This wrapper for time() is to work around systems (i.e. MS Windows CE)
     183      that lack a working time() function. */
     184      inline static std::time_t time(time_t* p)
    122185      {
    123         return std::time(t);
     186#if !defined(UNDER_CE)
     187        return std::time(p);
     188#else
     189        SYSTEMTIME systime;
     190        GetSystemTime(&systime);
     191        FILETIME ft;
     192        if(!SystemTimeToFileTime(&systime, &ft))
     193          boost::throw_exception(std::runtime_error("could not convert local time to file time"));
     194        /* convert
     195         1. FILETIME to int64_t
     196         2. 100ns to seconds
     197         3. epoch beginning 1601 to one beginning 1970
     198         4. int64_t to time_t */
     199        int64_t t64 = (static_cast<int64_t>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
     200        t64 = (t64 + 5000000) / 10000000;
     201        t64 -= 11644473600;
     202        std::time_t res = static_cast<std::time_t>(t64);
     203        // make sure the static cast didn't truncate the result
     204        if(res != t64)
     205          boost::throw_exception(std::runtime_error("could not convert t64 to time_t"));
     206        if(p)
     207          *p = res;
     208        return res;
     209#endif
    124210      }
     211#if defined(UNDER_CE)
     212    private:
     213      /* utility function to convert a SYSTIME to a std::tm
     214      Most fields are equal or similar, but the day of the year requires some
     215      computations. */
     216      inline static void systime_to_tm(std::tm* result, SYSTEMTIME const& st)
     217      {
     218        // assign the common values
     219        result->tm_sec = st.wSecond;
     220        result->tm_min = st.wMinute;
     221        result->tm_hour = st.wHour;
     222        result->tm_mday = st.wDay;
     223        result->tm_mon = st.wMonth - 1;
     224        result->tm_year = st.wYear - 1900;
     225        result->tm_wday = st.wDayOfWeek;
     226        // compute day of year
     227        bool leapyear;
     228        if((st.wYear % 1000) == 0)
     229          leapyear = true;
     230        else if((st.wYear % 100) == 0)
     231          leapyear = false;
     232        else if((st.wYear % 4) == 0)
     233          leapyear = true;
     234        else
     235          leapyear = false;
     236        result->tm_yday = result->tm_mday - 1;
     237        if(leapyear)
     238        {
     239          int const dpm[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
     240          for(int i=0; i!=result->tm_mon; ++i)
     241            result->tm_yday += dpm[i];
     242        }
     243        else
     244        {
     245          int const dpm[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
     246          for(int i=0; i!=result->tm_mon; ++i)
     247            result->tm_yday += dpm[i];
     248        }
     249      }
     250#endif
    125251  };
    126252}} // namespaces
    127253