LocalDateTime.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. //
  2. // LocalDateTime.cpp
  3. //
  4. // $Id: //poco/1.4/Foundation/src/LocalDateTime.cpp#2 $
  5. //
  6. // Library: Foundation
  7. // Package: DateTime
  8. // Module: LocalDateTime
  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/LocalDateTime.h"
  16. #include "Poco/Timezone.h"
  17. #include "Poco/Timespan.h"
  18. #include "Poco/Exception.h"
  19. #include <algorithm>
  20. #include <ctime>
  21. #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
  22. #include "wce_time.h"
  23. #endif
  24. namespace Poco {
  25. LocalDateTime::LocalDateTime()
  26. {
  27. determineTzd(true);
  28. }
  29. LocalDateTime::LocalDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond):
  30. _dateTime(year, month, day, hour, minute, second, millisecond, microsecond)
  31. {
  32. determineTzd();
  33. }
  34. LocalDateTime::LocalDateTime(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond):
  35. _dateTime(year, month, day, hour, minute, second, millisecond, microsecond),
  36. _tzd(tzd)
  37. {
  38. }
  39. LocalDateTime::LocalDateTime(double julianDay):
  40. _dateTime(julianDay)
  41. {
  42. determineTzd(true);
  43. }
  44. LocalDateTime::LocalDateTime(int tzd, double julianDay):
  45. _dateTime(julianDay),
  46. _tzd(tzd)
  47. {
  48. adjustForTzd();
  49. }
  50. LocalDateTime::LocalDateTime(const DateTime& dateTime):
  51. _dateTime(dateTime)
  52. {
  53. determineTzd(true);
  54. }
  55. LocalDateTime::LocalDateTime(int tzd, const DateTime& dateTime):
  56. _dateTime(dateTime),
  57. _tzd(tzd)
  58. {
  59. adjustForTzd();
  60. }
  61. LocalDateTime::LocalDateTime(int tzd, const DateTime& dateTime, bool adjust):
  62. _dateTime(dateTime),
  63. _tzd(tzd)
  64. {
  65. if (adjust)
  66. adjustForTzd();
  67. }
  68. LocalDateTime::LocalDateTime(const LocalDateTime& dateTime):
  69. _dateTime(dateTime._dateTime),
  70. _tzd(dateTime._tzd)
  71. {
  72. }
  73. LocalDateTime::LocalDateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff, int tzd):
  74. _dateTime(utcTime, diff),
  75. _tzd(tzd)
  76. {
  77. adjustForTzd();
  78. }
  79. LocalDateTime::~LocalDateTime()
  80. {
  81. }
  82. LocalDateTime& LocalDateTime::operator = (const LocalDateTime& dateTime)
  83. {
  84. if (&dateTime != this)
  85. {
  86. _dateTime = dateTime._dateTime;
  87. _tzd = dateTime._tzd;
  88. }
  89. return *this;
  90. }
  91. LocalDateTime& LocalDateTime::operator = (const Timestamp& timestamp)
  92. {
  93. if (timestamp != this->timestamp())
  94. {
  95. _dateTime = timestamp;
  96. determineTzd(true);
  97. }
  98. return *this;
  99. }
  100. LocalDateTime& LocalDateTime::operator = (double julianDay)
  101. {
  102. _dateTime = julianDay;
  103. determineTzd(true);
  104. return *this;
  105. }
  106. LocalDateTime& LocalDateTime::assign(int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds)
  107. {
  108. _dateTime.assign(year, month, day, hour, minute, second, millisecond, microseconds);
  109. determineTzd(false);
  110. return *this;
  111. }
  112. LocalDateTime& LocalDateTime::assign(int tzd, int year, int month, int day, int hour, int minute, int second, int millisecond, int microseconds)
  113. {
  114. _dateTime.assign(year, month, day, hour, minute, second, millisecond, microseconds);
  115. _tzd = tzd;
  116. return *this;
  117. }
  118. LocalDateTime& LocalDateTime::assign(int tzd, double julianDay)
  119. {
  120. _tzd = tzd;
  121. _dateTime = julianDay;
  122. adjustForTzd();
  123. return *this;
  124. }
  125. void LocalDateTime::swap(LocalDateTime& dateTime)
  126. {
  127. _dateTime.swap(dateTime._dateTime);
  128. std::swap(_tzd, dateTime._tzd);
  129. }
  130. DateTime LocalDateTime::utc() const
  131. {
  132. return DateTime(_dateTime.utcTime(), -((Timestamp::TimeDiff) _tzd)*Timespan::SECONDS);
  133. }
  134. bool LocalDateTime::operator == (const LocalDateTime& dateTime) const
  135. {
  136. return utcTime() == dateTime.utcTime();
  137. }
  138. bool LocalDateTime::operator != (const LocalDateTime& dateTime) const
  139. {
  140. return utcTime() != dateTime.utcTime();
  141. }
  142. bool LocalDateTime::operator < (const LocalDateTime& dateTime) const
  143. {
  144. return utcTime() < dateTime.utcTime();
  145. }
  146. bool LocalDateTime::operator <= (const LocalDateTime& dateTime) const
  147. {
  148. return utcTime() <= dateTime.utcTime();
  149. }
  150. bool LocalDateTime::operator > (const LocalDateTime& dateTime) const
  151. {
  152. return utcTime() > dateTime.utcTime();
  153. }
  154. bool LocalDateTime::operator >= (const LocalDateTime& dateTime) const
  155. {
  156. return utcTime() >= dateTime.utcTime();
  157. }
  158. LocalDateTime LocalDateTime::operator + (const Timespan& span) const
  159. {
  160. // First calculate the adjusted UTC time, then calculate the
  161. // locally adjusted time by constructing a new LocalDateTime.
  162. DateTime tmp(utcTime(), span.totalMicroseconds());
  163. return LocalDateTime(tmp);
  164. }
  165. LocalDateTime LocalDateTime::operator - (const Timespan& span) const
  166. {
  167. // First calculate the adjusted UTC time, then calculate the
  168. // locally adjusted time by constructing a new LocalDateTime.
  169. DateTime tmp(utcTime(), -span.totalMicroseconds());
  170. return LocalDateTime(tmp);
  171. }
  172. Timespan LocalDateTime::operator - (const LocalDateTime& dateTime) const
  173. {
  174. return Timespan((utcTime() - dateTime.utcTime())/10);
  175. }
  176. LocalDateTime& LocalDateTime::operator += (const Timespan& span)
  177. {
  178. // Use the same trick as in operator+. Create a UTC time, adjust
  179. // it for the span, and convert back to LocalDateTime. This will
  180. // recalculate the tzd correctly in the case where the addition
  181. // crosses a DST boundary.
  182. *this = DateTime(utcTime(), span.totalMicroseconds());
  183. return *this;
  184. }
  185. LocalDateTime& LocalDateTime::operator -= (const Timespan& span)
  186. {
  187. // Use the same trick as in operator-. Create a UTC time, adjust
  188. // it for the span, and convert back to LocalDateTime. This will
  189. // recalculate the tzd correctly in the case where the subtraction
  190. // crosses a DST boundary.
  191. *this = DateTime(utcTime(), -span.totalMicroseconds());
  192. return *this;
  193. }
  194. void LocalDateTime::determineTzd(bool adjust)
  195. {
  196. if (adjust)
  197. {
  198. std::time_t epochTime = _dateTime.timestamp().epochTime();
  199. #if defined(_WIN32) || defined(POCO_NO_POSIX_TSF)
  200. #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
  201. std::tm* broken = wceex_localtime(&epochTime);
  202. #else
  203. std::tm* broken = std::localtime(&epochTime);
  204. #endif
  205. if (!broken) throw Poco::SystemException("cannot get local time");
  206. _tzd = (Timezone::utcOffset() + ((broken->tm_isdst == 1) ? 3600 : 0));
  207. #else
  208. std::tm broken;
  209. #if defined(POCO_VXWORKS)
  210. if (localtime_r(&epochTime, &broken) != OK)
  211. throw Poco::SystemException("cannot get local time");
  212. #else
  213. if (!localtime_r(&epochTime, &broken))
  214. throw Poco::SystemException("cannot get local time");
  215. #endif
  216. _tzd = (Timezone::utcOffset() + ((broken.tm_isdst == 1) ? 3600 : 0));
  217. #endif
  218. adjustForTzd();
  219. }
  220. else
  221. {
  222. int dst;
  223. dstOffset(dst);
  224. _tzd = (Timezone::utcOffset() + dst);
  225. }
  226. }
  227. std::time_t LocalDateTime::dstOffset(int& dstOffset) const
  228. {
  229. std::time_t local;
  230. std::tm broken;
  231. broken.tm_year = (_dateTime.year() - 1900);
  232. broken.tm_mon = (_dateTime.month() - 1);
  233. broken.tm_mday = _dateTime.day();
  234. broken.tm_hour = _dateTime.hour();
  235. broken.tm_min = _dateTime.minute();
  236. broken.tm_sec = _dateTime.second();
  237. broken.tm_isdst = -1;
  238. #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
  239. local = wceex_mktime(&broken);
  240. #else
  241. local = std::mktime(&broken);
  242. #endif
  243. dstOffset = (broken.tm_isdst == 1) ? 3600 : 0;
  244. return local;
  245. }
  246. } // namespace Poco