diff options
| author | jtc <jtc@NetBSD.org> | 1993-08-19 16:39:47 +0000 |
|---|---|---|
| committer | jtc <jtc@NetBSD.org> | 1993-08-19 16:39:47 +0000 |
| commit | cbc115a0d52630efe03910990e907e2d9fab6b65 (patch) | |
| tree | e713a16611ca10774af5a40ea624191006cfa09f /lib/libc/string/strftime.c | |
| parent | 5c2721a0c39f53810d2e0f9ed857137235e870e5 (diff) | |
Added the additional ``%'' format specifiers and the ``E'' and ``O''
format modifiers that are needed for a 1003.2 compliant date(1). The
modifiers don't actually do anything at present and are not documented.
It's too confusing to the user to describe localization features when
they aren't implemented yet. It is safe to do this, as the modifiers
fall back to the default behavior if the locale doesn't support alternate
eras or numeric formats.
But, in anticipation of _some_ locale support, all month and day names and
abbrevs, certain time formats, am/pm, etc. are now accessed through variables.
Diffstat (limited to 'lib/libc/string/strftime.c')
| -rw-r--r-- | lib/libc/string/strftime.c | 105 |
1 files changed, 75 insertions, 30 deletions
diff --git a/lib/libc/string/strftime.c b/lib/libc/string/strftime.c index b867567fac0..f717ae4b5fb 100644 --- a/lib/libc/string/strftime.c +++ b/lib/libc/string/strftime.c @@ -33,7 +33,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char sccsid[] = "from: @(#)strftime.c 5.11 (Berkeley) 2/24/91";*/ -static char rcsid[] = "$Id: strftime.c,v 1.2 1993/08/01 18:36:23 mycroft Exp $"; +static char rcsid[] = "$Id: strftime.c,v 1.3 1993/08/19 16:39:49 jtc Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -41,25 +41,34 @@ static char rcsid[] = "$Id: strftime.c,v 1.2 1993/08/01 18:36:23 mycroft Exp $"; #include <tzfile.h> #include <string.h> -static char *afmt[] = { +static char *abday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", }; -static char *Afmt[] = { +static char *day[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", }; -static char *bfmt[] = { +static char *abmon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; -static char *Bfmt[] = { +static char *mon[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", }; +static char *ampm[] = { + "AM", "PM", +}; + +static const char *d_t_fmt = "%a %b %e %H:%M:%S %Y"; +static const char *d_fmt = "%m/%d/%y"; +static const char *t_fmt = "%H:%M:%S"; +static const char *t_fmt_ampm = "%I:%M:%S %p"; static size_t gsize; static char *pt; static int _add(), _conv(), _secs(); +static size_t _fmt(); size_t strftime(s, maxsize, format, t) @@ -68,8 +77,6 @@ strftime(s, maxsize, format, t) const char *format; const struct tm *t; { - static size_t _fmt(); - pt = s; if ((gsize = maxsize) < 1) return(0); @@ -80,48 +87,61 @@ strftime(s, maxsize, format, t) return(0); } +#define SUN_WEEK(t) (((t)->tm_yday + 7 - \ + ((t)->tm_wday)) / 7) +#define MON_WEEK(t) (((t)->tm_yday + 7 - \ + ((t)->tm_wday ? (t)->tm_wday - 1 : 6)) / 7) static size_t _fmt(format, t) register char *format; struct tm *t; { for (; *format; ++format) { - if (*format == '%') - switch(*++format) { + if (*format == '%') { + ++format; + if (*format == 'E') { + /* Alternate Era */ + ++format; + } else if (*format == 'O') { + /* Alternate numeric symbols */ + ++format; + } + switch(*format) { case '\0': --format; break; case 'A': if (t->tm_wday < 0 || t->tm_wday > 6) return(0); - if (!_add(Afmt[t->tm_wday])) + if (!_add(day[t->tm_wday])) return(0); continue; case 'a': if (t->tm_wday < 0 || t->tm_wday > 6) return(0); - if (!_add(afmt[t->tm_wday])) + if (!_add(abday[t->tm_wday])) return(0); continue; case 'B': if (t->tm_mon < 0 || t->tm_mon > 11) return(0); - if (!_add(Bfmt[t->tm_mon])) + if (!_add(mon[t->tm_mon])) return(0); continue; case 'b': case 'h': if (t->tm_mon < 0 || t->tm_mon > 11) return(0); - if (!_add(bfmt[t->tm_mon])) + if (!_add(abmon[t->tm_mon])) return(0); continue; case 'C': - if (!_fmt("%a %b %e %H:%M:%S %Y", t)) + if (!_conv((t->tm_year + TM_YEAR_BASE) / 100, + 2, '0')) return(0); continue; case 'c': - if (!_fmt("%m/%d/%y %H:%M:%S", t)) + if (!_fmt(d_t_fmt, t)) return(0); continue; case 'D': @@ -155,7 +175,7 @@ _fmt(format, t) continue; case 'l': if (!_conv(t->tm_hour % 12 ? - t->tm_hour % 12 : 12, 2, ' ')) + t->tm_hour % 12: 12, 2, ' ')) return(0); continue; case 'M': @@ -171,15 +191,14 @@ _fmt(format, t) return(0); continue; case 'p': - if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) + if (!_add(ampm[t->tm_hour >= 12])) return(0); continue; case 'R': if (!_fmt("%H:%M", t)) return(0); - continue; case 'r': - if (!_fmt("%I:%M:%S %p", t)) + if (!_fmt(t_fmt_ampm, t)) return(0); continue; case 'S': @@ -191,7 +210,6 @@ _fmt(format, t) return(0); continue; case 'T': - case 'X': if (!_fmt("%H:%M:%S", t)) return(0); continue; @@ -200,14 +218,36 @@ _fmt(format, t) return(0); continue; case 'U': - if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, - 2, '0')) + if (!_conv(SUN_WEEK(t), 2, '0')) + return(0); + continue; + case 'u': + if (!_conv(t->tm_wday ? t->tm_wday : 7, 2, '0')) return(0); continue; + case 'V': + { + /* ISO 8601 Week Of Year: + If the week (Monday - Sunday) containing + January 1 has four or more days in the new + year, then it is week 1; otherwise it is + week 53 of the previous year and the next + week is week one. */ + + int week = MON_WEEK(t); + + if (((t->tm_yday + 7 - (t->tm_wday + 1)) % 7) >= 4) { + week++; + } else if (week == 0) { + week = 53; + } + + if (!_conv(week, 2, '0')) + return(0); + continue; + } case 'W': - if (!_conv((t->tm_yday + 7 - - (t->tm_wday ? (t->tm_wday - 1) : 6)) - / 7, 2, '0')) + if (!_conv(MON_WEEK(t), 2, '0')) return(0); continue; case 'w': @@ -215,20 +255,24 @@ _fmt(format, t) return(0); continue; case 'x': - if (!_fmt("%m/%d/%y", t)) + if (!_fmt(d_fmt, t)) + return(0); + continue; + case 'X': + if (!_fmt(t_fmt, t)) return(0); continue; case 'y': - if (!_conv((t->tm_year + TM_YEAR_BASE) - % 100, 2, '0')) + if (!_conv((t->tm_year + TM_YEAR_BASE) % 100, + 2, '0')) return(0); continue; case 'Y': - if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0')) + if (!_conv((t->tm_year + TM_YEAR_BASE), 4, '0')) return(0); continue; case 'Z': - if (!t->tm_zone || !_add(t->tm_zone)) + if (t->tm_zone && !_add(t->tm_zone)) return(0); continue; case '%': @@ -239,6 +283,7 @@ _fmt(format, t) */ default: break; + } } if (!gsize--) return(0); |
