|
| 1 | +/* |
| 2 | +Copyright (C) 2010-2020 Ali Gholami Rudi <ali at rudi dot ir> |
| 3 | +
|
| 4 | +Permission to use, copy, modify, and/or distribute this software for any |
| 5 | +purpose with or without fee is hereby granted, provided that the above |
| 6 | +copyright notice and this permission notice appear in all copies. |
| 7 | +
|
| 8 | +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 9 | +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 10 | +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 11 | +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 12 | +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 13 | +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 14 | +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 15 | +*/ |
| 16 | + |
| 17 | +#include <stdio.h> |
| 18 | +#include <stdlib.h> |
| 19 | +#include <time.h> |
| 20 | + |
| 21 | +static const char *wday_ab[] = |
| 22 | +{ |
| 23 | + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" |
| 24 | +}; |
| 25 | + |
| 26 | +static const char *wday[] = |
| 27 | +{ |
| 28 | + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" |
| 29 | +}; |
| 30 | + |
| 31 | +static const char *mon_ab[] = |
| 32 | +{ |
| 33 | + "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
| 34 | + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
| 35 | +}; |
| 36 | + |
| 37 | +static const char *mon[] = |
| 38 | +{ |
| 39 | + "January", "February", "March", "April", "May", "June", |
| 40 | + "July", "August", "September", "October", "November", "December" |
| 41 | +}; |
| 42 | + |
| 43 | +static char *putstr(char *d, const char *s) |
| 44 | +{ |
| 45 | + while (*s) |
| 46 | + { |
| 47 | + *d++ = *s++; |
| 48 | + } |
| 49 | + return d; |
| 50 | +} |
| 51 | + |
| 52 | +static char *puti(char *s, unsigned long n, int wid, int zpad) |
| 53 | +{ |
| 54 | + int i; |
| 55 | + for (i = wid - 1; i >= 0; i--) |
| 56 | + { |
| 57 | + if (!n) |
| 58 | + { |
| 59 | + if (!zpad && i < wid - 1) |
| 60 | + { |
| 61 | + s[i] = ' '; |
| 62 | + } |
| 63 | + else |
| 64 | + { |
| 65 | + s[i] = '0'; |
| 66 | + } |
| 67 | + } |
| 68 | + else |
| 69 | + { |
| 70 | + s[i] = '0' + n % 10; |
| 71 | + n /= 10; |
| 72 | + } |
| 73 | + } |
| 74 | + return s + wid; |
| 75 | +} |
| 76 | + |
| 77 | +size_t strftime(char *s, size_t n, const char *f, const struct tm *tm) |
| 78 | +{ |
| 79 | + const char *beg = s; |
| 80 | + const char *e = s + n; |
| 81 | + |
| 82 | + while (s + 1 < e && *f) |
| 83 | + { |
| 84 | + int c = *f++; |
| 85 | + int val; |
| 86 | + |
| 87 | + if (c != '%') |
| 88 | + { |
| 89 | + *s++ = c; |
| 90 | + continue; |
| 91 | + } |
| 92 | + |
| 93 | + c = *f++; |
| 94 | + switch (c) |
| 95 | + { |
| 96 | + case '%': |
| 97 | + *s++ = '%'; |
| 98 | + break; |
| 99 | + case 'a': |
| 100 | + s = putstr(s, wday_ab[tm->tm_wday]); |
| 101 | + break; |
| 102 | + case 'A': |
| 103 | + s = putstr(s, wday[tm->tm_wday]); |
| 104 | + break; |
| 105 | + case 'b': |
| 106 | + case 'h': |
| 107 | + s = putstr(s, mon_ab[tm->tm_mon]); |
| 108 | + break; |
| 109 | + case 'B': |
| 110 | + s = putstr(s, mon[tm->tm_mon]); |
| 111 | + break; |
| 112 | + case 'c': |
| 113 | + s += strftime(s, e - s, "%b %a %d %k:%M:%S %Z %Y", tm); |
| 114 | + break; |
| 115 | + case 'C': |
| 116 | + s = puti(s, (1900 + tm->tm_year) / 100, 2, 1); |
| 117 | + break; |
| 118 | + case 'd': |
| 119 | + s = puti(s, tm->tm_mday, 2, 1); |
| 120 | + break; |
| 121 | + case 'D': |
| 122 | + s += strftime(s, e - s, "%m/%d/%y", tm); |
| 123 | + break; |
| 124 | + case 'e': |
| 125 | + s = puti(s, tm->tm_mday, 2, 0); |
| 126 | + break; |
| 127 | + case 'F': |
| 128 | + s += strftime(s, e - s, "%Y/%m/%d", tm); |
| 129 | + break; |
| 130 | + case 'H': |
| 131 | + s = puti(s, tm->tm_hour, 2, 1); |
| 132 | + break; |
| 133 | + case 'I': |
| 134 | + val = tm->tm_hour > 12 ? tm->tm_hour - 12 : tm->tm_hour; |
| 135 | + s = puti(s, val ? val : 12, 2, 1); |
| 136 | + break; |
| 137 | + case 'j': |
| 138 | + s = puti(s, tm->tm_yday + 1, 3, 1); |
| 139 | + break; |
| 140 | + case 'k': |
| 141 | + s = puti(s, tm->tm_hour, 2, 1); |
| 142 | + break; |
| 143 | + case 'm': |
| 144 | + s = puti(s, tm->tm_mon + 1, 2, 1); |
| 145 | + break; |
| 146 | + case 'M': |
| 147 | + s = puti(s, tm->tm_min, 2, 1); |
| 148 | + break; |
| 149 | + case 'n': |
| 150 | + *s++ = '\n'; |
| 151 | + break; |
| 152 | + case 'p': |
| 153 | + s = putstr(s, tm->tm_hour >= 12 ? "PM" : "AM"); |
| 154 | + break; |
| 155 | + case 'P': |
| 156 | + s = putstr(s, tm->tm_hour >= 12 ? "pm" : "am"); |
| 157 | + break; |
| 158 | + case 'r': |
| 159 | + s += strftime(s, e - s, "%I:%M:%S %p", tm); |
| 160 | + break; |
| 161 | + case 'R': |
| 162 | + s += strftime(s, e - s, "%H:%M", tm); |
| 163 | + break; |
| 164 | + case 'S': |
| 165 | + s = puti(s, tm->tm_sec, 2, 1); |
| 166 | + break; |
| 167 | + case 't': |
| 168 | + *s++ = '\t'; |
| 169 | + break; |
| 170 | + case 'T': |
| 171 | + s += strftime(s, e - s, "%H:%M:%S", tm); |
| 172 | + break; |
| 173 | + case 'u': |
| 174 | + s = puti(s, tm->tm_wday ? tm->tm_wday : 7, 1, 0); |
| 175 | + break; |
| 176 | + case 'w': |
| 177 | + s = puti(s, tm->tm_wday, 1, 0); |
| 178 | + break; |
| 179 | + case 'x': |
| 180 | + s += strftime(s, e - s, "%b %a %d", tm); |
| 181 | + break; |
| 182 | + case 'X': |
| 183 | + s += strftime(s, e - s, "%k:%M:%S", tm); |
| 184 | + break; |
| 185 | + case 'y': |
| 186 | + s = puti(s, tm->tm_year % 100, 2, 1); |
| 187 | + break; |
| 188 | + case 'Y': |
| 189 | + s = puti(s, 1900 + tm->tm_year, 4, 1); |
| 190 | + break; |
| 191 | + default: |
| 192 | + break; |
| 193 | + } |
| 194 | + } |
| 195 | + *s = '\0'; |
| 196 | + return s - beg; |
| 197 | +} |
0 commit comments