date.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. * (C) Copyright 2001
  3. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  4. *
  5. * See file CREDITS for list of people who contributed to this
  6. * project.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation; either version 2 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21. * MA 02111-1307 USA
  22. */
  23. /*
  24. * Date & Time support for Philips PCF8563 RTC
  25. */
  26. #include <common.h>
  27. #include <command.h>
  28. #include <rtc.h>
  29. #if (CONFIG_COMMANDS & CFG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
  30. #define FEBRUARY 2
  31. #define STARTOFTIME 1970
  32. #define SECDAY 86400L
  33. #define SECYR (SECDAY * 365)
  34. #define leapyear(year) ((year) % 4 == 0)
  35. #define days_in_year(a) (leapyear(a) ? 366 : 365)
  36. #define days_in_month(a) (month_days[(a) - 1])
  37. static int month_days[12] = {
  38. 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  39. };
  40. /*
  41. * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
  42. */
  43. void GregorianDay(struct rtc_time * tm)
  44. {
  45. int leapsToDate;
  46. int lastYear;
  47. int day;
  48. int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
  49. lastYear=tm->tm_year-1;
  50. /*
  51. * Number of leap corrections to apply up to end of last year
  52. */
  53. leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
  54. /*
  55. * This year is a leap year if it is divisible by 4 except when it is
  56. * divisible by 100 unless it is divisible by 400
  57. *
  58. * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
  59. */
  60. if((tm->tm_year%4==0) &&
  61. ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
  62. (tm->tm_mon>2)) {
  63. /*
  64. * We are past Feb. 29 in a leap year
  65. */
  66. day=1;
  67. } else {
  68. day=0;
  69. }
  70. day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
  71. tm->tm_wday=day%7;
  72. }
  73. void to_tm(int tim, struct rtc_time * tm)
  74. {
  75. register int i;
  76. register long hms, day;
  77. day = tim / SECDAY;
  78. hms = tim % SECDAY;
  79. /* Hours, minutes, seconds are easy */
  80. tm->tm_hour = hms / 3600;
  81. tm->tm_min = (hms % 3600) / 60;
  82. tm->tm_sec = (hms % 3600) % 60;
  83. /* Number of years in days */
  84. for (i = STARTOFTIME; day >= days_in_year(i); i++) {
  85. day -= days_in_year(i);
  86. }
  87. tm->tm_year = i;
  88. /* Number of months in days left */
  89. if (leapyear(tm->tm_year)) {
  90. days_in_month(FEBRUARY) = 29;
  91. }
  92. for (i = 1; day >= days_in_month(i); i++) {
  93. day -= days_in_month(i);
  94. }
  95. days_in_month(FEBRUARY) = 28;
  96. tm->tm_mon = i;
  97. /* Days are what is left over (+1) from all that. */
  98. tm->tm_mday = day + 1;
  99. /*
  100. * Determine the day of week
  101. */
  102. GregorianDay(tm);
  103. }
  104. /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
  105. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
  106. * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
  107. *
  108. * [For the Julian calendar (which was used in Russia before 1917,
  109. * Britain & colonies before 1752, anywhere else before 1582,
  110. * and is still in use by some communities) leave out the
  111. * -year/100+year/400 terms, and add 10.]
  112. *
  113. * This algorithm was first published by Gauss (I think).
  114. *
  115. * WARNING: this function will overflow on 2106-02-07 06:28:16 on
  116. * machines were long is 32-bit! (However, as time_t is signed, we
  117. * will already get problems at other places on 2038-01-19 03:14:08)
  118. */
  119. unsigned long
  120. mktime (unsigned int year, unsigned int mon,
  121. unsigned int day, unsigned int hour,
  122. unsigned int min, unsigned int sec)
  123. {
  124. if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
  125. mon += 12; /* Puts Feb last since it has leap day */
  126. year -= 1;
  127. }
  128. return (((
  129. (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
  130. year*365 - 719499
  131. )*24 + hour /* now have hours */
  132. )*60 + min /* now have minutes */
  133. )*60 + sec; /* finally seconds */
  134. }
  135. #endif /* CFG_CMD_DATE */