Opened 12 years ago
Last modified 11 years ago
#5428 new Bugs
No <ctime> function in Windows CE 6.0
Reported by: | Owned by: | az_sw_dude | |
---|---|---|---|
Milestone: | To Be Determined | Component: | date_time |
Version: | Boost 1.46.1 | Severity: | Problem |
Keywords: | wince | Cc: | ulrich.eckhardt@… |
Description
Windows CE platform is nothing <ctime> function. example std::localtime, std::gmtime, etc...
boost/date_time/c_time.hpp is direct use "std::localtime", "std::gmtime". this problem solution is make alternative implementation.
Windows CE platform <ctime> sample implementation is there: OpenTimeCE. (I cant paste URL, as spam...)
Attachments (2)
Change History (9)
comment:1 by , 11 years ago
comment:2 by , 11 years ago
Cc: | added |
---|---|
Keywords: | wince added |
Instead of providing a thread-unsafe localtime() implementation, the above could be modified to provide a thread-safe one that could be used for all win32 implementations. Since I'm pondering the same problems for my 1.48 migration, I'll take a look if I can't fix this.
comment:3 by , 11 years ago
The above implementation of localtime from sqlite is incorrect, AFAICT. The problem is that the tm_yday and tm_isdst fields are not set correctly. Further, even the hour differs sometimes, which I guess might be due to the daylight saving time offsets. I haven't completely figured out how to pull that info out of the system.
The code for gmtime() below was tested on a German MS Windows XP system for time_t values between 1 and 0xfffffff8, using the native gmtime() implementation of VC8 as reference. Both yield the same results. This also runs on MS Windows CE6, though I still need to test a few checkpoint values since I don't have a native gmtime() at my service there.
I'm a bit unsure if I can simply set the tm_isdst to zero for gmtime(), maybe someone else could jump in here.
//! requires a pointer to a user created std::tm struct inline static std::tm* gmtime(const std::time_t* t, std::tm* result) { /* Three conversions here: 1. convert to 64-bit type to avoid overflows 2. epoch beginning 1970 to one beginning 1601 3. seconds to 100ns steps */ int64_t t64 = static_cast<int64_t>(*t); t64 += 11644473600; t64 *= 10000000; // convert to FILETIME struct FILETIME utc_time; utc_time.dwLowDateTime = static_cast<DWORD>(t64 & 0xFFFFFFFF); utc_time.dwHighDateTime= static_cast<DWORD>(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")); result->tm_year = st.wYear - 1900; result->tm_mon = st.wMonth - 1; result->tm_wday = st.wDayOfWeek; result->tm_mday = st.wDay; result->tm_hour = st.wHour; result->tm_min = st.wMinute; result->tm_sec = st.wSecond; // 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 ml[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; for(int i=0; i!=result->tm_mon; ++i) result->tm_yday += ml[i]; } else { int const ml[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; for(int i=0; i!=result->tm_mon; ++i) result->tm_yday += ml[i]; } /* MSVC8 implementation always does that, using a German MS Windows XP, not sure if that is correct... */ result->tm_isdst = 0; return result; }
comment:4 by , 11 years ago
Short update: Another function missing from both CE5 and CE6 is time(). This function is used in boost/date_time/date_clock_device.hpp and boost/date_time/time_clock.hpp. Both uses are inside of template code, so the lack of these functions isn't obvious until the templates are instantiated.
My plan is to create a patch that adds a wrapper for time() to the c_time class and redirect any direct uses of time() there. Then, in a second step, I can implement the time wrapper there for CE. I'll post it in two steps because the first step will affect all platforms and I want that step to be as small and clear as possible, hopefully increasing the chances for it to be applied.
Notes:
- I don't have any environments earlier than CE5 here, so I can't speak for those, but I'm assuming that the state of the time functions is the same.
- There are no definitions of time() etc in CE5 and CE6, see e.g. this blog posting of one of the CE developers.
- In CE5 you have declarations in time.h, which are imported by STLport into namespace std, in CE6 those are gone, too.
by , 11 years ago
Attachment: | boost central time wrapper.patch added |
---|
add central point for time() workarounds
comment:5 by , 11 years ago
The attached patch is step 1. It adds a time() function to c_time, which currently only forwards to std::time(). All uses of std::time() in date_time were replaced with calls to that wrapper function.
I did two more things:
- In c_time.hpp were a few tabs and some foobar'd formatting, which I fixed along the way. There also were two misleading comments
#else // BOOST_HAS_THREADS
which I simply removed. - In the four cases where time() was used, it was used like
time_t t; time(&t);
which I replaced with a single linetime_t t = time(0);
. I was even wondering if I shouldn't drop the pointer argument completely from the wrapper, it seems of little use to me.
I'd be happy about some feedback whether these changes are acceptable. I'll send the second step implementing c_time::time() for CE tomorrow, I still need to clean it up a bit.
by , 11 years ago
Attachment: | boost time functions for CE.patch added |
---|
implementations of time(), localtime(), gmtime() for CE
comment:6 by , 11 years ago
This second patch adds implementations of the missing functions to c_time. With the exception of the tests relying on serialization, I have run all unit tests on a CE6 system without additional failures when compared to the desktop win32 version. Note that all this is based on 1.48, though the files in question haven't changed in trunk, AFAICT.
SQLite3 do this (#if SQLITE_OS_WINCE)