Skip to content

Commit 19517c2

Browse files
add strftime impl
1 parent 6b98f49 commit 19517c2

File tree

3 files changed

+200
-1
lines changed

3 files changed

+200
-1
lines changed

makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ $(LIBS): fasmg
4141
$(Q)$(MAKE) -C $(call SRCDIR,$@)
4242

4343
install: all $(addprefix install-,$(SRCS)) $(addprefix install-,$(LIBS))
44-
$(Q)$(MAKE) -f linker.mk -C src
44+
$(Q)$(MAKE) -f linker.mk -C src -B
4545
$(Q)$(call MKDIR,$(INSTALL_DIR))
4646
$(Q)$(call MKDIR,$(INSTALL_BIN))
4747
$(Q)$(call MKDIR,$(INSTALL_H))

src/libc/include/time.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ char *asctime(const struct tm *tmp);
4545

4646
char *ctime(const time_t *timer);
4747

48+
size_t strftime(char* ptr, size_t maxsize, const char* format, const struct tm* timeptr);
49+
4850
__END_DECLS
4951

5052
#endif /* _TIME_H */

src/libc/strftime.c

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
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

Comments
 (0)