strftime.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * strftime - convert a structure to a string, controlled by an argument
  3. */
  4. /* $Id$ */
  5. #include <time.h>
  6. #include "loc_time.h"
  7. /* The width can be -1 in both s_prnt() as in u_prnt(). This
  8. * indicates that as many characters as needed should be printed.
  9. */
  10. static char *
  11. s_prnt(char *s, size_t maxsize, const char *str, int width)
  12. {
  13. while (width > 0 || (width < 0 && *str)) {
  14. if (!maxsize) break;
  15. *s++ = *str++;
  16. maxsize--;
  17. width--;
  18. }
  19. return s;
  20. }
  21. static char *
  22. u_prnt(char *s, size_t maxsize, unsigned val, int width)
  23. {
  24. int c;
  25. c = val % 10;
  26. val = val / 10;
  27. if (--width > 0 || (width < 0 && val != 0))
  28. s = u_prnt(s, (maxsize ? maxsize - 1 : 0), val, width);
  29. if (maxsize) *s++ = c + '0';
  30. return s;
  31. }
  32. size_t
  33. strftime(char *s, size_t maxsize,
  34. const char *format, const struct tm *timeptr)
  35. {
  36. size_t n;
  37. char *firsts, *olds;
  38. if (!format) return 0;
  39. _tzset(); /* for %Z conversion */
  40. firsts = s;
  41. while (maxsize && *format) {
  42. while (maxsize && *format && *format != '%') {
  43. *s++ = *format++;
  44. maxsize--;
  45. }
  46. if (!maxsize || !*format) break;
  47. format++;
  48. olds = s;
  49. switch (*format++) {
  50. case 'a':
  51. s = s_prnt(s, maxsize,
  52. _days[timeptr->tm_wday], ABB_LEN);
  53. maxsize -= s - olds;
  54. break;
  55. case 'A':
  56. s = s_prnt(s, maxsize, _days[timeptr->tm_wday], -1);
  57. maxsize -= s - olds;
  58. break;
  59. case 'b':
  60. s = s_prnt(s, maxsize,
  61. _months[timeptr->tm_mon], ABB_LEN);
  62. maxsize -= s - olds;
  63. break;
  64. case 'B':
  65. s = s_prnt(s, maxsize, _months[timeptr->tm_mon], -1);
  66. maxsize -= s - olds;
  67. break;
  68. case 'c':
  69. n = strftime(s, maxsize,
  70. "%a %b %d %H:%M:%S %Y", timeptr);
  71. if (n) maxsize -= n;
  72. else maxsize = 0;
  73. s += n;
  74. break;
  75. case 'd':
  76. s = u_prnt(s, maxsize, timeptr->tm_mday, 2);
  77. maxsize -= s - olds;
  78. break;
  79. case 'H':
  80. s = u_prnt(s, maxsize, timeptr->tm_hour, 2);
  81. maxsize -= s - olds;
  82. break;
  83. case 'I':
  84. s = u_prnt(s, maxsize,
  85. (timeptr->tm_hour + 11) % 12 + 1, 2);
  86. maxsize -= s - olds;
  87. break;
  88. case 'j':
  89. s = u_prnt(s, maxsize, timeptr->tm_yday + 1, 3);
  90. maxsize -= s - olds;
  91. break;
  92. case 'm':
  93. s = u_prnt(s, maxsize, timeptr->tm_mon + 1, 2);
  94. maxsize -= s - olds;
  95. break;
  96. case 'M':
  97. s = u_prnt(s, maxsize, timeptr->tm_min, 2);
  98. maxsize -= s - olds;
  99. break;
  100. case 'p':
  101. s = s_prnt(s, maxsize,
  102. (timeptr->tm_hour < 12) ? "AM" : "PM", 2);
  103. maxsize -= s - olds;
  104. break;
  105. case 'S':
  106. s = u_prnt(s, maxsize, timeptr->tm_sec, 2);
  107. maxsize -= s - olds;
  108. break;
  109. case 'U':
  110. s = u_prnt(s, maxsize, /* ??? */
  111. (timeptr->tm_yday + 7 - timeptr->tm_wday) / 7, 2);
  112. maxsize -= s - olds;
  113. break;
  114. case 'w':
  115. s = u_prnt(s, maxsize, timeptr->tm_wday, 1);
  116. maxsize -= s - olds;
  117. break;
  118. case 'W':
  119. s = u_prnt(s, maxsize, /* ??? */
  120. (timeptr->tm_yday+7-(timeptr->tm_wday+6)%7)/7,2);
  121. maxsize -= s - olds;
  122. break;
  123. case 'x':
  124. n = strftime(s, maxsize, "%a %b %d %Y", timeptr);
  125. if (n) maxsize -= n;
  126. else maxsize = 0;
  127. s += n;
  128. break;
  129. case 'X':
  130. n = strftime(s, maxsize, "%H:%M:%S", timeptr);
  131. if (n) maxsize -= n;
  132. else maxsize = 0;
  133. s += n;
  134. break;
  135. case 'y':
  136. s = u_prnt(s, maxsize, timeptr->tm_year % 100, 2);
  137. maxsize -= s - olds;
  138. break;
  139. case 'Y':
  140. s = u_prnt(s, maxsize, timeptr->tm_year + YEAR0, -1);
  141. maxsize -= s - olds;
  142. break;
  143. case 'Z':
  144. s = s_prnt(s, maxsize,
  145. _tzname[(timeptr->tm_isdst > 0)], -1);
  146. maxsize -= s - olds;
  147. break;
  148. case '%':
  149. *s++ = '%';
  150. maxsize--;
  151. break;
  152. default:
  153. /* A conversion error. Leave the loop. */
  154. while (*format) format++;
  155. break;
  156. }
  157. }
  158. if (maxsize) {
  159. *s = '\0';
  160. return s - firsts;
  161. }
  162. return 0; /* The buffer is full */
  163. }