timelib.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include <platform.h>
  14. #include <time.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <ctype.h>
  18. #include <assert.h>
  19. #include <eclrtl.hpp>
  20. #ifdef _WINDOWS
  21. #include <sys/timeb.h>
  22. #endif
  23. #include "timelib.hpp"
  24. static const char * compatibleVersions[] = {
  25. NULL };
  26. #define TIMELIB_VERSION "TIMELIB 1.0.0"
  27. static const char * EclDefinition =
  28. "EXPORT TMPartsRec := RECORD \n"
  29. " UNSIGNED4 v; \n"
  30. "END;"
  31. "EXPORT TimeLib := SERVICE\n"
  32. " integer8 SecondsFromParts(integer2 year, unsigned1 month, unsigned1 day, unsigned1 hour, unsigned1 minute, unsigned1 second, boolean is_local_time) : c,pure,entrypoint='tlSecondsFromParts'; \n"
  33. " DATASET(TMPartsRec) SecondsToParts(INTEGER8 seconds) : c,pure,entrypoint='tlSecondsToParts'; \n"
  34. " UNSIGNED2 GetDayOfYear(INTEGER2 year, UNSIGNED1 month, UNSIGNED1 day) : c,pure,entrypoint='tlGetDayOfYear'; \n"
  35. " UNSIGNED1 GetDayOfWeek(INTEGER2 year, UNSIGNED1 month, UNSIGNED1 day) : c,pure,entrypoint='tlGetDayOfWeek'; \n"
  36. " STRING DateToString(UNSIGNED4 date, VARSTRING format) : c,pure,entrypoint='tlDateToString'; \n"
  37. " STRING TimeToString(UNSIGNED3 time, VARSTRING format) : c,pure,entrypoint='tlTimeToString'; \n"
  38. " STRING SecondsToString(INTEGER8 seconds, VARSTRING format) : c,pure,entrypoint='tlSecondsToString'; \n"
  39. " UNSIGNED4 AdjustDate(UNSIGNED4 date, INTEGER2 year_delta, INTEGER4 month_delta, INTEGER4 day_delta) : c,pure,entrypoint='tlAdjustDate'; \n"
  40. " UNSIGNED4 AdjustDateBySeconds(UNSIGNED4 date, INTEGER4 seconds_delta) : c,pure,entrypoint='tlAdjustDateBySeconds'; \n"
  41. " UNSIGNED3 AdjustTime(UNSIGNED3 time, INTEGER2 hour_delta, INTEGER4 minute_delta, INTEGER4 second_delta) : c,pure,entrypoint='tlAdjustTime'; \n"
  42. " UNSIGNED3 AdjustTimeBySeconds(UNSIGNED3 time, INTEGER4 seconds_delta) : c,pure,entrypoint='tlAdjustTimeBySeconds'; \n"
  43. " INTEGER4 AdjustSeconds(INTEGER8 seconds, INTEGER2 year_delta, INTEGER4 month_delta, INTEGER4 day_delta, INTEGER2 hour_delta, INTEGER4 minute_delta, INTEGER4 second_delta) : c,pure,entrypoint='tlAdjustSeconds'; \n"
  44. " UNSIGNED4 AdjustCalendar(UNSIGNED4 date, INTEGER2 year_delta, INTEGER4 month_delta, INTEGER4 day_delta) : c,pure,entrypoint='tlAdjustCalendar'; \n"
  45. " BOOLEAN IsLocalDaylightSavingsInEffect() : c,pure,entrypoint='tlIsLocalDaylightSavingsInEffect'; \n"
  46. " INTEGER4 LocalTimeZoneOffset() : c,pure,entrypoint='tlLocalTimeZoneOffset'; \n"
  47. " UNSIGNED4 CurrentDate(BOOLEAN in_local_time) : c,pure,entrypoint='tlCurrentDate'; \n"
  48. " UNSIGNED4 CurrentTime(BOOLEAN in_local_time) : c,pure,entrypoint='tlCurrentTime'; \n"
  49. " INTEGER4 CurrentSeconds(BOOLEAN in_local_time) : c,pure,entrypoint='tlCurrentSeconds'; \n"
  50. " INTEGER8 CurrentTimestamp(BOOLEAN in_local_time) : c,pure,entrypoint='tlCurrentTimestamp'; \n"
  51. " UNSIGNED4 GetLastDayOfMonth(UNSIGNED4 date) : c,pure,entrypoint='tlGetLastDayOfMonth'; \n"
  52. " DATASET(TMPartsRec) DatesForWeek(UNSIGNED4 date) : c,pure,entrypoint='tlDatesForWeek'; \n"
  53. "END;";
  54. TIMELIB_API bool getECLPluginDefinition(ECLPluginDefinitionBlock *pb)
  55. {
  56. if (pb->size == sizeof(ECLPluginDefinitionBlockEx))
  57. {
  58. ECLPluginDefinitionBlockEx * pbx = (ECLPluginDefinitionBlockEx *) pb;
  59. pbx->compatibleVersions = compatibleVersions;
  60. }
  61. else if (pb->size != sizeof(ECLPluginDefinitionBlock))
  62. return false;
  63. pb->magicVersion = PLUGIN_VERSION;
  64. pb->version = TIMELIB_VERSION;
  65. pb->moduleName = "lib_timelib";
  66. pb->ECL = EclDefinition;
  67. pb->flags = PLUGIN_IMPLICIT_MODULE | PLUGIN_MULTIPLE_VERSIONS;
  68. pb->description = "TimeLib time manipulation library";
  69. return true;
  70. }
  71. IPluginContext * parentCtx = NULL;
  72. TIMELIB_API void setPluginContext(IPluginContext * _ctx) { parentCtx = _ctx; }
  73. //------------------------------------------------------------------------------
  74. #ifdef _WINDOWS
  75. const __int64 _onesec_in100ns = (__int64)10000000;
  76. __int64 tlFileTimeToInt64(FILETIME f)
  77. {
  78. __int64 seconds;
  79. seconds = f.dwHighDateTime;
  80. seconds <<= 32;
  81. seconds |= f.dwLowDateTime;
  82. return seconds;
  83. }
  84. FILETIME tlInt64ToFileTime(__int64 seconds)
  85. {
  86. FILETIME f;
  87. f.dwHighDateTime = (DWORD)((seconds >> 32) & 0x00000000FFFFFFFF);
  88. f.dwLowDateTime = (DWORD)(seconds & 0x00000000FFFFFFFF);
  89. return f;
  90. }
  91. FILETIME tlFileTimeFromYear(WORD year)
  92. {
  93. SYSTEMTIME s;
  94. FILETIME f;
  95. memset(&s, 0, sizeof(s));
  96. s.wYear = year;
  97. s.wMonth = 1;
  98. s.wDayOfWeek = 1;
  99. s.wDay = 1;
  100. SystemTimeToFileTime(&s, &f);
  101. return f;
  102. }
  103. unsigned int tlYearDayFromSystemTime(const SYSTEMTIME* s)
  104. {
  105. __int64 seconds;
  106. FILETIME f1;
  107. FILETIME f2;
  108. f1 = tlFileTimeFromYear(s->wYear);
  109. SystemTimeToFileTime(s, &f2);
  110. seconds = tlFileTimeToInt64(f2) - tlFileTimeToInt64(f1);
  111. return static_cast<unsigned int>((seconds / _onesec_in100ns) / (60 * 60 * 24));
  112. }
  113. SYSTEMTIME tlTimeStructToSystemTime(struct tm* timeInfoPtr)
  114. {
  115. SYSTEMTIME s;
  116. s.wYear = timeInfoPtr->tm_year + 1900;
  117. s.wMonth = timeInfoPtr->tm_mon + 1;
  118. s.wDayOfWeek = timeInfoPtr->tm_wday;
  119. s.wDay = timeInfoPtr->tm_mday;
  120. s.wHour = timeInfoPtr->tm_hour;
  121. s.wMinute = timeInfoPtr->tm_min;
  122. s.wSecond = timeInfoPtr->tm_sec;
  123. s.wMilliseconds = 0;
  124. return s;
  125. }
  126. void tlSystemTimeToTimeStruct_r(SYSTEMTIME* s, struct tm* timeInfoPtr)
  127. {
  128. memset(timeInfoPtr, 0, sizeof(struct tm));
  129. timeInfoPtr->tm_year = s->wYear - 1900;
  130. timeInfoPtr->tm_mon = s->wMonth - 1;
  131. timeInfoPtr->tm_wday = s->wDayOfWeek;
  132. timeInfoPtr->tm_mday = s->wDay;
  133. timeInfoPtr->tm_yday = tlYearDayFromSystemTime(s);
  134. timeInfoPtr->tm_hour = s->wHour;
  135. timeInfoPtr->tm_min = s->wMinute;
  136. timeInfoPtr->tm_sec = s->wSecond;
  137. timeInfoPtr->tm_isdst = 0;
  138. }
  139. time_t tlFileTimeToSeconds(const FILETIME* f)
  140. {
  141. __int64 offset = 11644473600; // Number of seconds between 1601 and 1970 (Jan 1 of each)
  142. __int64 seconds;
  143. seconds = tlFileTimeToInt64(*f) - offset;
  144. return static_cast<time_t>(seconds / _onesec_in100ns);
  145. }
  146. FILETIME tlSecondsToFileTime(const time_t seconds)
  147. {
  148. FILETIME f1970 = tlFileTimeFromYear(1970);
  149. FILETIME f;
  150. __int64 time;
  151. time = (seconds * _onesec_in100ns) + tlFileTimeToInt64(f1970);
  152. f = tlInt64ToFileTime(time);
  153. return f;
  154. }
  155. __int64 tlLocalTimeDiff()
  156. {
  157. SYSTEMTIME systemUTC;
  158. SYSTEMTIME systemLocal;
  159. FILETIME fileUTC;
  160. FILETIME fileLocal;
  161. GetSystemTime(&systemUTC);
  162. GetLocalTime(&systemLocal);
  163. SystemTimeToFileTime(&systemUTC, &fileUTC);
  164. SystemTimeToFileTime(&systemLocal, &fileLocal);
  165. return tlFileTimeToInt64(fileUTC) - tlFileTimeToInt64(fileLocal);
  166. }
  167. void tlBoundaryMod(int* tensPtr, int* unitsPtr, int base)
  168. {
  169. if (*unitsPtr >= base)
  170. {
  171. *tensPtr += *unitsPtr / base;
  172. *unitsPtr %= base;
  173. }
  174. else if (*unitsPtr < 0)
  175. {
  176. --*tensPtr;
  177. *unitsPtr += base;
  178. if (*unitsPtr < 0)
  179. {
  180. *tensPtr -= 1 + (-*unitsPtr) / base;
  181. *unitsPtr = base - (-*unitsPtr) % base;
  182. }
  183. }
  184. }
  185. void tlNormalizeTimeStruct(struct tm* timeInfoPtr)
  186. {
  187. // Normalize incoming struct tm
  188. const int secondsPerMinute = 60;
  189. const int minutesPerHour = 60;
  190. const int hoursPerDay = 24;
  191. const int daysPerWeek = 7;
  192. const int daysPerNYear = 365;
  193. const int daysPerLYear = 366;
  194. const int yearLengths[2] = { daysPerNYear, daysPerLYear };
  195. const int secondsPerHour = secondsPerMinute * minutesPerHour;
  196. const long secondsPerDay = secondsPerHour * hoursPerDay;
  197. const int monthsPerYear = 12;
  198. const int yearBase = 1900;
  199. const int monthLengths[2][monthsPerYear] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
  200. tlBoundaryMod(&timeInfoPtr->tm_min, &timeInfoPtr->tm_sec, secondsPerMinute);
  201. tlBoundaryMod(&timeInfoPtr->tm_hour, &timeInfoPtr->tm_min, minutesPerHour);
  202. tlBoundaryMod(&timeInfoPtr->tm_mday, &timeInfoPtr->tm_hour, hoursPerDay);
  203. tlBoundaryMod(&timeInfoPtr->tm_year, &timeInfoPtr->tm_mon, monthsPerYear);
  204. while (timeInfoPtr->tm_mday <= 0)
  205. {
  206. --timeInfoPtr->tm_year;
  207. int isLeapYear = ((((timeInfoPtr->tm_year + yearBase) % 4) == 0 && ((timeInfoPtr->tm_year + yearBase) % 100) != 0) || ((timeInfoPtr->tm_year + yearBase) % 400) == 0);
  208. timeInfoPtr->tm_mday += yearLengths[isLeapYear];
  209. }
  210. for (;;)
  211. {
  212. int isLeapYear = ((((timeInfoPtr->tm_year + yearBase) % 4) == 0 && ((timeInfoPtr->tm_year + yearBase) % 100) != 0) || ((timeInfoPtr->tm_year + yearBase) % 400) == 0);
  213. int i = monthLengths[isLeapYear][timeInfoPtr->tm_mon];
  214. if (timeInfoPtr->tm_mday <= i)
  215. break;
  216. timeInfoPtr->tm_mday -= i;
  217. if (++timeInfoPtr->tm_mon >= monthsPerYear)
  218. {
  219. timeInfoPtr->tm_mon = 0;
  220. ++timeInfoPtr->tm_year;
  221. }
  222. }
  223. }
  224. //---------------------------
  225. void tlWinLocalTime_r(const time_t* clock, struct tm* timeInfoPtr)
  226. {
  227. SYSTEMTIME s;
  228. FILETIME f;
  229. __int64 time;
  230. f = tlSecondsToFileTime(*clock);
  231. time = tlFileTimeToInt64(f) - tlLocalTimeDiff();
  232. f = tlInt64ToFileTime(time);
  233. FileTimeToSystemTime(&f, &s);
  234. tlSystemTimeToTimeStruct_r(&s, timeInfoPtr);
  235. }
  236. void tlWinGMTime_r(const time_t* clock, struct tm* timeInfo)
  237. {
  238. FILETIME f;
  239. SYSTEMTIME s;
  240. f = tlSecondsToFileTime(*clock);
  241. FileTimeToSystemTime(&f, &s);
  242. tlSystemTimeToTimeStruct_r(&s, timeInfo);
  243. }
  244. time_t tlWinMKTime(struct tm* timeInfoPtr)
  245. {
  246. SYSTEMTIME s;
  247. FILETIME f;
  248. time_t diff;
  249. // Windows apparently doesn't normalize/fix bogus date values before
  250. // doing conversions, so we need to normalize them first
  251. tlNormalizeTimeStruct(timeInfoPtr);
  252. s = tlTimeStructToSystemTime(timeInfoPtr);
  253. SystemTimeToFileTime(&s, &f);
  254. // Reset day of week
  255. FileTimeToSystemTime(&f, &s);
  256. timeInfoPtr->wday = s.wDayOfWeek;
  257. diff = tlLocalTimeDiff() / _onesec_in100ns;
  258. return tlFileTimeToSeconds(&f) - diff;
  259. }
  260. #endif
  261. //------------------------------------------------------------------------------
  262. void tlLocalTime_r(const time_t* clock, struct tm* timeInfoPtr)
  263. {
  264. #ifdef _WINDOWS
  265. tlWinLocalTime_r(clock, timeInfoPtr);
  266. #else
  267. localtime_r(clock, timeInfoPtr);
  268. #endif
  269. }
  270. void tlGMTime_r(const time_t* clock, struct tm* timeInfoPtr)
  271. {
  272. #ifdef _WINDOWS
  273. tlWinGMTime_r(clock, timeInfoPtr);
  274. #else
  275. gmtime_r(clock, timeInfoPtr);
  276. #endif
  277. }
  278. time_t tlMKTime(struct tm* timeInfoPtr, bool inLocalTimeZone)
  279. {
  280. time_t the_time = 0;
  281. #ifdef _WINDOWS
  282. the_time = tlWinMKTime(timeInfoPtr);
  283. if (!inLocalTimeZone)
  284. {
  285. // Adjust for time zone offset
  286. the_time += (tlLocalTimeZoneDiffIn100nsIntervals() / _onesec_in100ns);
  287. }
  288. #else
  289. // Get the initial time components; note that mktime assumes local time
  290. the_time = mktime(timeInfoPtr);
  291. if (!inLocalTimeZone)
  292. {
  293. // Adjust for time zone offset
  294. the_time += timeInfoPtr->tm_gmtoff;
  295. }
  296. #endif
  297. return the_time;
  298. }
  299. //------------------------------------------------------------------------------
  300. void tlMakeTimeStructFromUTCSeconds(time_t seconds, struct tm* timeInfo)
  301. {
  302. tlGMTime_r(&seconds, timeInfo);
  303. }
  304. void tlInsertDateIntoTimeStruct(struct tm* timeInfo, unsigned int date)
  305. {
  306. unsigned int year = date / 10000;
  307. unsigned int month = (date - (year * 10000)) / 100;
  308. unsigned int day = date - (year * 10000) - (month * 100);
  309. timeInfo->tm_year = year - 1900;
  310. timeInfo->tm_mon = month - 1;
  311. timeInfo->tm_mday = day;
  312. }
  313. unsigned int tlExtractDateFromTimeStruct(struct tm* timeInfo)
  314. {
  315. unsigned int result = 0;
  316. result = (timeInfo->tm_year + 1900) * 10000;
  317. result += (timeInfo->tm_mon + 1) * 100;
  318. result += timeInfo->tm_mday;
  319. return result;
  320. }
  321. void tlInsertTimeIntoTimeStruct(struct tm* timeInfo, unsigned int time)
  322. {
  323. unsigned int hour = time / 10000;
  324. unsigned int minute = (time - (hour * 10000)) / 100;
  325. unsigned int second = time - (hour * 10000) - (minute * 100);
  326. timeInfo->tm_hour = hour;
  327. timeInfo->tm_min = minute;
  328. timeInfo->tm_sec = second;
  329. }
  330. unsigned int tlExtractTimeFromTimeStruct(struct tm* timeInfo)
  331. {
  332. unsigned int result = 0;
  333. result = timeInfo->tm_hour * 10000;
  334. result += timeInfo->tm_min * 100;
  335. result += timeInfo->tm_sec;
  336. return result;
  337. }
  338. //------------------------------------------------------------------------------
  339. TIMELIB_API __int64 TIMELIB_CALL tlSecondsFromParts(int year, unsigned int month, unsigned int day, unsigned int hour, unsigned int minute, unsigned int second, bool is_local_time)
  340. {
  341. struct tm timeInfo;
  342. time_t the_time = 0;
  343. memset(&timeInfo, 0, sizeof(timeInfo));
  344. // Push each time part value into the tm struct
  345. timeInfo.tm_sec = second;
  346. timeInfo.tm_min = minute;
  347. timeInfo.tm_hour = hour;
  348. timeInfo.tm_mday = day;
  349. timeInfo.tm_mon = month - 1;
  350. timeInfo.tm_year = year - 1900;
  351. the_time = tlMKTime(&timeInfo, is_local_time);
  352. return static_cast<__int64>(the_time);
  353. }
  354. //------------------------------------------------------------------------------
  355. TIMELIB_API void TIMELIB_CALL tlSecondsToParts(size32_t &__lenResult, void* &__result, __int64 seconds)
  356. {
  357. struct tm timeInfo;
  358. tlMakeTimeStructFromUTCSeconds(seconds, &timeInfo);
  359. __lenResult = sizeof(unsigned int) * 7;
  360. __result = CTXMALLOC(parentCtx, __lenResult);
  361. // Actually write the output values one at a time
  362. unsigned int* out = reinterpret_cast<unsigned int*>(__result);
  363. out[0] = timeInfo.tm_sec;
  364. out[1] = timeInfo.tm_min;
  365. out[2] = timeInfo.tm_hour;
  366. out[3] = timeInfo.tm_mday;
  367. out[4] = timeInfo.tm_mon;
  368. out[5] = timeInfo.tm_year;
  369. out[6] = timeInfo.tm_wday;
  370. }
  371. //------------------------------------------------------------------------------
  372. TIMELIB_API unsigned int TIMELIB_CALL tlGetDayOfYear(short year, unsigned short month, unsigned short day)
  373. {
  374. unsigned int dayOfYear = 0;
  375. #ifdef _WINDOWS
  376. SYSTEMTIME s;
  377. memset(&s, 0, sizeof(s));
  378. s.wYear = year;
  379. s.wMonth = month;
  380. s.wDay = day;
  381. dayOfYear = tlYearDayFromSystemTime(&s);
  382. #else
  383. struct tm timeInfo;
  384. memset(&timeInfo, 0, sizeof(timeInfo));
  385. // Push each time part value into the tm struct
  386. timeInfo.tm_mday = day;
  387. timeInfo.tm_mon = month - 1;
  388. timeInfo.tm_year = year - 1900;
  389. tlMKTime(&timeInfo);
  390. dayOfYear = timeInfo.tm_yday;
  391. #endif
  392. return dayOfYear;
  393. }
  394. //------------------------------------------------------------------------------
  395. TIMELIB_API unsigned int TIMELIB_CALL tlGetDayOfWeek(short year, unsigned short month, unsigned short day)
  396. {
  397. struct tm timeInfo;
  398. memset(&timeInfo, 0, sizeof(timeInfo));
  399. // Push each time part value into the tm struct
  400. timeInfo.tm_mday = day;
  401. timeInfo.tm_mon = month - 1;
  402. timeInfo.tm_year = year - 1900;
  403. tlMKTime(&timeInfo);
  404. return timeInfo.tm_wday;
  405. }
  406. //------------------------------------------------------------------------------
  407. TIMELIB_API void TIMELIB_CALL tlDateToString(size32_t &__lenResult, char* &__result, unsigned int date, const char* format)
  408. {
  409. struct tm timeInfo;
  410. size_t kBufferSize = 256;
  411. char buffer[kBufferSize];
  412. memset(&timeInfo, 0, sizeof(timeInfo));
  413. tlInsertDateIntoTimeStruct(&timeInfo, date);
  414. __lenResult = strftime(buffer, kBufferSize, format, &timeInfo);
  415. __result = NULL;
  416. if (__lenResult > 0)
  417. {
  418. __result = reinterpret_cast<char*>(CTXMALLOC(parentCtx, __lenResult));
  419. memcpy(__result, buffer, __lenResult);
  420. }
  421. }
  422. //------------------------------------------------------------------------------
  423. TIMELIB_API void TIMELIB_CALL tlTimeToString(size32_t &__lenResult, char* &__result, unsigned int time, const char* format)
  424. {
  425. struct tm timeInfo;
  426. size_t kBufferSize = 256;
  427. char buffer[kBufferSize];
  428. memset(&timeInfo, 0, sizeof(timeInfo));
  429. tlInsertTimeIntoTimeStruct(&timeInfo, time);
  430. __lenResult = strftime(buffer, kBufferSize, format, &timeInfo);
  431. __result = NULL;
  432. if (__lenResult > 0)
  433. {
  434. __result = reinterpret_cast<char*>(rtlMalloc(__lenResult));
  435. memcpy(__result, buffer, __lenResult);
  436. }
  437. }
  438. //------------------------------------------------------------------------------
  439. TIMELIB_API void TIMELIB_CALL tlSecondsToString(size32_t &__lenResult, char* &__result, __int64 seconds, const char* format)
  440. {
  441. struct tm timeInfo;
  442. time_t theTime = seconds;
  443. size_t kBufferSize = 256;
  444. char buffer[kBufferSize];
  445. memset(buffer, kBufferSize, 0);
  446. tlGMTime_r(&theTime, &timeInfo);
  447. __lenResult = strftime(buffer, kBufferSize, format, &timeInfo);
  448. __result = NULL;
  449. if (__lenResult > 0)
  450. {
  451. __result = reinterpret_cast<char*>(rtlMalloc(__lenResult));
  452. memcpy(__result, buffer, __lenResult);
  453. }
  454. }
  455. //------------------------------------------------------------------------------
  456. TIMELIB_API unsigned int TIMELIB_CALL tlAdjustDate(unsigned int date, short year_delta, int month_delta, int day_delta)
  457. {
  458. struct tm timeInfo;
  459. unsigned int result = 0;
  460. memset(&timeInfo, 0, sizeof(timeInfo));
  461. tlInsertDateIntoTimeStruct(&timeInfo, date);
  462. timeInfo.tm_year += year_delta;
  463. timeInfo.tm_mon += month_delta;
  464. timeInfo.tm_mday += day_delta;
  465. tlMKTime(&timeInfo);
  466. result = tlExtractDateFromTimeStruct(&timeInfo);
  467. return result;
  468. }
  469. //------------------------------------------------------------------------------
  470. TIMELIB_API unsigned int TIMELIB_CALL tlAdjustDateBySeconds(unsigned int date, int seconds_delta)
  471. {
  472. struct tm timeInfo;
  473. unsigned int result = 0;
  474. memset(&timeInfo, 0, sizeof(timeInfo));
  475. tlInsertDateIntoTimeStruct(&timeInfo, date);
  476. timeInfo.tm_sec = seconds_delta;
  477. tlMKTime(&timeInfo);
  478. result = tlExtractDateFromTimeStruct(&timeInfo);
  479. return result;
  480. }
  481. //------------------------------------------------------------------------------
  482. TIMELIB_API unsigned int TIMELIB_CALL tlAdjustTime(unsigned int time, short hour_delta, int minute_delta, int second_delta)
  483. {
  484. struct tm timeInfo;
  485. unsigned int result = 0;
  486. memset(&timeInfo, 0, sizeof(timeInfo));
  487. tlInsertTimeIntoTimeStruct(&timeInfo, time);
  488. timeInfo.tm_hour += hour_delta;
  489. timeInfo.tm_min += minute_delta;
  490. timeInfo.tm_sec += second_delta;
  491. tlMKTime(&timeInfo);
  492. result = tlExtractTimeFromTimeStruct(&timeInfo);
  493. return result;
  494. }
  495. //------------------------------------------------------------------------------
  496. TIMELIB_API unsigned int TIMELIB_CALL tlAdjustTimeBySeconds(unsigned int time, int seconds_delta)
  497. {
  498. struct tm timeInfo;
  499. unsigned int result = 0;
  500. memset(&timeInfo, 0, sizeof(timeInfo));
  501. tlInsertTimeIntoTimeStruct(&timeInfo, time);
  502. timeInfo.tm_sec += seconds_delta;
  503. tlMKTime(&timeInfo);
  504. result = tlExtractTimeFromTimeStruct(&timeInfo);
  505. return result;
  506. }
  507. //------------------------------------------------------------------------------
  508. TIMELIB_API __int64 TIMELIB_CALL tlAdjustSeconds(__int64 seconds, short year_delta, int month_delta, int day_delta, short hour_delta, int minute_delta, int second_delta)
  509. {
  510. struct tm timeInfo;
  511. time_t theTime = seconds;
  512. time_t result = 0;
  513. tlLocalTime_r(&theTime, &timeInfo);
  514. timeInfo.tm_year += year_delta;
  515. timeInfo.tm_mon += month_delta;
  516. timeInfo.tm_mday += day_delta;
  517. timeInfo.tm_hour += hour_delta;
  518. timeInfo.tm_min += minute_delta;
  519. timeInfo.tm_sec += second_delta;
  520. result = theTime = tlMKTime(&timeInfo);
  521. return static_cast<__int64>(result);
  522. }
  523. //------------------------------------------------------------------------------
  524. TIMELIB_API unsigned int TIMELIB_CALL tlAdjustCalendar(unsigned int date, short year_delta, int month_delta, int day_delta)
  525. {
  526. struct tm timeInfo;
  527. unsigned int year = date / 10000;
  528. unsigned int month = (date - (year * 10000)) / 100;
  529. unsigned int day = date - (year * 10000) - (month * 100);
  530. int expectedMonthVal = month + month_delta - 1;
  531. unsigned int result = 0;
  532. // Normalize the expected month value
  533. if (expectedMonthVal >= 0)
  534. {
  535. expectedMonthVal = expectedMonthVal % 12;
  536. }
  537. else
  538. {
  539. expectedMonthVal = 12 - (abs(expectedMonthVal) % 12);
  540. }
  541. memset(&timeInfo, 0, sizeof(timeInfo));
  542. timeInfo.tm_year = year - 1900;
  543. timeInfo.tm_mon = month - 1;
  544. timeInfo.tm_mday = day;
  545. timeInfo.tm_year += year_delta;
  546. timeInfo.tm_mon += month_delta;
  547. tlMKTime(&timeInfo);
  548. if (timeInfo.tm_mon != expectedMonthVal)
  549. {
  550. // If the returned month doesn't match the expected month, we need to
  551. // go back to the last day of the previous month
  552. timeInfo.tm_mday = 0;
  553. tlMKTime(&timeInfo);
  554. }
  555. if (day_delta != 0)
  556. {
  557. // Now apply the day delta
  558. timeInfo.tm_mday += day_delta;
  559. tlMKTime(&timeInfo);
  560. }
  561. result = tlExtractDateFromTimeStruct(&timeInfo);
  562. return result;
  563. }
  564. //------------------------------------------------------------------------------
  565. TIMELIB_API bool TIMELIB_CALL tlIsLocalDaylightSavingsInEffect()
  566. {
  567. struct tm timeInfo;
  568. time_t theTime = time(NULL);
  569. tlLocalTime_r(&theTime, &timeInfo);
  570. return (timeInfo.tm_isdst == 1);
  571. }
  572. //------------------------------------------------------------------------------
  573. TIMELIB_API int TIMELIB_CALL tlLocalTimeZoneOffset()
  574. {
  575. int offset = 0;
  576. #ifdef _WINDOWS
  577. offset = tlLocalTimeZoneDiffIn100nsIntervals() / _onesec_in100ns;
  578. #else
  579. struct tm timeInfo;
  580. time_t theTime = time(NULL);
  581. tlLocalTime_r(&theTime, &timeInfo);
  582. offset = timeInfo.tm_gmtoff;
  583. #endif
  584. return offset;
  585. }
  586. //------------------------------------------------------------------------------
  587. TIMELIB_API unsigned int TIMELIB_CALL tlCurrentDate(bool in_local_time)
  588. {
  589. struct tm timeInfo;
  590. time_t theTime = time(NULL);
  591. unsigned int result = 0;
  592. // Create time parts differently depending on whether you need
  593. // UTC or local time
  594. if (in_local_time)
  595. {
  596. tlLocalTime_r(&theTime, &timeInfo);
  597. }
  598. else
  599. {
  600. tlGMTime_r(&theTime, &timeInfo);
  601. }
  602. result = tlExtractDateFromTimeStruct(&timeInfo);
  603. return result;
  604. }
  605. //------------------------------------------------------------------------------
  606. TIMELIB_API unsigned int TIMELIB_CALL tlCurrentTime(bool in_local_time)
  607. {
  608. struct tm timeInfo;
  609. time_t theTime = time(NULL);
  610. unsigned int result = 0;
  611. // Create time parts differently depending on whether you need
  612. // UTC or local time
  613. if (in_local_time)
  614. {
  615. tlLocalTime_r(&theTime, &timeInfo);
  616. }
  617. else
  618. {
  619. tlGMTime_r(&theTime, &timeInfo);
  620. }
  621. result = tlExtractTimeFromTimeStruct(&timeInfo);
  622. return result;
  623. }
  624. //------------------------------------------------------------------------------
  625. TIMELIB_API __int64 TIMELIB_CALL tlCurrentSeconds(bool in_local_time)
  626. {
  627. time_t result = time(NULL);
  628. if (in_local_time)
  629. {
  630. result += tlLocalTimeZoneOffset();
  631. }
  632. return static_cast<__int64>(result);
  633. }
  634. //------------------------------------------------------------------------------
  635. TIMELIB_API __int64 TIMELIB_CALL tlCurrentTimestamp(bool in_local_time)
  636. {
  637. __int64 result = 0;
  638. #ifdef _WINDOWS
  639. struct _timeb now;
  640. _ftime(&now);
  641. result = (now.time * 1000000) + now.(millitm * 1000);
  642. #else
  643. struct timeval tv;
  644. if (gettimeofday(&tv, NULL) == 0)
  645. {
  646. result = (tv.tv_sec * 1000000) + tv.tv_usec;
  647. }
  648. #endif
  649. if (in_local_time)
  650. {
  651. result += (static_cast<long>(tlLocalTimeZoneOffset()) * 1000000);
  652. }
  653. return result;
  654. }
  655. //------------------------------------------------------------------------------
  656. TIMELIB_API unsigned int TIMELIB_CALL tlGetLastDayOfMonth(unsigned int date)
  657. {
  658. struct tm timeInfo;
  659. unsigned int result = 0;
  660. memset(&timeInfo, 0, sizeof(timeInfo));
  661. tlInsertDateIntoTimeStruct(&timeInfo, date);
  662. // Call mktime once to fix up any bogus data
  663. tlMKTime(&timeInfo);
  664. // Adjust and call again
  665. timeInfo.tm_mon += 1;
  666. timeInfo.tm_mday = 0;
  667. tlMKTime(&timeInfo);
  668. result = tlExtractDateFromTimeStruct(&timeInfo);
  669. return result;
  670. }
  671. //------------------------------------------------------------------------------
  672. TIMELIB_API void TIMELIB_CALL tlDatesForWeek(size32_t &__lenResult, void* &__result, unsigned int date)
  673. {
  674. struct tm timeInfo;
  675. unsigned int weekStartResult = 0;
  676. unsigned int weekEndResult = 0;
  677. memset(&timeInfo, 0, sizeof(timeInfo));
  678. tlInsertDateIntoTimeStruct(&timeInfo, date);
  679. // Call mktime once to fix up any bogus data
  680. tlMKTime(&timeInfo);
  681. // Adjust and call again
  682. timeInfo.tm_mday -= timeInfo.tm_wday;
  683. tlMKTime(&timeInfo);
  684. weekStartResult = tlExtractDateFromTimeStruct(&timeInfo);
  685. // Adjust to the beginning of the week
  686. timeInfo.tm_mday += 6;
  687. tlMKTime(&timeInfo);
  688. weekEndResult = tlExtractDateFromTimeStruct(&timeInfo);
  689. __lenResult = sizeof(unsigned int) * 2;
  690. __result = CTXMALLOC(parentCtx, __lenResult);
  691. unsigned int* out = reinterpret_cast<unsigned int*>(__result);
  692. out[0] = weekStartResult;
  693. out[1] = weekEndResult;
  694. }