fork download
  1. #define _POSIX_C_SOURCE 200809L
  2. #include <errno.h>
  3.  
  4. #include <time.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. #define YYYYMMDDhhmmss 0
  10. #define YYMMDDhhmmss 1
  11. #define ssmmhhDDMMYYYY 2
  12. #define ssmmhhDDMMYY 3
  13.  
  14. int chars_to_int(const char * s, unsigned int n)
  15. {
  16. int rv = 0;
  17. while (n--)
  18. {
  19. if (*s >= 48 && *s <= 57)
  20. {
  21. rv = 10 * rv + (*s-48);
  22. }
  23. else if (*s == 32)
  24. {
  25. // gently handle space
  26. rv *= 10;
  27. }
  28. else
  29. {
  30. return -1;
  31. }
  32. ++s;
  33. }
  34. return rv;
  35. }
  36.  
  37. /**
  38.  * Convert a string in one of the following formats into a (possibly negative) offset of seconds.
  39.  * +hhmm
  40.  * -hhmm
  41.  * 2Bhhmm
  42.  * 2Dhhmm
  43.  * 2bhhmm
  44.  * 2dhhmm
  45.  *
  46.  * where h and m are digits representing hours and minutes
  47.  *
  48.  * @param input String in one of the formats
  49.  * @return true and the offset in seconds if input matches one of the formats
  50.  * false and 0 if it does not
  51.  */
  52. int string_to_offset(const char * input)
  53. {
  54. int len = strlen(input);
  55. int offset = 0;
  56. int sign = 0;
  57. if (len == 5)
  58. {
  59. offset = 1;
  60. if (input[0] == '+')
  61. {
  62. // +hhmm
  63. sign = +1;
  64. }
  65. else if (input[0] == '-')
  66. {
  67. // -hhmm
  68. sign = -1;
  69. }
  70. }
  71. else if (len == 6 && input[0] == '2')
  72. {
  73. offset = 2;
  74. if (input[1] == 'B' || input[1] == 'b')
  75. {
  76. // 2Bhhmm or 2bhhmm
  77. sign = +1;
  78. }
  79. if (input[1] == 'D' || input[1] == 'd')
  80. {
  81. // 2Dhhmm or 2Dhhmm
  82. sign = -1;
  83. }
  84. }
  85.  
  86. if (offset != 0 && sign != 0)
  87. {
  88. return (sign * (3600 * chars_to_int(input+offset,2) + 60 * chars_to_int(input+offset+2, 2)));
  89. }
  90. else
  91. {
  92. return -1;
  93. }
  94. }
  95.  
  96. // Return the current century.
  97. int current_century()
  98. {
  99. int current_century = -1;
  100.  
  101. if (current_century == -1)
  102. {
  103. time_t rawtime;
  104. time ( &rawtime );
  105. struct tm * timeinfo;
  106. timeinfo = localtime ( &rawtime );
  107. current_century = (1900+timeinfo->tm_year)/100;
  108. }
  109.  
  110. return current_century;
  111. }
  112.  
  113. // Return the current year.
  114. int current_year()
  115. {
  116. int current_year = -1;
  117.  
  118. if (current_year == -1)
  119. {
  120. time_t rawtime;
  121. time ( &rawtime );
  122. struct tm * timeinfo;
  123. timeinfo = localtime ( &rawtime );
  124. current_year = 1900+timeinfo->tm_year;
  125. }
  126.  
  127. return current_year;
  128. }
  129.  
  130. /**
  131.  * Add a century to a year, so that the year is max 20 years in the future and max 80 years in the past
  132.  *
  133.  * @param year The last two digits of the year
  134.  * @return The four digit year as int.
  135.  */
  136. int add_century(int year)
  137. {
  138. static const int yearsInFuture = 20;
  139.  
  140. int currentYear = current_year();
  141. int proposedYear = year + 100*current_century();
  142. if (proposedYear - currentYear > yearsInFuture)
  143. {
  144. // Too far in future, e.g. current year = 2101, year = 99 (proposedYear = 2199)
  145. proposedYear = proposedYear - 100;
  146. }
  147. else if (currentYear - proposedYear > 100 - yearsInFuture)
  148. {
  149. // Too far in the past, e.g. current year = 2099, year = 00 (proposedYear = 2000)
  150. proposedYear = proposedYear + 100;
  151. }
  152.  
  153. return proposedYear;
  154. }
  155.  
  156. /**
  157.  * Converts a string representing a local date/time to the native time_t type.
  158.  * The timezone of the date/time string is indicated by the timezone string which
  159.  * may either be in [+-]hhmm or 2[bBdD]hhmm format or may be any timezone recognized
  160.  * by the underlying C-library (e.g. "GMT+2").
  161.  *
  162.  * @param time The string representing the date/time.
  163.  * @param timezone The offset compared to UTC represented by the time or the timezone time refers to
  164.  * @param format The format in which the date/time is stored in the string
  165.  * @return The time in native time_t type
  166.  */
  167. time_t localtime_to_time_t(const char * time, const char * timezone, int format)
  168. {
  169. //time_t rv;
  170.  
  171. //////////////
  172. struct tm timeinfo;
  173. switch (format)
  174. {
  175. case YYYYMMDDhhmmss:
  176. if (strlen(time) < 14) return 0;
  177. timeinfo.tm_year = chars_to_int(time + 0, 4) - 1900;
  178. timeinfo.tm_mon = chars_to_int(time + 4, 2) - 1;
  179. timeinfo.tm_mday = chars_to_int(time + 6, 2);
  180. timeinfo.tm_hour = chars_to_int(time + 8, 2);
  181. timeinfo.tm_min = chars_to_int(time + 10, 2);
  182. timeinfo.tm_sec = chars_to_int(time + 12, 2);
  183. break;
  184. case YYMMDDhhmmss:
  185. if (strlen(time) < 12) return 0;
  186. timeinfo.tm_year = add_century(chars_to_int(time + 0, 2)) - 1900;
  187. timeinfo.tm_mon = chars_to_int(time + 2, 2) - 1;
  188. timeinfo.tm_mday = chars_to_int(time + 4, 2);
  189. timeinfo.tm_hour = chars_to_int(time + 6, 2);
  190. timeinfo.tm_min = chars_to_int(time + 8, 2);
  191. timeinfo.tm_sec = chars_to_int(time + 10, 2);
  192. puts("here");
  193. break;
  194. case ssmmhhDDMMYYYY:
  195. if (strlen(time) < 14) return 0;
  196. timeinfo.tm_sec = chars_to_int(time, 2);
  197. timeinfo.tm_min = chars_to_int(time + 2, 2);
  198. timeinfo.tm_hour = chars_to_int(time + 4, 2);
  199. timeinfo.tm_mday = chars_to_int(time + 6, 2);
  200. timeinfo.tm_mon = chars_to_int(time + 8, 2) - 1;
  201. timeinfo.tm_year = chars_to_int(time + 10, 4) - 1900;
  202. break;
  203. case ssmmhhDDMMYY:
  204. if (strlen(time) < 12) return 0;
  205. timeinfo.tm_sec = chars_to_int(time, 2);
  206. timeinfo.tm_min = chars_to_int(time + 2, 2);
  207. timeinfo.tm_hour = chars_to_int(time + 4, 2);
  208. timeinfo.tm_mday = chars_to_int(time + 6, 2);
  209. timeinfo.tm_mon = chars_to_int(time + 8, 2) - 1;
  210. timeinfo.tm_year = add_century(chars_to_int(time + 0, 2)) - 1900;
  211. break;
  212. }
  213.  
  214. printf("%d\n", timeinfo.tm_mday);
  215.  
  216. /////////////
  217.  
  218. timeinfo.tm_isdst = -1;
  219. int timezone_offset = string_to_offset(timezone);
  220. if (timezone_offset) {
  221. printf("%d\n", timezone_offset);
  222. }
  223.  
  224.  
  225. if (timezone_offset > -1)
  226. {
  227. // timezone is an offset
  228. // TZEnv utc("UTC");
  229.  
  230. //////////////////////////
  231. char *tz = getenv("TZ");
  232. //char dup_tz[strlen(tz) + 1];
  233. //strcpy(dup_tz, tz);
  234. //puts(dup_tz);
  235. if (tz) {
  236.  
  237. }
  238.  
  239. //setenv("TZ", "", 1); // TZ empty refers to UTC
  240. //tzset();
  241.  
  242.  
  243. ///////////////////////////
  244.  
  245. // errno = 0;
  246. // rv = mktime(&timeinfo) - timezone_offset;
  247. // int saved_errno = errno;
  248.  
  249. // setenv("TZ", dup_tz, 1);
  250.  
  251.  
  252. // errno = saved_errno;
  253.  
  254. } else {
  255. return 99999;
  256. }
  257.  
  258. //if (rv == -1) return -1;
  259. return 0;
  260. }
  261.  
  262. int main(void) {
  263.  
  264. time_t epoch = localtime_to_time_t("181218213533", "2b0200", YYMMDDhhmmss);
  265. printf("%lld\n", (long long) epoch);
  266.  
  267. return 0;
  268. }
  269.  
Success #stdin #stdout 0s 9424KB
stdin
Standard input is empty
stdout
here
18
7200
0