Timestamp.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. //
  2. // Timestamp.cpp
  3. //
  4. // $Id: //poco/1.4/Foundation/src/Timestamp.cpp#2 $
  5. //
  6. // Library: Foundation
  7. // Package: DateTime
  8. // Module: Timestamp
  9. //
  10. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #include "Poco/Timestamp.h"
  16. #include "Poco/Timespan.h"
  17. #include "Poco/Exception.h"
  18. #include <algorithm>
  19. #undef min
  20. #undef max
  21. #include <limits>
  22. #if defined(POCO_OS_FAMILY_UNIX)
  23. #include <time.h>
  24. #include <unistd.h>
  25. #if defined(POCO_VXWORKS)
  26. #include <timers.h>
  27. #else
  28. #include <sys/time.h>
  29. #include <sys/times.h>
  30. #endif
  31. #elif defined(POCO_OS_FAMILY_WINDOWS)
  32. #include "Poco/UnWindows.h"
  33. #if defined(_WIN32_WCE)
  34. #include <cmath>
  35. #endif
  36. #endif
  37. #if defined(_WIN32_WCE)
  38. //
  39. // See <http://community.opennetcf.com/articles/cf/archive/2007/11/20/getting-a-millisecond-resolution-datetime-under-windows-ce.aspx>
  40. // for an explanation of the following code.
  41. //
  42. // In short: Windows CE system time in most cases only has a resolution of one second.
  43. // But we want millisecond resolution.
  44. //
  45. namespace {
  46. class TickOffset
  47. {
  48. public:
  49. TickOffset()
  50. {
  51. SYSTEMTIME st1, st2;
  52. std::memset(&st1, 0, sizeof(SYSTEMTIME));
  53. std::memset(&st2, 0, sizeof(SYSTEMTIME));
  54. GetSystemTime(&st1);
  55. while (true)
  56. {
  57. GetSystemTime(&st2);
  58. // wait for a rollover
  59. if (st1.wSecond != st2.wSecond)
  60. {
  61. _offset = GetTickCount() % 1000;
  62. break;
  63. }
  64. }
  65. }
  66. void calibrate(int seconds)
  67. {
  68. SYSTEMTIME st1, st2;
  69. systemTime(&st1);
  70. WORD s = st1.wSecond;
  71. int sum = 0;
  72. int remaining = seconds;
  73. while (remaining > 0)
  74. {
  75. systemTime(&st2);
  76. WORD s2 = st2.wSecond;
  77. if (s != s2)
  78. {
  79. remaining--;
  80. // store the offset from zero
  81. sum += (st2.wMilliseconds > 500) ? (st2.wMilliseconds - 1000) : st2.wMilliseconds;
  82. s = st2.wSecond;
  83. }
  84. }
  85. // adjust the offset by the average deviation from zero (round to the integer farthest from zero)
  86. if (sum < 0)
  87. _offset += (int) std::floor(sum / (float)seconds);
  88. else
  89. _offset += (int) std::ceil(sum / (float)seconds);
  90. }
  91. void systemTime(SYSTEMTIME* pST)
  92. {
  93. std::memset(pST, 0, sizeof(SYSTEMTIME));
  94. WORD tick = GetTickCount() % 1000;
  95. GetSystemTime(pST);
  96. WORD ms = (tick >= _offset) ? (tick - _offset) : (1000 - (_offset - tick));
  97. pST->wMilliseconds = ms;
  98. }
  99. void systemTimeAsFileTime(FILETIME* pFT)
  100. {
  101. SYSTEMTIME st;
  102. systemTime(&st);
  103. SystemTimeToFileTime(&st, pFT);
  104. }
  105. private:
  106. WORD _offset;
  107. };
  108. static TickOffset offset;
  109. void GetSystemTimeAsFileTimeWithMillisecondResolution(FILETIME* pFT)
  110. {
  111. offset.systemTimeAsFileTime(pFT);
  112. }
  113. } // namespace
  114. #endif // defined(_WIN32_WCE)
  115. namespace Poco {
  116. const Timestamp::TimeVal Timestamp::TIMEVAL_MIN = std::numeric_limits<Timestamp::TimeVal>::min();
  117. const Timestamp::TimeVal Timestamp::TIMEVAL_MAX = std::numeric_limits<Timestamp::TimeVal>::max();
  118. Timestamp::Timestamp()
  119. {
  120. update();
  121. }
  122. Timestamp::Timestamp(TimeVal tv)
  123. {
  124. _ts = tv;
  125. }
  126. Timestamp::Timestamp(const Timestamp& other)
  127. {
  128. _ts = other._ts;
  129. }
  130. Timestamp::~Timestamp()
  131. {
  132. }
  133. Timestamp& Timestamp::operator = (const Timestamp& other)
  134. {
  135. _ts = other._ts;
  136. return *this;
  137. }
  138. Timestamp& Timestamp::operator = (TimeVal tv)
  139. {
  140. _ts = tv;
  141. return *this;
  142. }
  143. void Timestamp::swap(Timestamp& timestamp)
  144. {
  145. std::swap(_ts, timestamp._ts);
  146. }
  147. Timestamp Timestamp::fromEpochTime(std::time_t t)
  148. {
  149. return Timestamp(TimeVal(t)*resolution());
  150. }
  151. Timestamp Timestamp::fromUtcTime(UtcTimeVal val)
  152. {
  153. val -= (TimeDiff(0x01b21dd2) << 32) + 0x13814000;
  154. val /= 10;
  155. return Timestamp(val);
  156. }
  157. void Timestamp::update()
  158. {
  159. #if defined(POCO_OS_FAMILY_WINDOWS)
  160. FILETIME ft;
  161. #if defined(_WIN32_WCE)
  162. GetSystemTimeAsFileTimeWithMillisecondResolution(&ft);
  163. #else
  164. GetSystemTimeAsFileTime(&ft);
  165. #endif
  166. ULARGE_INTEGER epoch; // UNIX epoch (1970-01-01 00:00:00) expressed in Windows NT FILETIME
  167. epoch.LowPart = 0xD53E8000;
  168. epoch.HighPart = 0x019DB1DE;
  169. ULARGE_INTEGER ts;
  170. ts.LowPart = ft.dwLowDateTime;
  171. ts.HighPart = ft.dwHighDateTime;
  172. ts.QuadPart -= epoch.QuadPart;
  173. _ts = ts.QuadPart/10;
  174. #elif defined(POCO_VXWORKS)
  175. struct timespec ts;
  176. if (clock_gettime(CLOCK_REALTIME, &ts))
  177. throw SystemException("cannot get time of day");
  178. _ts = TimeVal(ts.tv_sec)*resolution() + ts.tv_nsec/1000;
  179. #else
  180. struct timeval tv;
  181. if (gettimeofday(&tv, NULL))
  182. throw SystemException("cannot get time of day");
  183. _ts = TimeVal(tv.tv_sec)*resolution() + tv.tv_usec;
  184. #endif
  185. }
  186. Timestamp Timestamp::operator + (const Timespan& span) const
  187. {
  188. return *this + span.totalMicroseconds();
  189. }
  190. Timestamp Timestamp::operator - (const Timespan& span) const
  191. {
  192. return *this - span.totalMicroseconds();
  193. }
  194. Timestamp& Timestamp::operator += (const Timespan& span)
  195. {
  196. return *this += span.totalMicroseconds();
  197. }
  198. Timestamp& Timestamp::operator -= (const Timespan& span)
  199. {
  200. return *this -= span.totalMicroseconds();
  201. }
  202. #if defined(_WIN32)
  203. Timestamp Timestamp::fromFileTimeNP(UInt32 fileTimeLow, UInt32 fileTimeHigh)
  204. {
  205. ULARGE_INTEGER epoch; // UNIX epoch (1970-01-01 00:00:00) expressed in Windows NT FILETIME
  206. epoch.LowPart = 0xD53E8000;
  207. epoch.HighPart = 0x019DB1DE;
  208. ULARGE_INTEGER ts;
  209. ts.LowPart = fileTimeLow;
  210. ts.HighPart = fileTimeHigh;
  211. ts.QuadPart -= epoch.QuadPart;
  212. return Timestamp(ts.QuadPart/10);
  213. }
  214. void Timestamp::toFileTimeNP(UInt32& fileTimeLow, UInt32& fileTimeHigh) const
  215. {
  216. ULARGE_INTEGER epoch; // UNIX epoch (1970-01-01 00:00:00) expressed in Windows NT FILETIME
  217. epoch.LowPart = 0xD53E8000;
  218. epoch.HighPart = 0x019DB1DE;
  219. ULARGE_INTEGER ts;
  220. ts.QuadPart = _ts*10;
  221. ts.QuadPart += epoch.QuadPart;
  222. fileTimeLow = ts.LowPart;
  223. fileTimeHigh = ts.HighPart;
  224. }
  225. #endif
  226. } // namespace Poco