tm2sec.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include <u.h>
  2. #include <libc.h>
  3. #define TZSIZE 150
  4. static void readtimezone(void);
  5. static int rd_name(char**, char*);
  6. static int rd_long(char**, long*);
  7. static
  8. struct
  9. {
  10. char stname[4];
  11. char dlname[4];
  12. long stdiff;
  13. long dldiff;
  14. long dlpairs[TZSIZE];
  15. } timezone;
  16. #define SEC2MIN 60L
  17. #define SEC2HOUR (60L*SEC2MIN)
  18. #define SEC2DAY (24L*SEC2HOUR)
  19. /*
  20. * days per month plus days/year
  21. */
  22. static int dmsize[] =
  23. {
  24. 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  25. };
  26. static int ldmsize[] =
  27. {
  28. 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  29. };
  30. /*
  31. * return the days/month for the given year
  32. */
  33. static int *
  34. yrsize(int y)
  35. {
  36. if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
  37. return ldmsize;
  38. else
  39. return dmsize;
  40. }
  41. /*
  42. * compute seconds since Jan 1 1970 GMT
  43. * and convert to our timezone.
  44. */
  45. long
  46. tm2sec(Tm *tm)
  47. {
  48. long secs;
  49. int i, yday, year, *d2m;
  50. if(strcmp(tm->zone, "GMT") != 0 && timezone.stname[0] == 0)
  51. readtimezone();
  52. secs = 0;
  53. /*
  54. * seconds per year
  55. */
  56. year = tm->year + 1900;
  57. for(i = 1970; i < year; i++){
  58. d2m = yrsize(i);
  59. secs += d2m[0] * SEC2DAY;
  60. }
  61. /*
  62. * if mday is set, use mon and mday to compute yday
  63. */
  64. if(tm->mday){
  65. yday = 0;
  66. d2m = yrsize(year);
  67. for(i=0; i<tm->mon; i++)
  68. yday += d2m[i+1];
  69. yday += tm->mday-1;
  70. }else{
  71. yday = tm->yday;
  72. }
  73. secs += yday * SEC2DAY;
  74. /*
  75. * hours, minutes, seconds
  76. */
  77. secs += tm->hour * SEC2HOUR;
  78. secs += tm->min * SEC2MIN;
  79. secs += tm->sec;
  80. /*
  81. * Only handles zones mentioned in /env/timezone,
  82. * but things get too ambiguous otherwise.
  83. */
  84. if(strcmp(tm->zone, timezone.stname) == 0)
  85. secs -= timezone.stdiff;
  86. else if(strcmp(tm->zone, timezone.dlname) == 0)
  87. secs -= timezone.dldiff;
  88. if(secs < 0)
  89. secs = 0;
  90. return secs;
  91. }
  92. static
  93. void
  94. readtimezone(void)
  95. {
  96. char buf[TZSIZE*11+30], *p;
  97. int i;
  98. memset(buf, 0, sizeof(buf));
  99. i = open("/env/timezone", 0);
  100. if(i < 0)
  101. goto error;
  102. if(read(i, buf, sizeof(buf)) >= sizeof(buf))
  103. goto error;
  104. close(i);
  105. p = buf;
  106. if(rd_name(&p, timezone.stname))
  107. goto error;
  108. if(rd_long(&p, &timezone.stdiff))
  109. goto error;
  110. if(rd_name(&p, timezone.dlname))
  111. goto error;
  112. if(rd_long(&p, &timezone.dldiff))
  113. goto error;
  114. for(i=0; i<TZSIZE; i++) {
  115. if(rd_long(&p, &timezone.dlpairs[i]))
  116. goto error;
  117. if(timezone.dlpairs[i] == 0)
  118. return;
  119. }
  120. error:
  121. timezone.stdiff = 0;
  122. strcpy(timezone.stname, "GMT");
  123. timezone.dlpairs[0] = 0;
  124. }
  125. static int
  126. rd_name(char **f, char *p)
  127. {
  128. int c, i;
  129. for(;;) {
  130. c = *(*f)++;
  131. if(c != ' ' && c != '\n')
  132. break;
  133. }
  134. for(i=0; i<3; i++) {
  135. if(c == ' ' || c == '\n')
  136. return 1;
  137. *p++ = c;
  138. c = *(*f)++;
  139. }
  140. if(c != ' ' && c != '\n')
  141. return 1;
  142. *p = 0;
  143. return 0;
  144. }
  145. static int
  146. rd_long(char **f, long *p)
  147. {
  148. int c, s;
  149. long l;
  150. s = 0;
  151. for(;;) {
  152. c = *(*f)++;
  153. if(c == '-') {
  154. s++;
  155. continue;
  156. }
  157. if(c != ' ' && c != '\n')
  158. break;
  159. }
  160. if(c == 0) {
  161. *p = 0;
  162. return 0;
  163. }
  164. l = 0;
  165. for(;;) {
  166. if(c == ' ' || c == '\n')
  167. break;
  168. if(c < '0' || c > '9')
  169. return 1;
  170. l = l*10 + c-'0';
  171. c = *(*f)++;
  172. }
  173. if(s)
  174. l = -l;
  175. *p = l;
  176. return 0;
  177. }