htime.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #include "htime.h"
  2. #include <string.h>
  3. #ifdef _MSC_VER
  4. #define strcasecmp stricmp
  5. #define strncasecmp strnicmp
  6. #else
  7. #include <strings.h>
  8. #define stricmp strcasecmp
  9. #define strnicmp strncasecmp
  10. #endif
  11. static const char* s_months[] = {"January", "February", "March", "April", "May", "June",
  12. "July", "August", "September", "October", "November", "December"};
  13. static const uint8_t s_days[] = \
  14. // 1 3 5 7 8 10 12
  15. {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  16. inline unsigned long long gethrtime() {
  17. #ifdef OS_WIN
  18. static LONGLONG s_freq = 0;
  19. if (s_freq == 0) {
  20. LARGE_INTEGER freq;
  21. QueryPerformanceFrequency(&freq);
  22. s_freq = freq.QuadPart;
  23. }
  24. if (s_freq != 0) {
  25. LARGE_INTEGER count;
  26. QueryPerformanceCounter(&count);
  27. return count.QuadPart / (double)s_freq * 1000000;
  28. }
  29. return 0;
  30. #elif defined(OS_LINUX)
  31. struct timespec ts;
  32. clock_gettime(CLOCK_MONOTONIC, &ts);
  33. return ts.tv_sec*(unsigned long long)1000000 + ts.tv_nsec / 1000;
  34. #else
  35. return clock() / (double)CLOCKS_PER_SEC * 1000000;
  36. #endif
  37. }
  38. datetime_t datetime_now() {
  39. datetime_t dt;
  40. #ifdef OS_WIN
  41. SYSTEMTIME tm;
  42. GetLocalTime(&tm);
  43. dt.year = tm.wYear;
  44. dt.month = tm.wMonth;
  45. dt.day = tm.wDay;
  46. dt.hour = tm.wHour;
  47. dt.min = tm.wMinute;
  48. dt.sec = tm.wSecond;
  49. dt.ms = tm.wMilliseconds;
  50. #else
  51. struct timeval tv;
  52. struct tm* tm = NULL;
  53. gettimeofday(&tv, NULL);
  54. time_t tt = tv.tv_sec;
  55. tm = localtime(&tt);
  56. dt.year = tm->tm_year + 1900;
  57. dt.month = tm->tm_mon + 1;
  58. dt.day = tm->tm_mday;
  59. dt.hour = tm->tm_hour;
  60. dt.min = tm->tm_min;
  61. dt.sec = tm->tm_sec;
  62. dt.ms = tv.tv_usec/1000;
  63. #endif
  64. return dt;
  65. }
  66. time_t datetime_mktime(datetime_t* dt) {
  67. struct tm tm;
  68. tm.tm_yday = dt->year - 1900;
  69. tm.tm_mon = dt->month - 1;
  70. tm.tm_mday = dt->day;
  71. tm.tm_hour = dt->hour;
  72. tm.tm_min = dt->min;
  73. tm.tm_sec = dt->sec;
  74. return mktime(&tm);
  75. }
  76. int days_of_month(int month, int year) {
  77. if (month < 1 || month > 12) {
  78. return 0;
  79. }
  80. int days = s_days[month-1];
  81. return (month == 2 && IS_LEAP_YEAR(year)) ? ++days : days;
  82. }
  83. datetime_t* datetime_past(datetime_t* dt, int days) {
  84. assert(days >= 0);
  85. int sub = days;
  86. while (sub) {
  87. if (dt->day > sub) {
  88. dt->day -= sub;
  89. break;
  90. }
  91. sub -= dt->day;
  92. if (--dt->month == 0) {
  93. dt->month = 12;
  94. --dt->year;
  95. }
  96. dt->day = days_of_month(dt->month, dt->year);
  97. }
  98. return dt;
  99. }
  100. datetime_t* datetime_future(datetime_t* dt, int days) {
  101. assert(days >= 0);
  102. int sub = days;
  103. int mdays;
  104. while (sub) {
  105. mdays = days_of_month(dt->month, dt->year);
  106. if (dt->day + sub <= mdays) {
  107. dt->day += sub;
  108. break;
  109. }
  110. sub -= (mdays - dt->day + 1);
  111. if (++dt->month > 12) {
  112. dt->month = 1;
  113. ++dt->year;
  114. }
  115. dt->day = 1;
  116. }
  117. return dt;
  118. }
  119. time_t calc_next_timeout(int minute, int hour, int day, int week, int month) {
  120. enum {
  121. UNKOWN,
  122. HOURLY,
  123. DAILY,
  124. WEEKLY,
  125. MONTHLY,
  126. YEARLY,
  127. } period_type = UNKOWN;
  128. struct tm tm;
  129. time_t tt;
  130. time(&tt);
  131. tm = *localtime(&tt);
  132. time_t tt_round = 0;
  133. tm.tm_sec = 0;
  134. if (minute >= 0) {
  135. period_type = HOURLY;
  136. tm.tm_min = minute;
  137. }
  138. if (hour >= 0) {
  139. period_type = DAILY;
  140. tm.tm_hour = hour;
  141. }
  142. if (week >= 0) {
  143. period_type = WEEKLY;
  144. }
  145. else if (day > 0) {
  146. period_type = MONTHLY;
  147. tm.tm_mday = day;
  148. if (month > 0) {
  149. period_type = YEARLY;
  150. tm.tm_mon = month - 1;
  151. }
  152. }
  153. if (period_type == UNKOWN) {
  154. return -1;
  155. }
  156. tt_round = mktime(&tm);
  157. if (week >= 0) {
  158. tt_round = tt + (week-tm.tm_wday)*SECONDS_PER_DAY;
  159. }
  160. if (tt_round > tt) {
  161. return tt_round;
  162. }
  163. switch(period_type) {
  164. case HOURLY:
  165. tt_round += SECONDS_PER_HOUR;
  166. return tt_round;
  167. case DAILY:
  168. tt_round += SECONDS_PER_DAY;
  169. return tt_round;
  170. case WEEKLY:
  171. tt_round += SECONDS_PER_WEEK;
  172. return tt_round;
  173. case MONTHLY:
  174. if (++tm.tm_mon == 12) {
  175. tm.tm_mon = 0;
  176. ++tm.tm_year;
  177. }
  178. break;
  179. case YEARLY:
  180. ++tm.tm_year;
  181. break;
  182. default:
  183. return -1;
  184. }
  185. return mktime(&tm);
  186. }
  187. int month_atoi(const char* month) {
  188. for (size_t i = 0; i < 12; ++i) {
  189. if (strnicmp(month, s_months[i], strlen(month)) == 0)
  190. return i+1;
  191. }
  192. return 0;
  193. }
  194. const char* month_itoa(int month) {
  195. if (month < 1 || month > 12) {
  196. return NULL;
  197. }
  198. return s_months[month-1];
  199. }
  200. datetime_t get_compile_datetime() {
  201. static datetime_t dt;
  202. char month[32];
  203. sscanf(__DATE__, "%s %d %d", month, &dt.day, &dt.year);
  204. sscanf(__TIME__, "%d %d %d", &dt.hour, &dt.min, &dt.sec);
  205. dt.month = month_atoi(month);
  206. return dt;
  207. }