htime.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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 HAVE_CLOCK_GETTIME
  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. struct timeval tv;
  36. gettimeofday(&tv, NULL);
  37. return tv.tv_sec*(unsigned long long)1000000 + tv.tv_usec;
  38. #endif
  39. }
  40. datetime_t datetime_now() {
  41. datetime_t dt;
  42. #ifdef OS_WIN
  43. SYSTEMTIME tm;
  44. GetLocalTime(&tm);
  45. dt.year = tm.wYear;
  46. dt.month = tm.wMonth;
  47. dt.day = tm.wDay;
  48. dt.hour = tm.wHour;
  49. dt.min = tm.wMinute;
  50. dt.sec = tm.wSecond;
  51. dt.ms = tm.wMilliseconds;
  52. #else
  53. struct timeval tv;
  54. struct tm* tm = NULL;
  55. gettimeofday(&tv, NULL);
  56. time_t tt = tv.tv_sec;
  57. tm = localtime(&tt);
  58. dt.year = tm->tm_year + 1900;
  59. dt.month = tm->tm_mon + 1;
  60. dt.day = tm->tm_mday;
  61. dt.hour = tm->tm_hour;
  62. dt.min = tm->tm_min;
  63. dt.sec = tm->tm_sec;
  64. dt.ms = tv.tv_usec/1000;
  65. #endif
  66. return dt;
  67. }
  68. time_t datetime_mktime(datetime_t* dt) {
  69. struct tm tm;
  70. tm.tm_yday = dt->year - 1900;
  71. tm.tm_mon = dt->month - 1;
  72. tm.tm_mday = dt->day;
  73. tm.tm_hour = dt->hour;
  74. tm.tm_min = dt->min;
  75. tm.tm_sec = dt->sec;
  76. return mktime(&tm);
  77. }
  78. int days_of_month(int month, int year) {
  79. if (month < 1 || month > 12) {
  80. return 0;
  81. }
  82. int days = s_days[month-1];
  83. return (month == 2 && IS_LEAP_YEAR(year)) ? ++days : days;
  84. }
  85. datetime_t* datetime_past(datetime_t* dt, int days) {
  86. assert(days >= 0);
  87. int sub = days;
  88. while (sub) {
  89. if (dt->day > sub) {
  90. dt->day -= sub;
  91. break;
  92. }
  93. sub -= dt->day;
  94. if (--dt->month == 0) {
  95. dt->month = 12;
  96. --dt->year;
  97. }
  98. dt->day = days_of_month(dt->month, dt->year);
  99. }
  100. return dt;
  101. }
  102. datetime_t* datetime_future(datetime_t* dt, int days) {
  103. assert(days >= 0);
  104. int sub = days;
  105. int mdays;
  106. while (sub) {
  107. mdays = days_of_month(dt->month, dt->year);
  108. if (dt->day + sub <= mdays) {
  109. dt->day += sub;
  110. break;
  111. }
  112. sub -= (mdays - dt->day + 1);
  113. if (++dt->month > 12) {
  114. dt->month = 1;
  115. ++dt->year;
  116. }
  117. dt->day = 1;
  118. }
  119. return dt;
  120. }
  121. time_t calc_next_timeout(int minute, int hour, int day, int week, int month) {
  122. enum {
  123. UNKOWN,
  124. HOURLY,
  125. DAILY,
  126. WEEKLY,
  127. MONTHLY,
  128. YEARLY,
  129. } period_type = UNKOWN;
  130. struct tm tm;
  131. time_t tt;
  132. time(&tt);
  133. tm = *localtime(&tt);
  134. time_t tt_round = 0;
  135. tm.tm_sec = 0;
  136. if (minute >= 0) {
  137. period_type = HOURLY;
  138. tm.tm_min = minute;
  139. }
  140. if (hour >= 0) {
  141. period_type = DAILY;
  142. tm.tm_hour = hour;
  143. }
  144. if (week >= 0) {
  145. period_type = WEEKLY;
  146. }
  147. else if (day > 0) {
  148. period_type = MONTHLY;
  149. tm.tm_mday = day;
  150. if (month > 0) {
  151. period_type = YEARLY;
  152. tm.tm_mon = month - 1;
  153. }
  154. }
  155. if (period_type == UNKOWN) {
  156. return -1;
  157. }
  158. tt_round = mktime(&tm);
  159. if (week >= 0) {
  160. tt_round = tt + (week-tm.tm_wday)*SECONDS_PER_DAY;
  161. }
  162. if (tt_round > tt) {
  163. return tt_round;
  164. }
  165. switch(period_type) {
  166. case HOURLY:
  167. tt_round += SECONDS_PER_HOUR;
  168. return tt_round;
  169. case DAILY:
  170. tt_round += SECONDS_PER_DAY;
  171. return tt_round;
  172. case WEEKLY:
  173. tt_round += SECONDS_PER_WEEK;
  174. return tt_round;
  175. case MONTHLY:
  176. if (++tm.tm_mon == 12) {
  177. tm.tm_mon = 0;
  178. ++tm.tm_year;
  179. }
  180. break;
  181. case YEARLY:
  182. ++tm.tm_year;
  183. break;
  184. default:
  185. return -1;
  186. }
  187. return mktime(&tm);
  188. }
  189. int month_atoi(const char* month) {
  190. for (size_t i = 0; i < 12; ++i) {
  191. if (strnicmp(month, s_months[i], strlen(month)) == 0)
  192. return i+1;
  193. }
  194. return 0;
  195. }
  196. const char* month_itoa(int month) {
  197. if (month < 1 || month > 12) {
  198. return NULL;
  199. }
  200. return s_months[month-1];
  201. }
  202. datetime_t get_compile_datetime() {
  203. static datetime_t dt;
  204. char month[32];
  205. sscanf(__DATE__, "%s %d %d", month, &dt.day, &dt.year);
  206. sscanf(__TIME__, "%d %d %d", &dt.hour, &dt.min, &dt.sec);
  207. dt.month = month_atoi(month);
  208. return dt;
  209. }