ctime.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. * This routine converts time as follows.
  3. * The epoch is 0000 Jan 1 1970 GMT.
  4. * The argument time is in seconds since then.
  5. * The localtime(t) entry returns a pointer to an array
  6. * containing
  7. *
  8. * seconds (0-59)
  9. * minutes (0-59)
  10. * hours (0-23)
  11. * day of month (1-31)
  12. * month (0-11)
  13. * year-1970
  14. * weekday (0-6, Sun is 0)
  15. * day of the year
  16. * daylight savings flag
  17. *
  18. * The routine gets the daylight savings time from the environment.
  19. *
  20. * asctime(tvec))
  21. * where tvec is produced by localtime
  22. * returns a ptr to a character string
  23. * that has the ascii time in the form
  24. *
  25. * \\
  26. * Thu Jan 01 00:00:00 GMT 1970n0
  27. * 012345678901234567890123456789
  28. * 0 1 2
  29. *
  30. * ctime(t) just calls localtime, then asctime.
  31. */
  32. #include <u.h>
  33. #include <libc.h>
  34. static char dmsize[12] =
  35. {
  36. 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  37. };
  38. /*
  39. * The following table is used for 1974 and 1975 and
  40. * gives the day number of the first day after the Sunday of the
  41. * change.
  42. */
  43. static int dysize(int);
  44. static void ct_numb(char*, int);
  45. #define TZSIZE 150
  46. static void readtimezone(void);
  47. static int rd_name(char**, char*);
  48. static int rd_long(char**, long*);
  49. static
  50. struct
  51. {
  52. char stname[4];
  53. char dlname[4];
  54. long stdiff;
  55. long dldiff;
  56. long dlpairs[TZSIZE];
  57. } timezone;
  58. char*
  59. ctime(long t)
  60. {
  61. return asctime(localtime(t));
  62. }
  63. Tm*
  64. localtime(long tim)
  65. {
  66. Tm *ct;
  67. long t, *p;
  68. int dlflag;
  69. if(timezone.stname[0] == 0)
  70. readtimezone();
  71. t = tim + timezone.stdiff;
  72. dlflag = 0;
  73. for(p = timezone.dlpairs; *p; p += 2)
  74. if(t >= p[0])
  75. if(t < p[1]) {
  76. t = tim + timezone.dldiff;
  77. dlflag++;
  78. break;
  79. }
  80. ct = gmtime(t);
  81. if(dlflag){
  82. strcpy(ct->zone, timezone.dlname);
  83. ct->tzoff = timezone.dldiff;
  84. } else {
  85. strcpy(ct->zone, timezone.stname);
  86. ct->tzoff = timezone.stdiff;
  87. }
  88. return ct;
  89. }
  90. Tm*
  91. gmtime(long tim)
  92. {
  93. int d0, d1;
  94. long hms, day;
  95. static Tm xtime;
  96. /*
  97. * break initial number into days
  98. */
  99. hms = tim % 86400L;
  100. day = tim / 86400L;
  101. if(hms < 0) {
  102. hms += 86400L;
  103. day -= 1;
  104. }
  105. /*
  106. * generate hours:minutes:seconds
  107. */
  108. xtime.sec = hms % 60;
  109. d1 = hms / 60;
  110. xtime.min = d1 % 60;
  111. d1 /= 60;
  112. xtime.hour = d1;
  113. /*
  114. * day is the day number.
  115. * generate day of the week.
  116. * The addend is 4 mod 7 (1/1/1970 was Thursday)
  117. */
  118. xtime.wday = (day + 7340036L) % 7;
  119. /*
  120. * year number
  121. */
  122. if(day >= 0)
  123. for(d1 = 1970; day >= dysize(d1); d1++)
  124. day -= dysize(d1);
  125. else
  126. for (d1 = 1970; day < 0; d1--)
  127. day += dysize(d1-1);
  128. xtime.year = d1-1900;
  129. xtime.yday = d0 = day;
  130. /*
  131. * generate month
  132. */
  133. if(dysize(d1) == 366)
  134. dmsize[1] = 29;
  135. for(d1 = 0; d0 >= dmsize[d1]; d1++)
  136. d0 -= dmsize[d1];
  137. dmsize[1] = 28;
  138. xtime.mday = d0 + 1;
  139. xtime.mon = d1;
  140. strcpy(xtime.zone, "GMT");
  141. return &xtime;
  142. }
  143. char*
  144. asctime(Tm *t)
  145. {
  146. char *ncp;
  147. static char cbuf[30];
  148. strcpy(cbuf, "Thu Jan 01 00:00:00 GMT 1970\n");
  149. ncp = &"SunMonTueWedThuFriSat"[t->wday*3];
  150. cbuf[0] = *ncp++;
  151. cbuf[1] = *ncp++;
  152. cbuf[2] = *ncp;
  153. ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[t->mon*3];
  154. cbuf[4] = *ncp++;
  155. cbuf[5] = *ncp++;
  156. cbuf[6] = *ncp;
  157. ct_numb(cbuf+8, t->mday);
  158. ct_numb(cbuf+11, t->hour+100);
  159. ct_numb(cbuf+14, t->min+100);
  160. ct_numb(cbuf+17, t->sec+100);
  161. ncp = t->zone;
  162. cbuf[20] = *ncp++;
  163. cbuf[21] = *ncp++;
  164. cbuf[22] = *ncp;
  165. if(t->year >= 100) {
  166. cbuf[24] = '2';
  167. cbuf[25] = '0';
  168. }
  169. ct_numb(cbuf+26, t->year+100);
  170. return cbuf;
  171. }
  172. static
  173. dysize(int y)
  174. {
  175. if(y%4 == 0 && (y%100 != 0 || y%400 == 0))
  176. return 366;
  177. return 365;
  178. }
  179. static
  180. void
  181. ct_numb(char *cp, int n)
  182. {
  183. cp[0] = ' ';
  184. if(n >= 10)
  185. cp[0] = (n/10)%10 + '0';
  186. cp[1] = n%10 + '0';
  187. }
  188. static
  189. void
  190. readtimezone(void)
  191. {
  192. char buf[TZSIZE*11+30], *p;
  193. int i;
  194. memset(buf, 0, sizeof(buf));
  195. i = open("/env/timezone", 0);
  196. if(i < 0)
  197. goto error;
  198. if(read(i, buf, sizeof(buf)) >= sizeof(buf)){
  199. close(i);
  200. goto error;
  201. }
  202. close(i);
  203. p = buf;
  204. if(rd_name(&p, timezone.stname))
  205. goto error;
  206. if(rd_long(&p, &timezone.stdiff))
  207. goto error;
  208. if(rd_name(&p, timezone.dlname))
  209. goto error;
  210. if(rd_long(&p, &timezone.dldiff))
  211. goto error;
  212. for(i=0; i<TZSIZE; i++) {
  213. if(rd_long(&p, &timezone.dlpairs[i]))
  214. goto error;
  215. if(timezone.dlpairs[i] == 0)
  216. return;
  217. }
  218. error:
  219. timezone.stdiff = 0;
  220. strcpy(timezone.stname, "GMT");
  221. timezone.dlpairs[0] = 0;
  222. }
  223. static
  224. rd_name(char **f, char *p)
  225. {
  226. int c, i;
  227. for(;;) {
  228. c = *(*f)++;
  229. if(c != ' ' && c != '\n')
  230. break;
  231. }
  232. for(i=0; i<3; i++) {
  233. if(c == ' ' || c == '\n')
  234. return 1;
  235. *p++ = c;
  236. c = *(*f)++;
  237. }
  238. if(c != ' ' && c != '\n')
  239. return 1;
  240. *p = 0;
  241. return 0;
  242. }
  243. static
  244. rd_long(char **f, long *p)
  245. {
  246. int c, s;
  247. long l;
  248. s = 0;
  249. for(;;) {
  250. c = *(*f)++;
  251. if(c == '-') {
  252. s++;
  253. continue;
  254. }
  255. if(c != ' ' && c != '\n')
  256. break;
  257. }
  258. if(c == 0) {
  259. *p = 0;
  260. return 0;
  261. }
  262. l = 0;
  263. for(;;) {
  264. if(c == ' ' || c == '\n')
  265. break;
  266. if(c < '0' || c > '9')
  267. return 1;
  268. l = l*10 + c-'0';
  269. c = *(*f)++;
  270. }
  271. if(s)
  272. l = -l;
  273. *p = l;
  274. return 0;
  275. }