fork(58) download
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <time.h>
  4.  
  5. typedef unsigned uint;
  6. typedef unsigned long long uint64;
  7.  
  8. struct tm* SecondsSinceEpochToDateTime(struct tm* pTm, uint64 SecondsSinceEpoch)
  9. {
  10. uint64 sec;
  11. uint quadricentennials, centennials, quadrennials, annuals/*1-ennial?*/;
  12. uint year, leap;
  13. uint yday, hour, min;
  14. uint month, mday, wday;
  15. static const uint daysSinceJan1st[2][13]=
  16. {
  17. {0,31,59,90,120,151,181,212,243,273,304,334,365}, // 365 days, non-leap
  18. {0,31,60,91,121,152,182,213,244,274,305,335,366} // 366 days, leap
  19. };
  20. /*
  21.   400 years:
  22.  
  23.   1st hundred, starting immediately after a leap year that's a multiple of 400:
  24.   n n n l \
  25.   n n n l } 24 times
  26.   ... /
  27.   n n n l /
  28.   n n n n
  29.  
  30.   2nd hundred:
  31.   n n n l \
  32.   n n n l } 24 times
  33.   ... /
  34.   n n n l /
  35.   n n n n
  36.  
  37.   3rd hundred:
  38.   n n n l \
  39.   n n n l } 24 times
  40.   ... /
  41.   n n n l /
  42.   n n n n
  43.  
  44.   4th hundred:
  45.   n n n l \
  46.   n n n l } 24 times
  47.   ... /
  48.   n n n l /
  49.   n n n L <- 97'th leap year every 400 years
  50. */
  51.  
  52. // Re-bias from 1970 to 1601:
  53. // 1970 - 1601 = 369 = 3*100 + 17*4 + 1 years (incl. 89 leap days) =
  54. // (3*100*(365+24/100) + 17*4*(365+1/4) + 1*365)*24*3600 seconds
  55. sec = SecondsSinceEpoch + 11644473600;
  56.  
  57. wday = (uint)((sec / 86400 + 1) % 7); // day of week
  58.  
  59. // Remove multiples of 400 years (incl. 97 leap days)
  60. quadricentennials = (uint)(sec / 12622780800ULL); // 400*365.2425*24*3600
  61. sec %= 12622780800ULL;
  62.  
  63. // Remove multiples of 100 years (incl. 24 leap days), can't be more than 3
  64. // (because multiples of 4*100=400 years (incl. leap days) have been removed)
  65. centennials = (uint)(sec / 3155673600ULL); // 100*(365+24/100)*24*3600
  66. if (centennials > 3)
  67. {
  68. centennials = 3;
  69. }
  70. sec -= centennials * 3155673600ULL;
  71.  
  72. // Remove multiples of 4 years (incl. 1 leap day), can't be more than 24
  73. // (because multiples of 25*4=100 years (incl. leap days) have been removed)
  74. quadrennials = (uint)(sec / 126230400); // 4*(365+1/4)*24*3600
  75. if (quadrennials > 24)
  76. {
  77. quadrennials = 24;
  78. }
  79. sec -= quadrennials * 126230400ULL;
  80.  
  81. // Remove multiples of years (incl. 0 leap days), can't be more than 3
  82. // (because multiples of 4 years (incl. leap days) have been removed)
  83. annuals = (uint)(sec / 31536000); // 365*24*3600
  84. if (annuals > 3)
  85. {
  86. annuals = 3;
  87. }
  88. sec -= annuals * 31536000ULL;
  89.  
  90. // Calculate the year and find out if it's leap
  91. year = 1601 + quadricentennials * 400 + centennials * 100 + quadrennials * 4 + annuals;
  92. leap = !(year % 4) && (year % 100 || !(year % 400));
  93.  
  94. // Calculate the day of the year and the time
  95. yday = sec / 86400;
  96. sec %= 86400;
  97. hour = sec / 3600;
  98. sec %= 3600;
  99. min = sec / 60;
  100. sec %= 60;
  101.  
  102. // Calculate the month
  103. for (mday = month = 1; month < 13; month++)
  104. {
  105. if (yday < daysSinceJan1st[leap][month])
  106. {
  107. mday += yday - daysSinceJan1st[leap][month - 1];
  108. break;
  109. }
  110. }
  111.  
  112. // Fill in C's "struct tm"
  113. memset(pTm, 0, sizeof(*pTm));
  114. pTm->tm_sec = sec; // [0,59]
  115. pTm->tm_min = min; // [0,59]
  116. pTm->tm_hour = hour; // [0,23]
  117. pTm->tm_mday = mday; // [1,31] (day of month)
  118. pTm->tm_mon = month - 1; // [0,11] (month)
  119. pTm->tm_year = year - 1900; // 70+ (year since 1900)
  120. pTm->tm_wday = wday; // [0,6] (day since Sunday AKA day of week)
  121. pTm->tm_yday = yday; // [0,365] (day since January 1st AKA day of year)
  122. pTm->tm_isdst = -1; // daylight saving time flag
  123.  
  124. return pTm;
  125. }
  126.  
  127. int main(void)
  128. {
  129. struct tm t;
  130. time_t tt;
  131. printf("%s", asctime(SecondsSinceEpochToDateTime(&t, -1)));
  132. printf("%s", asctime(gmtime((tt = 0, &tt))));
  133. printf("%s", asctime(SecondsSinceEpochToDateTime(&t, 0)));
  134. printf("%s\n", asctime(SecondsSinceEpochToDateTime(&t, 1)));
  135.  
  136. printf("%s", asctime(SecondsSinceEpochToDateTime(&t, 946684799)));
  137. printf("%s", asctime(SecondsSinceEpochToDateTime(&t, 946684799+1)));
  138. printf("%s\n", asctime(SecondsSinceEpochToDateTime(&t, 946684799+2)));
  139.  
  140. printf("%s", asctime(SecondsSinceEpochToDateTime(&t, 978307199)));
  141. printf("%s", asctime(SecondsSinceEpochToDateTime(&t, 978307199+1)));
  142. printf("%s\n", asctime(SecondsSinceEpochToDateTime(&t, 978307199+2)));
  143.  
  144. printf("%s", asctime(SecondsSinceEpochToDateTime(&t, tt = time(0))));
  145. printf("%s", asctime(gmtime(&tt)));
  146. return 0;
  147. }
  148.  
Success #stdin #stdout 0.01s 1808KB
stdin
Standard input is empty
stdout
Wed Dec 31 23:59:59 1969
Thu Jan  1 00:00:00 1970
Thu Jan  1 00:00:00 1970
Thu Jan  1 00:00:01 1970

Fri Dec 31 23:59:59 1999
Sat Jan  1 00:00:00 2000
Sat Jan  1 00:00:01 2000

Sun Dec 31 23:59:59 2000
Mon Jan  1 00:00:00 2001
Mon Jan  1 00:00:01 2001

Mon Jun 25 11:39:42 2012
Mon Jun 25 11:39:42 2012