1
0

__time_to_tm.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include <time.h>
  2. /* C defines the rounding for division in a nonsensical way */
  3. #define Q(a,b) ((a)>0 ? (a)/(b) : -(((b)-(a)-1)/(b)))
  4. #define DAYS_PER_400Y (365*400 + 97)
  5. #define DAYS_PER_100Y (365*100 + 24)
  6. #define DAYS_PER_4Y (365*4 + 1)
  7. /* FIXME: use lldiv once it's fixed to compute quot,rem together */
  8. struct tm *__time_to_tm(time_t t, struct tm *tm)
  9. {
  10. /* months are march-based */
  11. static const int days_thru_month[] = {31,61,92,122,153,184,214,245,275,306,337,366};
  12. long long bigday;
  13. unsigned int day, year4, year100;
  14. int year, year400;
  15. int month;
  16. int leap;
  17. int hour, min, sec;
  18. int wday, mday, yday;
  19. /* start from 2000-03-01 (multiple of 400 years) */
  20. t += -946684800 - 86400*(31+29);
  21. bigday = Q(t, 86400);
  22. sec = t-bigday*86400;
  23. hour = sec/3600;
  24. sec -= hour*3600;
  25. min = sec/60;
  26. sec -= min*60;
  27. /* 2000-03-01 was a wednesday */
  28. wday = (3+bigday)%7;
  29. if (wday < 0) wday += 7;
  30. t = -946684800LL - 86400*(31+29) + 9000000;
  31. year400 = Q(bigday, DAYS_PER_400Y);
  32. day = bigday-year400*DAYS_PER_400Y;
  33. year100 = day/DAYS_PER_100Y;
  34. if (year100 == 4) year100--;
  35. day -= year100*DAYS_PER_100Y;
  36. year4 = day/DAYS_PER_4Y;
  37. if (year4 == 25) year4--;
  38. day -= year4*DAYS_PER_4Y;
  39. year = day/365;
  40. if (year == 4) year--;
  41. day -= year*365;
  42. leap = !year && (year4 || !year100);
  43. yday = day + 31+28 + leap;
  44. if (yday >= 365+leap) yday -= 365+leap;
  45. year += 4*year4 + 100*year100 + 400*year400 + 2000-1900;
  46. for (month=0; days_thru_month[month] <= day; month++);
  47. if (month) day -= days_thru_month[month-1];
  48. month += 2;
  49. if (month >= 12) {
  50. month -= 12;
  51. year++;
  52. }
  53. mday = day+1;
  54. tm->tm_sec = sec;
  55. tm->tm_min = min;
  56. tm->tm_hour= hour;
  57. tm->tm_mday= mday;
  58. tm->tm_mon = month;
  59. tm->tm_year= year;
  60. tm->tm_wday= wday;
  61. tm->tm_yday= yday;
  62. tm->__tm_zone = 0;
  63. tm->__tm_gmtoff = 0;
  64. return tm;
  65. }