summaryrefslogtreecommitdiff
path: root/lib/libc/string/strftime.c
diff options
context:
space:
mode:
authorjtc <jtc@NetBSD.org>1993-08-19 16:39:47 +0000
committerjtc <jtc@NetBSD.org>1993-08-19 16:39:47 +0000
commitcbc115a0d52630efe03910990e907e2d9fab6b65 (patch)
treee713a16611ca10774af5a40ea624191006cfa09f /lib/libc/string/strftime.c
parent5c2721a0c39f53810d2e0f9ed857137235e870e5 (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.c105
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);