timec.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include <avr/pgmspace.h>
  2. #include "stime.h"
  3. #include "timec.h"
  4. #include "main.h"
  5. #include "ff.h"
  6. #include "xprintf.h"
  7. __flash const unsigned char mi[] = {3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
  8. unsigned char calc_weekday(struct tm *ct) {
  9. unsigned char w, x;
  10. x = ct->tm_year - 100;
  11. w = x%7;
  12. if(x != 0) { /* if year is not 2000 */
  13. /* Count only past years, for example if current year is 2004, count only 2000-2003, so x-- */
  14. x--;
  15. w += x >> 2; /* add number of years which are divisible by 4 4 */
  16. w -= x/100; /* subtract number of years which are divisible by 100 */
  17. w++; /* add the year 2000 which is divisible by 400 */
  18. }
  19. /* Add first weekday (Saturday 2000-01-01) */
  20. w+=4;
  21. /* Months */
  22. if(ct->tm_mon+1 > 1) { /* if it's not January */
  23. w += mi[ct->tm_mon+1 - 2]; /* add array increment */
  24. }
  25. /* Days */
  26. w += ct->tm_mday;
  27. /*
  28. ** If current month is March or later, and it's a leap year, this means February
  29. ** was 29 days so we have to add 1.
  30. */
  31. if(ct->tm_mon+1 > 2)
  32. if(!(ct->tm_year&3)) w+=1;
  33. /* Result modulo 7 */
  34. return (w%7)+1; /* 1 = Monday, 7 = Sunday */
  35. }
  36. signed int local_time_diff(time_t time) {
  37. signed char offset = TIME_OFFSET;
  38. unsigned char t;
  39. struct tm *ct = gmtime(&time);
  40. unsigned char weekday = calc_weekday(ct);
  41. if (ct->tm_mon+1 == 3 || ct->tm_mon+1 == 10){
  42. t = 35 + weekday - ct->tm_mday;
  43. t += 31;
  44. t = t%7;
  45. t = 31-t;
  46. if (ct->tm_mon+1 == 3){ // March
  47. if (ct->tm_mday==t) { // last Sunday
  48. if (ct->tm_hour >= 2 )
  49. offset = SUMMER_TIME_OFFSET;
  50. } else if (ct->tm_mday > t) { // after last Sunday
  51. offset = SUMMER_TIME_OFFSET;
  52. }
  53. } else { // October
  54. if (ct->tm_mday == t) { // last Sunday
  55. if(ct->tm_hour < 2)
  56. offset = SUMMER_TIME_OFFSET;
  57. } else if (ct->tm_mday < t) { // before last Sunday
  58. offset = SUMMER_TIME_OFFSET;
  59. }
  60. }
  61. } else if (ct->tm_mon+1 > 3 && ct->tm_mon+1 < 10) {
  62. offset = SUMMER_TIME_OFFSET;
  63. }
  64. return offset;
  65. }
  66. const char *local_time_mark(time_t time) {
  67. static char buf[4];
  68. signed int time_diff = local_time_diff(time);
  69. if (time_diff < 0) {
  70. buf[0] = '-';
  71. time_diff = -time_diff;
  72. } else {
  73. buf[0] = '+';
  74. }
  75. buf[1] = time_diff/10 + '0'; /* never greater than 23 */
  76. buf[2] = time_diff%10 + '0';
  77. buf[3] = '\0';
  78. return buf;
  79. }
  80. /* Make ISO time string */
  81. char *get_iso_time(time_t time, unsigned char local) {
  82. static char output[32];
  83. if (local)
  84. time += local_time_diff(time) * (signed int)3600;
  85. struct tm *ct = gmtime(&time);
  86. xsprintf(output, PSTR("%4u-%02u-%02uT%02u:%02u:%02u.000%s"), ct->tm_year+1900, ct->tm_mon+1, ct->tm_mday, ct->tm_hour, ct->tm_min, ct->tm_sec, local?local_time_mark(time):"Z");
  87. return output;
  88. }
  89. /*---------------------------------------------------------*/
  90. /* User Provided Timer Function for FatFs module */
  91. /*---------------------------------------------------------*/
  92. DWORD get_fattime (void)
  93. {
  94. struct tm *stm;
  95. time_t localtime = utc + local_time_diff(utc) * (signed int)3600;
  96. stm = gmtime(&localtime);
  97. return (DWORD)(stm->tm_year - 80) << 25 |
  98. (DWORD)(stm->tm_mon + 1) << 21 |
  99. (DWORD)stm->tm_mday << 16 |
  100. (DWORD)stm->tm_hour << 11 |
  101. (DWORD)stm->tm_min << 5 |
  102. (DWORD)stm->tm_sec >> 1;
  103. }