localtime.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. /* $Id$ */
  2. #include <time.h>
  3. #define LEAPYEAR(year) (!((year) % 4) && (((year) % 100) || !((year) % 400)))
  4. #define YEARSIZE(year) (LEAPYEAR(year) ? 366 : 365)
  5. #define FIRSTSUNDAY(t) (((t)->tm_yday - (t)->tm_wday + 420) % 7)
  6. static int
  7. last_sunday(d, t)
  8. register int d;
  9. register struct tm *t;
  10. {
  11. int first = FIRSTSUNDAY(t);
  12. if (d >= 58 && LEAPYEAR(t->tm_year+1900)) d++;
  13. if (d < first) return first;
  14. return d - (d - first) % 7;
  15. }
  16. dysize(y)
  17. {
  18. /* compatibility */
  19. return YEARSIZE(y);
  20. }
  21. extern struct tm *gmtime();
  22. struct tm *
  23. localtime(clock)
  24. long *clock;
  25. {
  26. register struct tm *gmt;
  27. long cl;
  28. int begindst, enddst;
  29. extern int __daylight;
  30. extern long __timezone;
  31. tzset();
  32. cl = *clock - __timezone;
  33. gmt = gmtime(&cl);
  34. if (__daylight) {
  35. /* daylight saving time.
  36. Unfortunately, rules differ for different countries.
  37. Implemented here are heuristics that got it right
  38. in Holland, over the last couple of years.
  39. Of course, there is no algorithm. It is all
  40. politics ...
  41. */
  42. begindst = last_sunday(89, gmt); /* last Sun before Apr */
  43. enddst = last_sunday(272, gmt); /* last Sun in Sep */
  44. if ((gmt->tm_yday>begindst ||
  45. (gmt->tm_yday==begindst && gmt->tm_hour>=2)) &&
  46. (gmt->tm_yday<enddst ||
  47. (gmt->tm_yday==enddst && gmt->tm_hour<3))) {
  48. /* it all happens between 2 and 3 */
  49. cl += 1*60*60;
  50. gmt = gmtime(&cl);
  51. gmt->tm_isdst++;
  52. }
  53. }
  54. return gmt;
  55. }