Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2017
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.76 KB | None | 0 0
  1. #include <iostream>
  2. #include <ctime>
  3. #include <cstring>
  4.  
  5. struct tm* SecondsSinceEpochToDateTime(struct tm* pTm, uint64_t SecondsSinceEpoch)
  6. {
  7. uint64_t sec;
  8. unsigned int quadricentennials, centennials, quadrennials, annuals/*1-ennial?*/;
  9. unsigned int year, leap;
  10. unsigned int yday, hour, min;
  11. unsigned int month, mday, wday;
  12. static const unsigned int daysSinceJan1st[2][13]=
  13. {
  14. {0,31,59,90,120,151,181,212,243,273,304,334,365}, // 365 days, non-leap
  15. {0,31,60,91,121,152,182,213,244,274,305,335,366} // 366 days, leap
  16. };
  17. /*
  18. 400 years:
  19.  
  20. 1st hundred, starting immediately after a leap year that's a multiple of 400:
  21. n n n l
  22. n n n l } 24 times
  23. ... /
  24. n n n l /
  25. n n n n
  26.  
  27. 2nd hundred:
  28. n n n l
  29. n n n l } 24 times
  30. ... /
  31. n n n l /
  32. n n n n
  33.  
  34. 3rd hundred:
  35. n n n l
  36. n n n l } 24 times
  37. ... /
  38. n n n l /
  39. n n n n
  40.  
  41. 4th hundred:
  42. n n n l
  43. n n n l } 24 times
  44. ... /
  45. n n n l /
  46. n n n L <- 97'th leap year every 400 years
  47. */
  48.  
  49. // Re-bias from 1970 to 1601:
  50. // 1970 - 1601 = 369 = 3*100 + 17*4 + 1 years (incl. 89 leap days) =
  51. // (3*100*(365+24/100) + 17*4*(365+1/4) + 1*365)*24*3600 seconds
  52. sec = SecondsSinceEpoch + 11644473600ULL;
  53.  
  54. wday = (uint)((sec / 86400 + 1) % 7); // day of week
  55.  
  56. // Remove multiples of 400 years (incl. 97 leap days)
  57. quadricentennials = (uint)(sec / 12622780800ULL); // 400*365.2425*24*3600
  58. sec %= 12622780800ULL;
  59.  
  60. // Remove multiples of 100 years (incl. 24 leap days), can't be more than 3
  61. // (because multiples of 4*100=400 years (incl. leap days) have been removed)
  62. centennials = (uint)(sec / 3155673600ULL); // 100*(365+24/100)*24*3600
  63. if (centennials > 3)
  64. {
  65. centennials = 3;
  66. }
  67. sec -= centennials * 3155673600ULL;
  68.  
  69. // Remove multiples of 4 years (incl. 1 leap day), can't be more than 24
  70. // (because multiples of 25*4=100 years (incl. leap days) have been removed)
  71. quadrennials = (uint)(sec / 126230400); // 4*(365+1/4)*24*3600
  72. if (quadrennials > 24)
  73. {
  74. quadrennials = 24;
  75. }
  76. sec -= quadrennials * 126230400ULL;
  77.  
  78. // Remove multiples of years (incl. 0 leap days), can't be more than 3
  79. // (because multiples of 4 years (incl. leap days) have been removed)
  80. annuals = (uint)(sec / 31536000); // 365*24*3600
  81. if (annuals > 3)
  82. {
  83. annuals = 3;
  84. }
  85. sec -= annuals * 31536000ULL;
  86.  
  87. // Calculate the year and find out if it's leap
  88. year = 1601 + quadricentennials * 400 + centennials * 100 + quadrennials * 4 + annuals;
  89. leap = !(year % 4) && (year % 100 || !(year % 400));
  90.  
  91. // Calculate the day of the year and the time
  92. yday = sec / 86400;
  93. sec %= 86400;
  94. hour = sec / 3600;
  95. sec %= 3600;
  96. min = sec / 60;
  97. sec %= 60;
  98.  
  99. // Calculate the month
  100. for (mday = month = 1; month < 13; month++)
  101. {
  102. if (yday < daysSinceJan1st[leap][month])
  103. {
  104. mday += yday - daysSinceJan1st[leap][month - 1];
  105. break;
  106. }
  107. }
  108.  
  109. // Fill in C's "struct tm"
  110. memset(pTm, 0, sizeof(*pTm));
  111. pTm->tm_sec = sec; // [0,59]
  112. pTm->tm_min = min; // [0,59]
  113. pTm->tm_hour = hour; // [0,23]
  114. pTm->tm_mday = mday; // [1,31] (day of month)
  115. pTm->tm_mon = month - 1; // [0,11] (month)
  116. pTm->tm_year = year - 1900; // 70+ (year since 1900)
  117. pTm->tm_wday = wday; // [0,6] (day since Sunday AKA day of week)
  118. pTm->tm_yday = yday; // [0,365] (day since January 1st AKA day of year)
  119. pTm->tm_isdst = -1; // daylight saving time flag
  120.  
  121. return pTm;
  122. }
  123.  
  124.  
  125. struct tm* fromOADate(struct tm* p_Tm, double p_OADate)
  126. {
  127. static const int64_t OA_UnixTimestamp = -2209161600; /* 30-Dec-1899 */
  128.  
  129. if (!( -109205 <= p_OADate /* 01-Jan-1601 */
  130. && p_OADate <= 2958465)) /* 31-Dec-9999 */
  131. {
  132. throw std::string("OADate must be between 109205 and 2958465!");
  133. }
  134.  
  135. int64_t OADatePassedDays = p_OADate;
  136. double OADateDayTime = p_OADate - OADatePassedDays;
  137. int64_t OADateSeconds = OA_UnixTimestamp
  138. + OADatePassedDays * 24LL * 3600LL
  139. + OADateDayTime * 24.0 * 3600.0;
  140.  
  141. return SecondsSinceEpochToDateTime(p_Tm, OADateSeconds);
  142. }
  143.  
  144.  
  145. int main()
  146. {
  147. struct tm timeVal;
  148.  
  149. std::cout << asctime(fromOADate(&timeVal, -109205)); /* 01-Jan-1601 00:00:00 */
  150. std::cout << asctime(fromOADate(&timeVal, 0)); /* 30-Dec-1899 00:00:00 */
  151. std::cout << asctime(fromOADate(&timeVal, 25569)); /* 01-Jan-1970 00:00:00 */
  152. std::cout << asctime(fromOADate(&timeVal, 50424.134803241)); /* 19-Jan-2038 03:14:07 */
  153. std::cout << asctime(fromOADate(&timeVal, 2958465)); /* 31-Dec-9999 00:00:00 */
  154.  
  155. return 0;
  156. }
  157.  
  158. #include <iostream>
  159. #include <ctime>
  160.  
  161. struct tm* fromOADate(struct tm* p_Tm, double p_OADate)
  162. {
  163. static const int64_t OA_UnixTimestamp = -2209161600; /* 30-Dec-1899 */
  164.  
  165. if (!( 25569 <= p_OADate /* 01-Jan-1970 00:00:00 */
  166. && p_OADate <= 2958465)) /* 31-Dec-9999 00:00:00 */
  167. {
  168. throw std::string("OADate must be between 25569 and 2958465!");
  169. }
  170.  
  171. time_t OADatePassedDays = p_OADate;
  172. double OADateDayTime = p_OADate - OADatePassedDays;
  173. time_t OADateSeconds = OA_UnixTimestamp
  174. + OADatePassedDays * 24LL * 3600LL
  175. + OADateDayTime * 24.0 * 3600.0;
  176.  
  177. /* date was greater than 19-Jan-2038 and build is 32 bit */
  178. if (0 > OADateSeconds)
  179. {
  180. throw std::string("OADate must be between 25569 and 50424.134803241!");
  181. }
  182.  
  183. return gmtime_r(&OADateSeconds, p_Tm);
  184. }
  185.  
  186.  
  187. int main()
  188. {
  189. struct tm timeVal;
  190.  
  191. std::cout << asctime(fromOADate(&timeVal, 25569)); /* 01-Jan-1970 00:00:00 */
  192. std::cout << asctime(fromOADate(&timeVal, 50424.134803241)); /* 19-Jan-2038 03:14:07 */
  193.  
  194. return 0;
  195. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement