9front - general discussion about 9front
 help / color / mirror / Atom feed
* Upas: Complete date library conversion.
@ 2020-09-19 18:53 ori
  2020-09-19 18:55 ` [9front] " ori
  0 siblings, 1 reply; 6+ messages in thread
From: ori @ 2020-09-19 18:53 UTC (permalink / raw)
  To: 9front

This patch completes the conversion to our new date and
time APIs. Needs careful review and testing. The imap
part seems to be working. I'm waiting on vultr to unblock
port 25 so I can test out the SMTP part of the patch.

diff -r 730a2ee35853 sys/src/cmd/upas/Mail/mail.c
--- a/sys/src/cmd/upas/Mail/mail.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/Mail/mail.c	Sat Sep 19 11:52:57 2020 -0700
@@ -82,6 +82,7 @@
 
 	doquote = needsrcquote;
 	quotefmtinstall();
+	tmfmtinstall();
 
 	/* open these early so we won't miss notification of new mail messages while we read mbox */
 	plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
diff -r 730a2ee35853 sys/src/cmd/upas/Mail/mesg.c
--- a/sys/src/cmd/upas/Mail/mesg.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/Mail/mesg.c	Sat Sep 19 11:52:57 2020 -0700
@@ -224,14 +224,13 @@
 int
 thisyear(char *year)
 {
-	static char now[10];
-	char *s;
+	Tzone *tz;
+	Tm tm;
 
-	if(now[0] == '\0'){
-		s = ctime(time(nil));
-		strcpy(now, s+24);
-	}
-	return strncmp(year, now, 4) == 0;
+	/* ignore errors: screwed means utc */
+	tz = tzload("local");
+	tmnow(&tm, tz);
+	return atoi(year) == (tm.year + 1900);
 }
 
 char*
diff -r 730a2ee35853 sys/src/cmd/upas/Mail/reply.c
--- a/sys/src/cmd/upas/Mail/reply.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/Mail/reply.c	Sat Sep 19 11:52:57 2020 -0700
@@ -388,7 +388,9 @@
 	Channel *sync;
 	Message *r;
 	int first, nfld, delit, ofd;
-	char *copy, *fld[100], *now;
+	char *copy, *fld[100];
+	Tzone *tz;
+	Tm now;
 
 	body = winreadbody(m->w, &n);
 	/* assemble to: list from first line, to: line, and cc: line */
@@ -467,11 +469,12 @@
 
 	ofd = open(outgoing, OWRITE|OCEXEC);	/* no error check necessary */
 	if(ofd >= 0){
-		/* From dhog Fri Aug 24 22:13:00 EDT 2001 */
-		now = ctime(time(0));
-		fprint(ofd, "From %s %s", user, now);
+		/* From dhog Fri Aug 24 22:13:00 +0500 2001 */
+		tz = tzload("local");
+		tmnow(&now, tz);
+		fprint(ofd, "From %s %τ", user, tmfmt(&now, "WW MMM _D hh:mm:ss Z YYYY"));
 		fprint(ofd, "From: %s\n", user);
-		fprint(ofd, "Date: %s", now);
+		fprint(ofd, "Date: %τ", tmfmt(&now, "WW MMM _D hh:mm:ss Z YYYY"));
 		for(i=0; i<natt; i++)
 			if(included[i])
 				fprint(ofd, "Include: %s\n", attlist[i]);
diff -r 730a2ee35853 sys/src/cmd/upas/common/common.h
--- a/sys/src/cmd/upas/common/common.h	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/common/common.h	Sat Sep 19 11:52:57 2020 -0700
@@ -20,6 +20,7 @@
 	Fstored		= 1<<6, /* S */
 	Nflags		= 7,
 };
+#define Timefmt "WW MMM _D hh:mm:ss ?Z YYYY"
 
 /*
  * flag.c
diff -r 730a2ee35853 sys/src/cmd/upas/common/folder.c
--- a/sys/src/cmd/upas/common/folder.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/common/folder.c	Sat Sep 19 11:52:57 2020 -0700
@@ -1,7 +1,5 @@
 #include "common.h"
 
-#define Ctimefmt "WW MMM _D hh:mm:ss ?Z YYYY"
-
 enum{
 	Mbox	= 1,
 	Mdir,
@@ -186,22 +184,24 @@
 int
 appendfolder(Biobuf *b, char *addr, int fd)
 {
-	char *s, *t;
-	int r;
+	char *s;
+	int r, n;
 	Biobuf bin;
 	Folder *f;
+	Tzone *tz;
 	Tm tm;
 
 	f = getfolder(b);
 	Bseek(f->out, 0, 2);
 	Binit(&bin, fd, OREAD);
 	s = Brdstr(&bin, '\n', 0);
-	if(s == nil || strncmp(s, "From ", 5) != 0)
-		Bprint(f->out, "From %s %.28s\n", addr, ctime(f->t));
-	else if(strncmp(s, "From ", 5) == 0 
-		&& (t = strchr(s + 5, ' ')) != nil
-		&& tmparse(&tm, Ctimefmt, t + 1, nil, nil) != nil)
-		f->t = tm2sec(&tm);
+	n = strlen(s);
+	if(!s || strncmp(s, "From ", 5) != 0){
+		tz = tzload("local");
+		tmtime(&tm, f->t, tz);
+		Bprint(f->out, "From %s %τ\n", addr, tmfmt(&tm, Timefmt));
+	}else if(n > 5 && tmparse(&tm, Timefmt, s + 5, nil, nil) != nil)
+		f->t = tmnorm(&tm);
 	if(s)
 		Bwrite(f->out, s, strlen(s));
 	free(s);
diff -r 730a2ee35853 sys/src/cmd/upas/common/libsys.c
--- a/sys/src/cmd/upas/common/libsys.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/common/libsys.c	Sat Sep 19 11:52:57 2020 -0700
@@ -5,14 +5,15 @@
 /*
  *  return the date
  */
-char*
-thedate(void)
+Tmfmt
+thedate(Tm *tm)
 {
-	static char now[64];
+	Tzone *tz;
 
-	strcpy(now, ctime(time(0)));
-	now[28] = 0;
-	return now;
+	/* if the local time is screwed, just do gmt */
+	tz = tzload("local");
+	tmnow(tm, tz);
+	return tmfmt(tm, Timefmt);
 }
 
 /*
diff -r 730a2ee35853 sys/src/cmd/upas/common/sys.h
--- a/sys/src/cmd/upas/common/sys.h	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/common/sys.h	Sat Sep 19 11:52:57 2020 -0700
@@ -35,7 +35,7 @@
 char	*domainname_read(void);
 char	**sysnames_read(void);
 char	*getlog(void);
-char	*thedate(void);
+Tmfmt	thedate(Tm*);
 Biobuf	*sysopen(char*, char*, ulong);
 int	sysopentty(void);
 int	sysclose(Biobuf*);
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/deliver.c
--- a/sys/src/cmd/upas/filterkit/deliver.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/deliver.c	Sat Sep 19 11:52:57 2020 -0700
@@ -14,13 +14,15 @@
 void
 main(int argc, char **argv)
 {
-	char *to, *s;
+	char *to;
+	Tmfmt tf;
+	Tm tm;
 	int r;
-	long l;
 	Addr *a;
 
 	ARGBEGIN{
 	}ARGEND;
+	tmfmtinstall();
 	if(argc != 3)
 		usage();
 	if(to = strrchr(argv[0], '!'))
@@ -30,9 +32,9 @@
 	a = readaddrs(argv[1], nil);
 	if(a == nil)
 		sysfatal("missing from address");
-	s = ctime(l = time(0));
+	tf = thedate(&tm);
 	werrstr("");
-	r = fappendfolder(a->val, l, argv[2], 0);
-	syslog(0, "mail", "delivered %s From %s %.28s (%s) %d %r", to, a->val, s, argv[0], r);
+	r = fappendfolder(a->val, tmnorm(&tm), argv[2], 0);
+	syslog(0, "mail", "delivered %s From %s %τ (%s) %d %r", to, a->val, tf, argv[0], r);
 	exits("");
 }
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/list.c
--- a/sys/src/cmd/upas/filterkit/list.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/list.c	Sat Sep 19 11:52:57 2020 -0700
@@ -306,6 +306,7 @@
 	} ARGEND;
 
 	quotefmtinstall();
+	tmfmtinstall();
 
 	if(argc < 3)
 		usage();
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/mbappend.c
--- a/sys/src/cmd/upas/filterkit/mbappend.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/mbappend.c	Sat Sep 19 11:52:57 2020 -0700
@@ -7,15 +7,15 @@
 void
 append(int fd, char *mb, char *from, long t)
 {
-	char *folder, *s;
+	char *folder;
+	Tm tm;
 	int r;
 
-	s = ctime(t);
 	folder = foldername(from, getuser(), mb);
 	r = fappendfolder(0, t, folder, fd);
 	if(r == 0)
 		werrstr("");
-	syslog(0, "mail", "mbappend %s %.28s (%s) %r", mb, s, folder);
+	syslog(0, "mail", "mbappend %s %τ (%s) %r", mb, thedate(&tm), folder);
 	if(r)
 		exits("fail");
 }
@@ -36,6 +36,7 @@
 
 	from = nil;
 	t = time(0);
+	tmfmtinstall();
 	ARGBEGIN{
 	case 't':
 		t = strtoul(EARGF(usage()), 0, 0);
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/mbcreate.c
--- a/sys/src/cmd/upas/filterkit/mbcreate.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/mbcreate.c	Sat Sep 19 11:52:57 2020 -0700
@@ -24,6 +24,7 @@
 	}ARGEND
 
 	r = 0;
+	tmfmtinstall();
 	for(; *argv; argv++)
 		r |= f(getuser(), *argv);
 	if(r)
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/mbremove.c
--- a/sys/src/cmd/upas/filterkit/mbremove.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/mbremove.c	Sat Sep 19 11:52:57 2020 -0700
@@ -235,6 +235,7 @@
 	}ARGEND
 
 	r = 0;
+	tmfmtinstall();
 	for(; *argv; argv++)
 		r |= f(getuser(), *argv);
 	if(r)
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/token.c
--- a/sys/src/cmd/upas/filterkit/token.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/token.c	Sat Sep 19 11:52:57 2020 -0700
@@ -62,6 +62,7 @@
 	ARGBEGIN {
 	} ARGEND;
 
+	tmfmtinstall();
 	switch(argc){
 	case 2:
 		exits(check_token(argv[0], argv[1]));
diff -r 730a2ee35853 sys/src/cmd/upas/fs/extra/strtotmtst.c
--- a/sys/src/cmd/upas/fs/extra/strtotmtst.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/fs/extra/strtotmtst.c	Sat Sep 19 11:52:57 2020 -0700
@@ -8,9 +8,10 @@
 	ARGBEGIN{
 	}ARGEND
 
+	tmfmtinstall();
 	for(; *argv; argv++)
 		if(strtotm(*argv, &tm) >= 0)
-			print("%s", asctime(&tm));
+			print("%τ\n", tmfmt(&tm, nil));
 		else
 			print("bad\n");
 	exits("");
diff -r 730a2ee35853 sys/src/cmd/upas/fs/fs.c
--- a/sys/src/cmd/upas/fs/fs.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/fs/fs.c	Sat Sep 19 11:52:57 2020 -0700
@@ -174,16 +174,15 @@
 static int
 Δfmt(Fmt *f)
 {
-	char buf[32];
 	uvlong v;
+	Tm tm;
 
 	v = va_arg(f->args, uvlong);
 	if(f->flags & FmtSharp)
 		if((v>>8) == 0)
 			return fmtstrcpy(f, "");
-	strcpy(buf, ctime(v>>8));
-	buf[28] = 0;
-	return fmtstrcpy(f, buf);
+	tmtime(&tm, v>>8, tzload("local"));
+	return fmtprint(f, "%τ", tmfmt(&tm, "WW MMM _D hh:mm:ss ZZZ YYYY"));
 }
 
 static int
@@ -320,6 +319,7 @@
 	fmtinstall(L'Δ', Δfmt);
 	fmtinstall('F', fcallfmt);
 	fmtinstall('H', encodefmt);		/* forces tls stuff */
+	tmfmtinstall();
 	quotefmtinstall();
 	if(pipe(p) < 0)
 		error("pipe failed");
diff -r 730a2ee35853 sys/src/cmd/upas/fs/mbox.c
--- a/sys/src/cmd/upas/fs/mbox.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/fs/mbox.c	Sat Sep 19 11:52:57 2020 -0700
@@ -366,11 +366,11 @@
 	if(m->fileid > 1000000ull<<8)
 		return;
 	if(m->unixdate && strtotm(m->unixdate, &tm) >= 0)
-		v = tm2sec(&tm);
+		v = tmnorm(&tm);
 	else if(m->date822 && strtotm(m->date822, &tm) >= 0)
-		v = tm2sec(&tm);
+		v = tmnorm(&tm);
 	else if(rxtotm(m, &tm) >= 0)
-		v = tm2sec(&tm);
+		v = tmnorm(&tm);
 	else{
 		logmsg(gettopmsg(mb, m), "%s:%s: datasec %s %s\n", mb->path,
 			m->whole? m->whole->name: "?",
diff -r 730a2ee35853 sys/src/cmd/upas/fs/plan9.c
--- a/sys/src/cmd/upas/fs/plan9.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/fs/plan9.c	Sat Sep 19 11:52:57 2020 -0700
@@ -34,7 +34,7 @@
 		return -1;
 	if(memtotm(p, n - (p - s), &tm) < 0)
 		return -1;
-	if(tm2sec(&tm) < 1000000)
+	if(tmnorm(&tm) < 1000000)
 		return -1;
 	return 0;
 }
diff -r 730a2ee35853 sys/src/cmd/upas/imap4d/date.c
--- a/sys/src/cmd/upas/imap4d/date.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/imap4d/date.c	Sat Sep 19 11:52:57 2020 -0700
@@ -1,142 +1,10 @@
 #include "imap4d.h"
 
-static char *wdayname[] = {
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-static char *monname[] = {
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-/*
- * zone	: [A-Za-z][A-Za-z][A-Za-z]	some time zone names
- *	| [A-IK-Z]			military time; rfc1123 says the rfc822 spec is wrong.
- *	| "UT"				universal time
- *	| [+-][0-9][0-9][0-9][0-9]
- * zones is the rfc-822 list of time zone names
- */
-static Namedint zones[] =
-{
-	{"A",	-1 * 3600},
-	{"B",	-2 * 3600},
-	{"C",	-3 * 3600},
-	{"CDT", -5 * 3600},
-	{"CST", -6 * 3600},
-	{"D",	-4 * 3600},
-	{"E",	-5 * 3600},
-	{"EDT", -4 * 3600},
-	{"EST", -5 * 3600},
-	{"F",	-6 * 3600},
-	{"G",	-7 * 3600},
-	{"GMT", 0},
-	{"H",	-8 * 3600},
-	{"I",	-9 * 3600},
-	{"K",	-10 * 3600},
-	{"L",	-11 * 3600},
-	{"M",	-12 * 3600},
-	{"MDT", -6 * 3600},
-	{"MST", -7 * 3600},
-	{"N",	+1 * 3600},
-	{"O",	+2 * 3600},
-	{"P",	+3 * 3600},
-	{"PDT", -7 * 3600},
-	{"PST", -8 * 3600},
-	{"Q",	+4 * 3600},
-	{"R",	+5 * 3600},
-	{"S",	+6 * 3600},
-	{"T",	+7 * 3600},
-	{"U",	+8 * 3600},
-	{"UT",	0},
-	{"V",	+9 * 3600},
-	{"W",	+10 * 3600},
-	{"X",	+11 * 3600},
-	{"Y",	+12 * 3600},
-	{"Z",	0},
-};
-
-static void
-zone2tm(Tm *tm, char *s)
-{
-	int i;
-	Tm aux, *atm;
-
-	if(*s == '+' || *s == '-'){
-		i = strtol(s, &s, 10);
-		tm->tzoff = (i/100)*3600 + i%100;
-		strncpy(tm->zone, "", 4);
-		return;
-	}
-
-	/*
-	 * look it up in the standard rfc822 table
-	 */
-	strncpy(tm->zone, s, 3);
-	tm->zone[3] = 0;
-	tm->tzoff = 0;
-	for(i = 0; i < nelem(zones); i++){
-		if(cistrcmp(zones[i].name, s) == 0){
-			tm->tzoff = zones[i].v;
-			return;
-		}
-	}
-
-	/*
-	 * one last try: look it up in the current local timezone
-	 * probe a couple of times to get daylight/standard time change.
-	 */
-	aux = *tm;
-	memset(aux.zone, 0, 4);
-	aux.hour--;
-	for(i = 0; i < 2; i++){
-		atm = localtime(tm2sec(&aux));
-		if(cistrcmp(tm->zone, atm->zone) == 0){
-			tm->tzoff = atm->tzoff;
-			return;
-		}
-		aux.hour++;
-	}
-
-	strncpy(tm->zone, "GMT", 4);
-	tm->tzoff = 0;
-}
-
-/*
- * hh[:mm[:ss]]
- */
-static void
-time2tm(Tm *tm, char *s)
-{
-	tm->hour = strtoul(s, &s, 10);
-	if(*s++ != ':')
-		return;
-	tm->min = strtoul(s, &s, 10);
-	if(*s++ != ':')
-		return;
-	tm->sec = strtoul(s, &s, 10);
-}
-
-static int
-dateindex(char *d, char **tab, int n)
-{
-	int i;
-
-	for(i = 0; i < n; i++)
-		if(cistrcmp(d, tab[i]) == 0)
-			return i;
-	return -1;
-}
-
 int
 imap4date(Tm *tm, char *date)
 {
-	char *flds[4];
-
-	if(getfields(date, flds, 3, 0, "-") != 3)
+	if(tmparse(tm, "DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) == nil)
 		return 0;
-
-	tm->mday = strtol(flds[0], nil, 10);
-	tm->mon = dateindex(flds[1], monname, 12);
-	tm->year = strtol(flds[2], nil, 10) - 1900;
 	return 1;
 }
 
@@ -146,29 +14,17 @@
 ulong
 imap4datetime(char *date)
 {
-	char *flds[4], *sflds[4];
-	ulong t;
 	Tm tm;
+	vlong s;
 
-	if(getfields(date, flds, 4, 0, " ") != 3)
-		return ~0;
-
-	if(!imap4date(&tm, flds[0]))
-		return ~0;
-
-	if(getfields(flds[1], sflds, 3, 0, ":") != 3)
-		return ~0;
-
-	tm.hour = strtol(sflds[0], nil, 10);
-	tm.min = strtol(sflds[1], nil, 10);
-	tm.sec = strtol(sflds[2], nil, 10);
-
-	strcpy(tm.zone, "GMT");
-	tm.yday = 0;
-	t = tm2sec(&tm);
-	zone2tm(&tm, flds[2]);
-	t -= tm.tzoff;
-	return t;
+	s = -1;
+	if(tmparse(&tm, "?DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) != nil)
+		s = tmnorm(&tm);
+	else if(tmparse(&tm, "?W, ?DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) != nil)
+		s = tmnorm(&tm);
+	if(s > 0 && s < (1ULL<<31))
+		return s;
+	return ~0;
 }
 
 /*
@@ -181,85 +37,18 @@
 Tm*
 date2tm(Tm *tm, char *date)
 {
-	char *flds[7], *s, dstr[64];
-	int n;
-	Tm gmt, *atm;
+	char **f, *fmts[] = {
+		"?W, ?DD ?MMM YYYY hh:mm:ss ?Z",
+		"?W ?M ?DD hh:mm:ss ?Z YYYY",
+		"?W, DD-?MM-YY hh:mm:ss ?Z",
+		"?DD ?MMM YYYY hh:mm:ss ?Z",
+		"?M ?DD hh:mm:ss ?Z YYYY",
+		"DD-?MM-YYYY hh:mm:ss ?Z",
+		nil,
+	};
 
-	/*
-	 * default date is Thu Jan  1 00:00:00 GMT 1970
-	 */
-	tm->wday = 4;
-	tm->mday = 1;
-	tm->mon = 1;
-	tm->hour = 0;
-	tm->min = 0;
-	tm->sec = 0;
-	tm->year = 70;
-	strcpy(tm->zone, "GMT");
-	tm->tzoff = 0;
-
-	strncpy(dstr, date, sizeof dstr);
-	dstr[sizeof dstr - 1] = 0;
-	n = tokenize(dstr, flds, 7);
-	if(n != 6 && n != 5)
-		return nil;
-
-	if(n == 5){
-		for(n = 5; n >= 1; n--)
-			flds[n] = flds[n - 1];
-		n = 5;
-	}else{
-		/*
-		 * Wday[,]
-		 */
-		s = strchr(flds[0], ',');
-		if(s != nil)
-			*s = 0;
-		tm->wday = dateindex(flds[0], wdayname, 7);
-		if(tm->wday < 0)
-			return nil;
-	}
-
-	/*
-	 * check for the two major formats:
-	 * Month first or day first
-	 */
-	tm->mon = dateindex(flds[1], monname, 12);
-	if(tm->mon >= 0){
-		tm->mday = strtoul(flds[2], nil, 10);
-		time2tm(tm, flds[3]);
-		zone2tm(tm, flds[4]);
-		tm->year = strtoul(flds[5], nil, 10);
-		if(strlen(flds[5]) > 2)
-			tm->year -= 1900;
-	}else{
-		tm->mday = strtoul(flds[1], nil, 10);
-		tm->mon = dateindex(flds[2], monname, 12);
-		if(tm->mon < 0)
-			return nil;
-		tm->year = strtoul(flds[3], nil, 10);
-		if(strlen(flds[3]) > 2)
-			tm->year -= 1900;
-		time2tm(tm, flds[4]);
-		zone2tm(tm, flds[5]);
-	}
-
-	if(n == 5){
-		gmt = *tm;
-		strncpy(gmt.zone, "", 4);
-		gmt.tzoff = 0;
-		atm = gmtime(tm2sec(&gmt));
-		tm->wday = atm->wday;
-	}else{
-		/*
-		 * Wday[,]
-		 */
-		s = strchr(flds[0], ',');
-		if(s != nil)
-			*s = 0;
-		tm->wday = dateindex(flds[0], wdayname, 7);
-		if(tm->wday < 0)
-			return nil;
-	}
-	return tm;
+	for(f = fmts; *f; f++)
+		if(tmparse(tm, *f, date, nil, nil) != nil)
+			return tm;
+	return nil;
 }
diff -r 730a2ee35853 sys/src/cmd/upas/imap4d/imap4d.c
--- a/sys/src/cmd/upas/imap4d/imap4d.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/imap4d/imap4d.c	Sat Sep 19 11:52:57 2020 -0700
@@ -215,6 +215,7 @@
 	Binit(&bin, dup(0, -1), OREAD);
 	close(0);
 	Binit(&bout, 1, OWRITE);
+	tmfmtinstall();
 	quotefmtinstall();
 	fmtinstall('F', Ffmt);
 	fmtinstall('D', Dfmt);	/* rfc822; # imap date %Z */
@@ -501,6 +502,8 @@
 	char *mbox, head[128];
 	uint t, n, now;
 	int flags, ok;
+	Tzone *tz;
+	Tm tm;
 	Uidplus u;
 
 	mustbe(' ');
@@ -536,7 +539,9 @@
 		return;
 	}
 
-	snprint(head, sizeof head, "From %s %s", username, ctime(t));
+	tz = tzload("local");
+	tmtime(&tm, t, tz);
+	snprint(head, sizeof head, "From %s %τ", username, tmfmt(&tm, "WW MMM _D hh:mm:ss Z YYYY"));
 	ok = appendsave(mbox, flags, head, &bin, n, &u);
 	crnl();
 	check();
diff -r 730a2ee35853 sys/src/cmd/upas/imap4d/nlisttst.c
--- a/sys/src/cmd/upas/imap4d/nlisttst.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/imap4d/nlisttst.c	Sat Sep 19 11:52:57 2020 -0700
@@ -1,7 +1,5 @@
 #include "nlist.c"
 
-char	username[] = "quanstro";
-char	mboxdir[] = "/mail/box/quanstro/";
 Biobuf	bout;
 Bin	*parsebin;
 
diff -r 730a2ee35853 sys/src/cmd/upas/imap4d/print.c
--- a/sys/src/cmd/upas/imap4d/print.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/imap4d/print.c	Sat Sep 19 11:52:57 2020 -0700
@@ -90,40 +90,25 @@
 	return fmtstrcpy(f, encfs(buf, sizeof buf, s));
 }
 
-static char *day[] = {
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
-};
-
-static char *mon[] = {
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
 int
 Dfmt(Fmt *f)
 {
-	char buf[128], *p, *e, *sgn, *fmt;
-	int off;
-	Tm *tm;
+	char buf[128], *fmt;
+	Tm *tm, t;
+	Tzone *tz;
 
 	tm = va_arg(f->args, Tm*);
-	if(tm == nil)
-		tm = localtime(time(0));
-	sgn = "+";
-	if(tm->tzoff < 0)
-		sgn = "";
-	e = buf + sizeof buf;
-	p = buf;
-	off = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60;
+	if(tm == nil){
+		tz = tzload("local");
+		tm = tmtime(&t, time(0), tz);
+	}
 	if((f->flags & FmtSharp) == 0){
 		/* rfc822 style */
-		fmt = "%.2d %s %.4d %.2d:%.2d:%.2d %s%.4d";
-		p = seprint(p, e, "%s, ", day[tm->wday]);
+		fmt = "WW, DD MMM YYYY hh:mm:ss Z";
 	}else
-		fmt = "%2d-%s-%.4d %2.2d:%2.2d:%2.2d %s%4.4d";
-	seprint(p, e, fmt,
-		tm->mday, mon[tm->mon], tm->year + 1900, tm->hour, tm->min, tm->sec,
-		sgn, off);
+		fmt = "DD-MMM-YYYY hh:mm:ss Z";
 	if(f->r == L'δ')
-		return fmtstrcpy(f, buf);
+		return fmtprint(f, "%τ", tmfmt(tm, fmt));
+	snprint(buf, sizeof(buf), "%τ", tmfmt(tm, fmt));
 	return fmtprint(f, "%Z", buf);
 }
diff -r 730a2ee35853 sys/src/cmd/upas/marshal/marshal.c
--- a/sys/src/cmd/upas/marshal/marshal.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/marshal/marshal.c	Sat Sep 19 11:52:57 2020 -0700
@@ -140,6 +140,7 @@
 char lastchar;
 char *replymsg;
 
+#define Rfc822fmt	"WW, DD MMM YYYY hh:mm:ss Z"
 enum
 {
 	Ok = 0,
@@ -208,6 +209,7 @@
 	hdrstring = nil;
 	ccargc = bccargc = 0;
 
+	tmfmtinstall();
 	quotefmtinstall();
 	fmtinstall('Z', doublequote);
 	fmtinstall('U', rfc2047fmt);
@@ -792,29 +794,13 @@
 	Bterm(f);
 }
 
-char *ascwday[] =
-{
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-char *ascmon[] =
-{
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
 int
 printdate(Biobuf *b)
 {
-	int tz;
 	Tm *tm;
 
 	tm = localtime(time(0));
-	tz = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60;
-
-	return Bprint(b, "Date: %s, %d %s %d %2.2d:%2.2d:%2.2d %s%.4d\n",
-		ascwday[tm->wday], tm->mday, ascmon[tm->mon], 1900 + tm->year,
-		tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz);
+	return Bprint(b, "Date: %τ\n", tmfmt(tm, Rfc822fmt));
 }
 
 int
@@ -1003,16 +989,10 @@
 int
 printunixfrom(int fd)
 {
-	int tz;
 	Tm *tm;
 
 	tm = localtime(time(0));
-	tz = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60;
-
-	return fprint(fd, "From %s %s %s %d %2.2d:%2.2d:%2.2d %s%.4d %d\n",
-		user,
-		ascwday[tm->wday], ascmon[tm->mon], tm->mday,
-		tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz, 1900 + tm->year);
+	return fprint(fd, "From %s %τ\n", user, tmfmt(tm, Rfc822fmt));
 }
 
 char *specialfile[] =
diff -r 730a2ee35853 sys/src/cmd/upas/pop3/pop3.c
--- a/sys/src/cmd/upas/pop3/pop3.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/pop3/pop3.c	Sat Sep 19 11:52:57 2020 -0700
@@ -102,6 +102,8 @@
 	Binit(&in, 0, OREAD);
 	Binit(&out, 1, OWRITE);
 
+	tmfmtinstall();
+
 	ARGBEGIN{
 	case 'a':
 		loggedin = 1;
diff -r 730a2ee35853 sys/src/cmd/upas/scanmail/scanmail.c
--- a/sys/src/cmd/upas/scanmail/scanmail.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/scanmail/scanmail.c	Sat Sep 19 11:52:57 2020 -0700
@@ -400,18 +400,16 @@
 opendump(char *sender)
 {
 	int i;
+	Tm tm;
 	ulong h;
 	char buf[512];
 	Biobuf *b;
-	char *cp;
+	char *cp, mon[8], day[4];
 
-	cp = ctime(time(0));
-	cp[7] = 0;
-	cp[10] = 0;
-	if(cp[8] == ' ')
-		snprint(buf, sizeof buf, "%s/queue.dump/%s%c", SPOOL, cp+4, cp[9]);
-	else
-		snprint(buf, sizeof buf, "%s/queue.dump/%s%c%c", SPOOL, cp+4, cp[8], cp[9]);
+	tmnow(&tm, nil);
+	snprint(mon, sizeof(mon), "%τ", tmfmt(&tm, "MMM"));
+	snprint(day, sizeof(day), "%τ", tmfmt(&tm, "D"));
+	snprint(buf, sizeof buf, "%s/queue.dump/%s%s", SPOOL, mon, day);
 	cp = buf+strlen(buf);
 	if(access(buf, 0) < 0 && sysmkdir(buf, 0777) < 0){
 		syslog(0, "smtpd", "couldn't dump mail from %s: %r", sender);
diff -r 730a2ee35853 sys/src/cmd/upas/send/main.c
--- a/sys/src/cmd/upas/send/main.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/send/main.c	Sat Sep 19 11:52:57 2020 -0700
@@ -66,6 +66,7 @@
 		usage();
 	}ARGEND
 
+	tmfmtinstall();
 	if(*argv == 0)
 		usage();
 	dp = 0;
@@ -404,20 +405,22 @@
 replymsg(String *errstring, message *mp, dest *dp)
 {
 	message *refp = m_new();
+	String *boundary;
 	dest *ndp;
-	char *rcvr;
+	char *rcvr, now[128];
 	int rv;
-	String *boundary;
+	Tm tm;
 
 	boundary = mkboundary();
 
 	refp->bulk = 1;
 	refp->rfc822headers = 1;
+	snprint(now, sizeof(now), "%τ", thedate(&tm));
 	rcvr = dp->status==d_eloop ? "postmaster" : s_to_c(mp->replyaddr);
 	ndp = d_new(s_copy(rcvr));
 	s_append(refp->sender, "postmaster");
 	s_append(refp->replyaddr, "/dev/null");
-	s_append(refp->date, thedate());
+	s_append(refp->date, now);
 	refp->haveto = 1;
 	s_append(refp->body, "To: ");
 	s_append(refp->body, rcvr);
diff -r 730a2ee35853 sys/src/cmd/upas/send/message.c
--- a/sys/src/cmd/upas/send/message.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/send/message.c	Sat Sep 19 11:52:57 2020 -0700
@@ -21,10 +21,12 @@
 int
 default_from(message *mp)
 {
-	char *cp, *lp;
+	char *cp, *lp, now[128];
+	Tm tm;
 
 	cp = getenv("upasname");
 	lp = getlog();
+	snprint(now, sizeof(now), "%τ", thedate(&tm));
 	if(lp == nil){
 		free(cp);
 		return -1;
@@ -34,7 +36,7 @@
 	else
 		s_append(mp->sender, lp);
 	free(cp);
-	s_append(mp->date, thedate());
+	s_append(mp->date, now);
 	return 0;
 }
 
diff -r 730a2ee35853 sys/src/cmd/upas/smtp/smtp.c
--- a/sys/src/cmd/upas/smtp/smtp.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/smtp/smtp.c	Sat Sep 19 11:52:57 2020 -0700
@@ -131,8 +131,10 @@
 	int i, ok, rcvrs, bustedmx;
 	String *from, *fromm, *sender;
 	Mx mx;
+	Tm tm;
 
 	alarmscale = 60*1000;	/* minutes */
+	tmfmtinstall();
 	quotefmtinstall();
 	mailfmtinstall();		/* 2047 encoding */
 	fmtinstall('D', Dfmt);
@@ -309,7 +311,7 @@
 	/*
 	 *  here when some but not all rcvrs failed
 	 */
-	fprint(2, "%s connect to %s: %D %s:\n", thedate(), addr, &mx, phase);
+	fprint(2, "%τ connect to %s: %D %s:\n", thedate(&tm), addr, &mx, phase);
 	for(i = 0; i < rcvrs; i++){
 		if(errs[i]){
 			syslog(0, "smtp.fail", "delivery to %s at %s %D %s, failed: %s",
@@ -335,7 +337,7 @@
 	}
 	syslog(0, "smtp.fail", "%s %s at %s %D %s failed: %s",
 		deliverytype(), allrx, addr, &mx, phase, s_to_c(reply));
-	fprint(2, "%s connect to %s %D %s:\n%s\n", thedate(), addr, &mx, phase, s_to_c(reply));
+	fprint(2, "%τ connect to %s %D %s:\n%s\n", thedate(&tm), addr, &mx, phase, s_to_c(reply));
 	if(!filter)
 		quit(rv);
 	exits(rv);
diff -r 730a2ee35853 sys/src/cmd/upas/smtp/smtpd.c
--- a/sys/src/cmd/upas/smtp/smtpd.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/smtp/smtpd.c	Sat Sep 19 11:52:57 2020 -0700
@@ -92,8 +92,10 @@
 {
 	char *netdir;
 	char buf[1024];
+	Tm tm;
 
 	netdir = nil;
+	tmfmtinstall();
 	quotefmtinstall();
 	fmtinstall('I', eipfmt);
 	fmtinstall('[', encodefmt);
@@ -163,7 +165,7 @@
 		snprint(buf, sizeof(buf), "%s/smtpd.db", UPASLOG);
 		if (open(buf, OWRITE) >= 0) {
 			seek(2, 0, 2);
-			fprint(2, "%d smtpd %s\n", getpid(), thedate());
+			fprint(2, "%d smtpd %τ\n", getpid(), thedate(&tm));
 		} else
 			debug = 0;
 	}
@@ -1169,6 +1171,7 @@
 	char *cp;
 	int n, nbytes, sawdot, status;
 	String *hdr, *line;
+	Tm tm;
 
 	pipesig(&status);	/* set status to 1 on write to closed pipe */
 	sawdot = 0;
@@ -1180,12 +1183,12 @@
 	 *  add a 'From ' line as envelope and Received: stamp
 	 */
 	nbytes = 0;
-	nbytes += Bprint(pp->std[0]->fp, "From %s %s remote from \n",
-		s_to_c(senders.first->p), thedate());
+	nbytes += Bprint(pp->std[0]->fp, "From %s %τ remote from \n",
+		s_to_c(senders.first->p), thedate(&tm));
 	nbytes += Bprint(pp->std[0]->fp, "Received: from %s ", him);
 	if(nci->rsys)
 		nbytes += Bprint(pp->std[0]->fp, "([%s]) ", nci->rsys);
-	nbytes += Bprint(pp->std[0]->fp, "by %s; %s\n", me, thedate());
+	nbytes += Bprint(pp->std[0]->fp, "by %s; %τ\n", me, thedate(&tm));
 
 	/*
 	 *  read first 16k obeying '.' escape.  we're assuming
diff -r 730a2ee35853 sys/src/cmd/upas/smtp/spam.c
--- a/sys/src/cmd/upas/smtp/spam.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/smtp/spam.c	Sat Sep 19 11:52:57 2020 -0700
@@ -417,17 +417,15 @@
 dumpfile(char *sender)
 {
 	int i, fd;
+	Tm tm;
 	ulong h;
 	static char buf[512];
-	char *cp;
+	char *cp, mon[8], day[4];
 
 	if (sflag == 1){
-		cp = ctime(time(0));
-		cp[7] = 0;
-		if(cp[8] == ' ')
-			sprint(buf, "%s/queue.dump/%s%c", SPOOL, cp + 4, cp[9]);
-		else
-			sprint(buf, "%s/queue.dump/%s%c%c", SPOOL, cp + 4, cp[8], cp[9]);
+		snprint(mon, sizeof(mon), "%τ", tmfmt(&tm, "MMM"));
+		snprint(day, sizeof(day), "%τ", tmfmt(&tm, "D"));
+		snprint(buf, sizeof buf, "%s/queue.dump/%s%s", SPOOL, mon, day);
 		cp = buf + strlen(buf);
 		if(access(buf, 0) < 0 && sysmkdir(buf, 0777) < 0)
 			return "/dev/null";
diff -r 730a2ee35853 sys/src/cmd/upas/vf/vf.c
--- a/sys/src/cmd/upas/vf/vf.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/vf/vf.c	Sat Sep 19 11:52:57 2020 -0700
@@ -372,7 +372,7 @@
 save(Part *p, char *file)
 {
 	int fd;
-	char *cp;
+	Tm tm;
 
 	Bterm(&out);
 	memset(&out, 0, sizeof(out));
@@ -382,9 +382,7 @@
 		return -1;
 	seek(fd, 0, 2);
 	Binit(&out, fd, OWRITE);
-	cp = ctime(time(0));
-	cp[28] = 0;
-	Bprint(&out, "From virusfilter %s\n", cp);
+	Bprint(&out, "From virusfilter %τ\n", thedate(&tm));
 	writeheader(p, 0);
 	bodyoff = Boffset(&out);
 	passbody(p, 1);



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9front] Upas: Complete date library conversion.
  2020-09-19 18:53 Upas: Complete date library conversion ori
@ 2020-09-19 18:55 ` ori
  2020-09-20  0:38   ` ori
  0 siblings, 1 reply; 6+ messages in thread
From: ori @ 2020-09-19 18:55 UTC (permalink / raw)
  To: ori, 9front

> This patch completes the conversion to our new date and
> time APIs. Needs careful review and testing. The imap
> part seems to be working. I'm waiting on vultr to unblock
> port 25 so I can test out the SMTP part of the patch.

One thing to note: This changes the date formats so that
timezones are unambiguous, using the +HHMM offset syntax.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9front] Upas: Complete date library conversion.
  2020-09-19 18:55 ` [9front] " ori
@ 2020-09-20  0:38   ` ori
  2020-09-20  1:46     ` Anthony Martin
  0 siblings, 1 reply; 6+ messages in thread
From: ori @ 2020-09-20  0:38 UTC (permalink / raw)
  To: 9front

>> This patch completes the conversion to our new date and
>> time APIs. Needs careful review and testing. The imap
>> part seems to be working. I'm waiting on vultr to unblock
>> port 25 so I can test out the SMTP part of the patch.
> 
> One thing to note: This changes the date formats so that
> timezones are unambiguous, using the +HHMM offset syntax.

Oh. This goes with one change to libc:

diff -r 730a2ee35853 sys/man/2/tmdate
--- a/sys/man/2/tmdate	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/man/2/tmdate	Sat Sep 19 17:38:18 2020 -0700
@@ -135,6 +135,7 @@
 .TP
 .B ?
 When parsing, this makes the following argument match fuzzily.
+When formatting, this is ignored.
 Fuzzy matching means that all formats are tried, from most to least specific.
 For example, 
 .I ?M
diff -r 730a2ee35853 sys/src/libc/port/date.c
--- a/sys/src/libc/port/date.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/libc/port/date.c	Sat Sep 19 17:38:18 2020 -0700
@@ -428,6 +428,9 @@
 		switch(c0){
 		case 0:
 			break;
+		/* Ignore '?' so we can share parse and format strings */
+		case '?':
+			continue;
 		case 'Y':
 			switch(w){
 			case 1:	n += fmtprint(f, "%*d", pad, tm->year + 1900);		break;



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9front] Upas: Complete date library conversion.
  2020-09-20  0:38   ` ori
@ 2020-09-20  1:46     ` Anthony Martin
  2020-09-20  1:51       ` ori
  0 siblings, 1 reply; 6+ messages in thread
From: Anthony Martin @ 2020-09-20  1:46 UTC (permalink / raw)
  To: 9front

ori@eigenstate.org once said:
>  When parsing, this makes the following argument match fuzzily.
> +When formatting, this is ignored.
>  Fuzzy matching means that all formats are tried, from most to least specific.
>  For example,

The word "fuzzily" is a bit silly and this rule is not like
approximate string matching nor fuzzy logic.

How about:

	When parsing, all formats of the following argument are tried
	from most to least specific. For example, ?M will match January,
	Jan, 01, and 1, in that order. When formatting, this is ignored.

Cheers,
  Anthony



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9front] Upas: Complete date library conversion.
  2020-09-20  1:46     ` Anthony Martin
@ 2020-09-20  1:51       ` ori
  2020-09-20  3:34         ` ori
  0 siblings, 1 reply; 6+ messages in thread
From: ori @ 2020-09-20  1:51 UTC (permalink / raw)
  To: 9front

> ori@eigenstate.org once said:
>>  When parsing, this makes the following argument match fuzzily.
>> +When formatting, this is ignored.
>>  Fuzzy matching means that all formats are tried, from most to least specific.
>>  For example,
> 
> The word "fuzzily" is a bit silly and this rule is not like
> approximate string matching nor fuzzy logic.
> 
> How about:
> 
> 	When parsing, all formats of the following argument are tried
> 	from most to least specific. For example, ?M will match January,
> 	Jan, 01, and 1, in that order. When formatting, this is ignored.
> 
> Cheers,
>   Anthony

I like that much better, thanks!

If there are revisions to the diff, I'll roll them in, if not,
it'll be in the commit.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [9front] Upas: Complete date library conversion.
  2020-09-20  1:51       ` ori
@ 2020-09-20  3:34         ` ori
  0 siblings, 0 replies; 6+ messages in thread
From: ori @ 2020-09-20  3:34 UTC (permalink / raw)
  To: ori, 9front

> I like that much better, thanks!
> 
> If there are revisions to the diff, I'll roll them in, if not,
> it'll be in the commit.

There was another revision. One missed conversion to +HHMM style
timezones in the unixdate field.

Finally testing this on my own smtp server, seems to be working
for me.

diff -r 730a2ee35853 sys/man/2/tmdate
--- a/sys/man/2/tmdate	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/man/2/tmdate	Sat Sep 19 20:33:27 2020 -0700
@@ -134,8 +134,7 @@
 will format to a width of 3. When parsing, this acts as whitespace.
 .TP
 .B ?
-When parsing, this makes the following argument match fuzzily.
-Fuzzy matching means that all formats are tried, from most to least specific.
+When parsing, all formats of the following argument are tried from most to least specific.
 For example, 
 .I ?M
 will match 
@@ -144,7 +143,9 @@
 .IR 01 ,
 and 
 .IR 1 ,
-in that order of preference.
+in that order. When formatting,
+.B ?
+is ignored.
 .TP
 .B ~
 When parsing a date, this slackens range enforcement, accepting
diff -r 730a2ee35853 sys/src/cmd/upas/Mail/mail.c
--- a/sys/src/cmd/upas/Mail/mail.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/Mail/mail.c	Sat Sep 19 20:33:27 2020 -0700
@@ -82,6 +82,7 @@
 
 	doquote = needsrcquote;
 	quotefmtinstall();
+	tmfmtinstall();
 
 	/* open these early so we won't miss notification of new mail messages while we read mbox */
 	plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
diff -r 730a2ee35853 sys/src/cmd/upas/Mail/mesg.c
--- a/sys/src/cmd/upas/Mail/mesg.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/Mail/mesg.c	Sat Sep 19 20:33:27 2020 -0700
@@ -224,14 +224,13 @@
 int
 thisyear(char *year)
 {
-	static char now[10];
-	char *s;
+	Tzone *tz;
+	Tm tm;
 
-	if(now[0] == '\0'){
-		s = ctime(time(nil));
-		strcpy(now, s+24);
-	}
-	return strncmp(year, now, 4) == 0;
+	/* ignore errors: screwed means utc */
+	tz = tzload("local");
+	tmnow(&tm, tz);
+	return atoi(year) == (tm.year + 1900);
 }
 
 char*
diff -r 730a2ee35853 sys/src/cmd/upas/Mail/reply.c
--- a/sys/src/cmd/upas/Mail/reply.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/Mail/reply.c	Sat Sep 19 20:33:27 2020 -0700
@@ -388,7 +388,9 @@
 	Channel *sync;
 	Message *r;
 	int first, nfld, delit, ofd;
-	char *copy, *fld[100], *now;
+	char *copy, *fld[100];
+	Tzone *tz;
+	Tm now;
 
 	body = winreadbody(m->w, &n);
 	/* assemble to: list from first line, to: line, and cc: line */
@@ -467,11 +469,12 @@
 
 	ofd = open(outgoing, OWRITE|OCEXEC);	/* no error check necessary */
 	if(ofd >= 0){
-		/* From dhog Fri Aug 24 22:13:00 EDT 2001 */
-		now = ctime(time(0));
-		fprint(ofd, "From %s %s", user, now);
+		/* From dhog Fri Aug 24 22:13:00 +0500 2001 */
+		tz = tzload("local");
+		tmnow(&now, tz);
+		fprint(ofd, "From %s %τ", user, tmfmt(&now, "WW MMM _D hh:mm:ss Z YYYY"));
 		fprint(ofd, "From: %s\n", user);
-		fprint(ofd, "Date: %s", now);
+		fprint(ofd, "Date: %τ", tmfmt(&now, "WW MMM _D hh:mm:ss Z YYYY"));
 		for(i=0; i<natt; i++)
 			if(included[i])
 				fprint(ofd, "Include: %s\n", attlist[i]);
diff -r 730a2ee35853 sys/src/cmd/upas/common/common.h
--- a/sys/src/cmd/upas/common/common.h	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/common/common.h	Sat Sep 19 20:33:27 2020 -0700
@@ -20,6 +20,7 @@
 	Fstored		= 1<<6, /* S */
 	Nflags		= 7,
 };
+#define Timefmt "WW MMM _D hh:mm:ss ?Z YYYY"
 
 /*
  * flag.c
diff -r 730a2ee35853 sys/src/cmd/upas/common/folder.c
--- a/sys/src/cmd/upas/common/folder.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/common/folder.c	Sat Sep 19 20:33:27 2020 -0700
@@ -1,7 +1,5 @@
 #include "common.h"
 
-#define Ctimefmt "WW MMM _D hh:mm:ss ?Z YYYY"
-
 enum{
 	Mbox	= 1,
 	Mdir,
@@ -186,22 +184,24 @@
 int
 appendfolder(Biobuf *b, char *addr, int fd)
 {
-	char *s, *t;
-	int r;
+	char *s;
+	int r, n;
 	Biobuf bin;
 	Folder *f;
+	Tzone *tz;
 	Tm tm;
 
 	f = getfolder(b);
 	Bseek(f->out, 0, 2);
 	Binit(&bin, fd, OREAD);
 	s = Brdstr(&bin, '\n', 0);
-	if(s == nil || strncmp(s, "From ", 5) != 0)
-		Bprint(f->out, "From %s %.28s\n", addr, ctime(f->t));
-	else if(strncmp(s, "From ", 5) == 0 
-		&& (t = strchr(s + 5, ' ')) != nil
-		&& tmparse(&tm, Ctimefmt, t + 1, nil, nil) != nil)
-		f->t = tm2sec(&tm);
+	n = strlen(s);
+	if(!s || strncmp(s, "From ", 5) != 0){
+		tz = tzload("local");
+		tmtime(&tm, f->t, tz);
+		Bprint(f->out, "From %s %τ\n", addr, tmfmt(&tm, Timefmt));
+	}else if(n > 5 && tmparse(&tm, Timefmt, s + 5, nil, nil) != nil)
+		f->t = tmnorm(&tm);
 	if(s)
 		Bwrite(f->out, s, strlen(s));
 	free(s);
diff -r 730a2ee35853 sys/src/cmd/upas/common/libsys.c
--- a/sys/src/cmd/upas/common/libsys.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/common/libsys.c	Sat Sep 19 20:33:27 2020 -0700
@@ -5,14 +5,15 @@
 /*
  *  return the date
  */
-char*
-thedate(void)
+Tmfmt
+thedate(Tm *tm)
 {
-	static char now[64];
+	Tzone *tz;
 
-	strcpy(now, ctime(time(0)));
-	now[28] = 0;
-	return now;
+	/* if the local time is screwed, just do gmt */
+	tz = tzload("local");
+	tmnow(tm, tz);
+	return tmfmt(tm, Timefmt);
 }
 
 /*
diff -r 730a2ee35853 sys/src/cmd/upas/common/sys.h
--- a/sys/src/cmd/upas/common/sys.h	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/common/sys.h	Sat Sep 19 20:33:27 2020 -0700
@@ -35,7 +35,7 @@
 char	*domainname_read(void);
 char	**sysnames_read(void);
 char	*getlog(void);
-char	*thedate(void);
+Tmfmt	thedate(Tm*);
 Biobuf	*sysopen(char*, char*, ulong);
 int	sysopentty(void);
 int	sysclose(Biobuf*);
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/deliver.c
--- a/sys/src/cmd/upas/filterkit/deliver.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/deliver.c	Sat Sep 19 20:33:27 2020 -0700
@@ -14,13 +14,15 @@
 void
 main(int argc, char **argv)
 {
-	char *to, *s;
+	char *to;
+	Tmfmt tf;
+	Tm tm;
 	int r;
-	long l;
 	Addr *a;
 
 	ARGBEGIN{
 	}ARGEND;
+	tmfmtinstall();
 	if(argc != 3)
 		usage();
 	if(to = strrchr(argv[0], '!'))
@@ -30,9 +32,9 @@
 	a = readaddrs(argv[1], nil);
 	if(a == nil)
 		sysfatal("missing from address");
-	s = ctime(l = time(0));
+	tf = thedate(&tm);
 	werrstr("");
-	r = fappendfolder(a->val, l, argv[2], 0);
-	syslog(0, "mail", "delivered %s From %s %.28s (%s) %d %r", to, a->val, s, argv[0], r);
+	r = fappendfolder(a->val, tmnorm(&tm), argv[2], 0);
+	syslog(0, "mail", "delivered %s From %s %τ (%s) %d %r", to, a->val, tf, argv[0], r);
 	exits("");
 }
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/list.c
--- a/sys/src/cmd/upas/filterkit/list.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/list.c	Sat Sep 19 20:33:27 2020 -0700
@@ -306,6 +306,7 @@
 	} ARGEND;
 
 	quotefmtinstall();
+	tmfmtinstall();
 
 	if(argc < 3)
 		usage();
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/mbappend.c
--- a/sys/src/cmd/upas/filterkit/mbappend.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/mbappend.c	Sat Sep 19 20:33:27 2020 -0700
@@ -7,15 +7,15 @@
 void
 append(int fd, char *mb, char *from, long t)
 {
-	char *folder, *s;
+	char *folder;
+	Tm tm;
 	int r;
 
-	s = ctime(t);
 	folder = foldername(from, getuser(), mb);
 	r = fappendfolder(0, t, folder, fd);
 	if(r == 0)
 		werrstr("");
-	syslog(0, "mail", "mbappend %s %.28s (%s) %r", mb, s, folder);
+	syslog(0, "mail", "mbappend %s %τ (%s) %r", mb, thedate(&tm), folder);
 	if(r)
 		exits("fail");
 }
@@ -36,6 +36,7 @@
 
 	from = nil;
 	t = time(0);
+	tmfmtinstall();
 	ARGBEGIN{
 	case 't':
 		t = strtoul(EARGF(usage()), 0, 0);
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/mbcreate.c
--- a/sys/src/cmd/upas/filterkit/mbcreate.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/mbcreate.c	Sat Sep 19 20:33:27 2020 -0700
@@ -24,6 +24,7 @@
 	}ARGEND
 
 	r = 0;
+	tmfmtinstall();
 	for(; *argv; argv++)
 		r |= f(getuser(), *argv);
 	if(r)
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/mbremove.c
--- a/sys/src/cmd/upas/filterkit/mbremove.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/mbremove.c	Sat Sep 19 20:33:27 2020 -0700
@@ -235,6 +235,7 @@
 	}ARGEND
 
 	r = 0;
+	tmfmtinstall();
 	for(; *argv; argv++)
 		r |= f(getuser(), *argv);
 	if(r)
diff -r 730a2ee35853 sys/src/cmd/upas/filterkit/token.c
--- a/sys/src/cmd/upas/filterkit/token.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/filterkit/token.c	Sat Sep 19 20:33:27 2020 -0700
@@ -62,6 +62,7 @@
 	ARGBEGIN {
 	} ARGEND;
 
+	tmfmtinstall();
 	switch(argc){
 	case 2:
 		exits(check_token(argv[0], argv[1]));
diff -r 730a2ee35853 sys/src/cmd/upas/fs/extra/strtotmtst.c
--- a/sys/src/cmd/upas/fs/extra/strtotmtst.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/fs/extra/strtotmtst.c	Sat Sep 19 20:33:27 2020 -0700
@@ -8,9 +8,10 @@
 	ARGBEGIN{
 	}ARGEND
 
+	tmfmtinstall();
 	for(; *argv; argv++)
 		if(strtotm(*argv, &tm) >= 0)
-			print("%s", asctime(&tm));
+			print("%τ\n", tmfmt(&tm, nil));
 		else
 			print("bad\n");
 	exits("");
diff -r 730a2ee35853 sys/src/cmd/upas/fs/fs.c
--- a/sys/src/cmd/upas/fs/fs.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/fs/fs.c	Sat Sep 19 20:33:27 2020 -0700
@@ -174,16 +174,15 @@
 static int
 Δfmt(Fmt *f)
 {
-	char buf[32];
 	uvlong v;
+	Tm tm;
 
 	v = va_arg(f->args, uvlong);
 	if(f->flags & FmtSharp)
 		if((v>>8) == 0)
 			return fmtstrcpy(f, "");
-	strcpy(buf, ctime(v>>8));
-	buf[28] = 0;
-	return fmtstrcpy(f, buf);
+	tmtime(&tm, v>>8, tzload("local"));
+	return fmtprint(f, "%τ", tmfmt(&tm, "WW MMM _D hh:mm:ss Z YYYY"));
 }
 
 static int
@@ -320,6 +319,7 @@
 	fmtinstall(L'Δ', Δfmt);
 	fmtinstall('F', fcallfmt);
 	fmtinstall('H', encodefmt);		/* forces tls stuff */
+	tmfmtinstall();
 	quotefmtinstall();
 	if(pipe(p) < 0)
 		error("pipe failed");
diff -r 730a2ee35853 sys/src/cmd/upas/fs/mbox.c
--- a/sys/src/cmd/upas/fs/mbox.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/fs/mbox.c	Sat Sep 19 20:33:27 2020 -0700
@@ -366,11 +366,11 @@
 	if(m->fileid > 1000000ull<<8)
 		return;
 	if(m->unixdate && strtotm(m->unixdate, &tm) >= 0)
-		v = tm2sec(&tm);
+		v = tmnorm(&tm);
 	else if(m->date822 && strtotm(m->date822, &tm) >= 0)
-		v = tm2sec(&tm);
+		v = tmnorm(&tm);
 	else if(rxtotm(m, &tm) >= 0)
-		v = tm2sec(&tm);
+		v = tmnorm(&tm);
 	else{
 		logmsg(gettopmsg(mb, m), "%s:%s: datasec %s %s\n", mb->path,
 			m->whole? m->whole->name: "?",
diff -r 730a2ee35853 sys/src/cmd/upas/fs/plan9.c
--- a/sys/src/cmd/upas/fs/plan9.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/fs/plan9.c	Sat Sep 19 20:33:27 2020 -0700
@@ -34,7 +34,7 @@
 		return -1;
 	if(memtotm(p, n - (p - s), &tm) < 0)
 		return -1;
-	if(tm2sec(&tm) < 1000000)
+	if(tmnorm(&tm) < 1000000)
 		return -1;
 	return 0;
 }
diff -r 730a2ee35853 sys/src/cmd/upas/imap4d/date.c
--- a/sys/src/cmd/upas/imap4d/date.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/imap4d/date.c	Sat Sep 19 20:33:27 2020 -0700
@@ -1,142 +1,10 @@
 #include "imap4d.h"
 
-static char *wdayname[] = {
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-static char *monname[] = {
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-/*
- * zone	: [A-Za-z][A-Za-z][A-Za-z]	some time zone names
- *	| [A-IK-Z]			military time; rfc1123 says the rfc822 spec is wrong.
- *	| "UT"				universal time
- *	| [+-][0-9][0-9][0-9][0-9]
- * zones is the rfc-822 list of time zone names
- */
-static Namedint zones[] =
-{
-	{"A",	-1 * 3600},
-	{"B",	-2 * 3600},
-	{"C",	-3 * 3600},
-	{"CDT", -5 * 3600},
-	{"CST", -6 * 3600},
-	{"D",	-4 * 3600},
-	{"E",	-5 * 3600},
-	{"EDT", -4 * 3600},
-	{"EST", -5 * 3600},
-	{"F",	-6 * 3600},
-	{"G",	-7 * 3600},
-	{"GMT", 0},
-	{"H",	-8 * 3600},
-	{"I",	-9 * 3600},
-	{"K",	-10 * 3600},
-	{"L",	-11 * 3600},
-	{"M",	-12 * 3600},
-	{"MDT", -6 * 3600},
-	{"MST", -7 * 3600},
-	{"N",	+1 * 3600},
-	{"O",	+2 * 3600},
-	{"P",	+3 * 3600},
-	{"PDT", -7 * 3600},
-	{"PST", -8 * 3600},
-	{"Q",	+4 * 3600},
-	{"R",	+5 * 3600},
-	{"S",	+6 * 3600},
-	{"T",	+7 * 3600},
-	{"U",	+8 * 3600},
-	{"UT",	0},
-	{"V",	+9 * 3600},
-	{"W",	+10 * 3600},
-	{"X",	+11 * 3600},
-	{"Y",	+12 * 3600},
-	{"Z",	0},
-};
-
-static void
-zone2tm(Tm *tm, char *s)
-{
-	int i;
-	Tm aux, *atm;
-
-	if(*s == '+' || *s == '-'){
-		i = strtol(s, &s, 10);
-		tm->tzoff = (i/100)*3600 + i%100;
-		strncpy(tm->zone, "", 4);
-		return;
-	}
-
-	/*
-	 * look it up in the standard rfc822 table
-	 */
-	strncpy(tm->zone, s, 3);
-	tm->zone[3] = 0;
-	tm->tzoff = 0;
-	for(i = 0; i < nelem(zones); i++){
-		if(cistrcmp(zones[i].name, s) == 0){
-			tm->tzoff = zones[i].v;
-			return;
-		}
-	}
-
-	/*
-	 * one last try: look it up in the current local timezone
-	 * probe a couple of times to get daylight/standard time change.
-	 */
-	aux = *tm;
-	memset(aux.zone, 0, 4);
-	aux.hour--;
-	for(i = 0; i < 2; i++){
-		atm = localtime(tm2sec(&aux));
-		if(cistrcmp(tm->zone, atm->zone) == 0){
-			tm->tzoff = atm->tzoff;
-			return;
-		}
-		aux.hour++;
-	}
-
-	strncpy(tm->zone, "GMT", 4);
-	tm->tzoff = 0;
-}
-
-/*
- * hh[:mm[:ss]]
- */
-static void
-time2tm(Tm *tm, char *s)
-{
-	tm->hour = strtoul(s, &s, 10);
-	if(*s++ != ':')
-		return;
-	tm->min = strtoul(s, &s, 10);
-	if(*s++ != ':')
-		return;
-	tm->sec = strtoul(s, &s, 10);
-}
-
-static int
-dateindex(char *d, char **tab, int n)
-{
-	int i;
-
-	for(i = 0; i < n; i++)
-		if(cistrcmp(d, tab[i]) == 0)
-			return i;
-	return -1;
-}
-
 int
 imap4date(Tm *tm, char *date)
 {
-	char *flds[4];
-
-	if(getfields(date, flds, 3, 0, "-") != 3)
+	if(tmparse(tm, "DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) == nil)
 		return 0;
-
-	tm->mday = strtol(flds[0], nil, 10);
-	tm->mon = dateindex(flds[1], monname, 12);
-	tm->year = strtol(flds[2], nil, 10) - 1900;
 	return 1;
 }
 
@@ -146,29 +14,17 @@
 ulong
 imap4datetime(char *date)
 {
-	char *flds[4], *sflds[4];
-	ulong t;
 	Tm tm;
+	vlong s;
 
-	if(getfields(date, flds, 4, 0, " ") != 3)
-		return ~0;
-
-	if(!imap4date(&tm, flds[0]))
-		return ~0;
-
-	if(getfields(flds[1], sflds, 3, 0, ":") != 3)
-		return ~0;
-
-	tm.hour = strtol(sflds[0], nil, 10);
-	tm.min = strtol(sflds[1], nil, 10);
-	tm.sec = strtol(sflds[2], nil, 10);
-
-	strcpy(tm.zone, "GMT");
-	tm.yday = 0;
-	t = tm2sec(&tm);
-	zone2tm(&tm, flds[2]);
-	t -= tm.tzoff;
-	return t;
+	s = -1;
+	if(tmparse(&tm, "?DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) != nil)
+		s = tmnorm(&tm);
+	else if(tmparse(&tm, "?W, ?DD-?MM-YYYY hh:mm:ss ?Z", date, nil, nil) != nil)
+		s = tmnorm(&tm);
+	if(s > 0 && s < (1ULL<<31))
+		return s;
+	return ~0;
 }
 
 /*
@@ -181,85 +37,18 @@
 Tm*
 date2tm(Tm *tm, char *date)
 {
-	char *flds[7], *s, dstr[64];
-	int n;
-	Tm gmt, *atm;
+	char **f, *fmts[] = {
+		"?W, ?DD ?MMM YYYY hh:mm:ss ?Z",
+		"?W ?M ?DD hh:mm:ss ?Z YYYY",
+		"?W, DD-?MM-YY hh:mm:ss ?Z",
+		"?DD ?MMM YYYY hh:mm:ss ?Z",
+		"?M ?DD hh:mm:ss ?Z YYYY",
+		"DD-?MM-YYYY hh:mm:ss ?Z",
+		nil,
+	};
 
-	/*
-	 * default date is Thu Jan  1 00:00:00 GMT 1970
-	 */
-	tm->wday = 4;
-	tm->mday = 1;
-	tm->mon = 1;
-	tm->hour = 0;
-	tm->min = 0;
-	tm->sec = 0;
-	tm->year = 70;
-	strcpy(tm->zone, "GMT");
-	tm->tzoff = 0;
-
-	strncpy(dstr, date, sizeof dstr);
-	dstr[sizeof dstr - 1] = 0;
-	n = tokenize(dstr, flds, 7);
-	if(n != 6 && n != 5)
-		return nil;
-
-	if(n == 5){
-		for(n = 5; n >= 1; n--)
-			flds[n] = flds[n - 1];
-		n = 5;
-	}else{
-		/*
-		 * Wday[,]
-		 */
-		s = strchr(flds[0], ',');
-		if(s != nil)
-			*s = 0;
-		tm->wday = dateindex(flds[0], wdayname, 7);
-		if(tm->wday < 0)
-			return nil;
-	}
-
-	/*
-	 * check for the two major formats:
-	 * Month first or day first
-	 */
-	tm->mon = dateindex(flds[1], monname, 12);
-	if(tm->mon >= 0){
-		tm->mday = strtoul(flds[2], nil, 10);
-		time2tm(tm, flds[3]);
-		zone2tm(tm, flds[4]);
-		tm->year = strtoul(flds[5], nil, 10);
-		if(strlen(flds[5]) > 2)
-			tm->year -= 1900;
-	}else{
-		tm->mday = strtoul(flds[1], nil, 10);
-		tm->mon = dateindex(flds[2], monname, 12);
-		if(tm->mon < 0)
-			return nil;
-		tm->year = strtoul(flds[3], nil, 10);
-		if(strlen(flds[3]) > 2)
-			tm->year -= 1900;
-		time2tm(tm, flds[4]);
-		zone2tm(tm, flds[5]);
-	}
-
-	if(n == 5){
-		gmt = *tm;
-		strncpy(gmt.zone, "", 4);
-		gmt.tzoff = 0;
-		atm = gmtime(tm2sec(&gmt));
-		tm->wday = atm->wday;
-	}else{
-		/*
-		 * Wday[,]
-		 */
-		s = strchr(flds[0], ',');
-		if(s != nil)
-			*s = 0;
-		tm->wday = dateindex(flds[0], wdayname, 7);
-		if(tm->wday < 0)
-			return nil;
-	}
-	return tm;
+	for(f = fmts; *f; f++)
+		if(tmparse(tm, *f, date, nil, nil) != nil)
+			return tm;
+	return nil;
 }
diff -r 730a2ee35853 sys/src/cmd/upas/imap4d/imap4d.c
--- a/sys/src/cmd/upas/imap4d/imap4d.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/imap4d/imap4d.c	Sat Sep 19 20:33:27 2020 -0700
@@ -215,6 +215,7 @@
 	Binit(&bin, dup(0, -1), OREAD);
 	close(0);
 	Binit(&bout, 1, OWRITE);
+	tmfmtinstall();
 	quotefmtinstall();
 	fmtinstall('F', Ffmt);
 	fmtinstall('D', Dfmt);	/* rfc822; # imap date %Z */
@@ -501,6 +502,8 @@
 	char *mbox, head[128];
 	uint t, n, now;
 	int flags, ok;
+	Tzone *tz;
+	Tm tm;
 	Uidplus u;
 
 	mustbe(' ');
@@ -536,7 +539,9 @@
 		return;
 	}
 
-	snprint(head, sizeof head, "From %s %s", username, ctime(t));
+	tz = tzload("local");
+	tmtime(&tm, t, tz);
+	snprint(head, sizeof head, "From %s %τ", username, tmfmt(&tm, "WW MMM _D hh:mm:ss Z YYYY"));
 	ok = appendsave(mbox, flags, head, &bin, n, &u);
 	crnl();
 	check();
diff -r 730a2ee35853 sys/src/cmd/upas/imap4d/nlisttst.c
--- a/sys/src/cmd/upas/imap4d/nlisttst.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/imap4d/nlisttst.c	Sat Sep 19 20:33:27 2020 -0700
@@ -1,7 +1,5 @@
 #include "nlist.c"
 
-char	username[] = "quanstro";
-char	mboxdir[] = "/mail/box/quanstro/";
 Biobuf	bout;
 Bin	*parsebin;
 
diff -r 730a2ee35853 sys/src/cmd/upas/imap4d/print.c
--- a/sys/src/cmd/upas/imap4d/print.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/imap4d/print.c	Sat Sep 19 20:33:27 2020 -0700
@@ -90,40 +90,25 @@
 	return fmtstrcpy(f, encfs(buf, sizeof buf, s));
 }
 
-static char *day[] = {
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
-};
-
-static char *mon[] = {
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
 int
 Dfmt(Fmt *f)
 {
-	char buf[128], *p, *e, *sgn, *fmt;
-	int off;
-	Tm *tm;
+	char buf[128], *fmt;
+	Tm *tm, t;
+	Tzone *tz;
 
 	tm = va_arg(f->args, Tm*);
-	if(tm == nil)
-		tm = localtime(time(0));
-	sgn = "+";
-	if(tm->tzoff < 0)
-		sgn = "";
-	e = buf + sizeof buf;
-	p = buf;
-	off = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60;
+	if(tm == nil){
+		tz = tzload("local");
+		tm = tmtime(&t, time(0), tz);
+	}
 	if((f->flags & FmtSharp) == 0){
 		/* rfc822 style */
-		fmt = "%.2d %s %.4d %.2d:%.2d:%.2d %s%.4d";
-		p = seprint(p, e, "%s, ", day[tm->wday]);
+		fmt = "WW, DD MMM YYYY hh:mm:ss Z";
 	}else
-		fmt = "%2d-%s-%.4d %2.2d:%2.2d:%2.2d %s%4.4d";
-	seprint(p, e, fmt,
-		tm->mday, mon[tm->mon], tm->year + 1900, tm->hour, tm->min, tm->sec,
-		sgn, off);
+		fmt = "DD-MMM-YYYY hh:mm:ss Z";
 	if(f->r == L'δ')
-		return fmtstrcpy(f, buf);
+		return fmtprint(f, "%τ", tmfmt(tm, fmt));
+	snprint(buf, sizeof(buf), "%τ", tmfmt(tm, fmt));
 	return fmtprint(f, "%Z", buf);
 }
diff -r 730a2ee35853 sys/src/cmd/upas/marshal/marshal.c
--- a/sys/src/cmd/upas/marshal/marshal.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/marshal/marshal.c	Sat Sep 19 20:33:27 2020 -0700
@@ -140,6 +140,7 @@
 char lastchar;
 char *replymsg;
 
+#define Rfc822fmt	"WW, DD MMM YYYY hh:mm:ss Z"
 enum
 {
 	Ok = 0,
@@ -208,6 +209,7 @@
 	hdrstring = nil;
 	ccargc = bccargc = 0;
 
+	tmfmtinstall();
 	quotefmtinstall();
 	fmtinstall('Z', doublequote);
 	fmtinstall('U', rfc2047fmt);
@@ -792,29 +794,13 @@
 	Bterm(f);
 }
 
-char *ascwday[] =
-{
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-char *ascmon[] =
-{
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
 int
 printdate(Biobuf *b)
 {
-	int tz;
 	Tm *tm;
 
 	tm = localtime(time(0));
-	tz = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60;
-
-	return Bprint(b, "Date: %s, %d %s %d %2.2d:%2.2d:%2.2d %s%.4d\n",
-		ascwday[tm->wday], tm->mday, ascmon[tm->mon], 1900 + tm->year,
-		tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz);
+	return Bprint(b, "Date: %τ\n", tmfmt(tm, Rfc822fmt));
 }
 
 int
@@ -1003,16 +989,10 @@
 int
 printunixfrom(int fd)
 {
-	int tz;
 	Tm *tm;
 
 	tm = localtime(time(0));
-	tz = (tm->tzoff/3600)*100 + (tm->tzoff/60)%60;
-
-	return fprint(fd, "From %s %s %s %d %2.2d:%2.2d:%2.2d %s%.4d %d\n",
-		user,
-		ascwday[tm->wday], ascmon[tm->mon], tm->mday,
-		tm->hour, tm->min, tm->sec, tz>=0?"+":"", tz, 1900 + tm->year);
+	return fprint(fd, "From %s %τ\n", user, tmfmt(tm, Rfc822fmt));
 }
 
 char *specialfile[] =
diff -r 730a2ee35853 sys/src/cmd/upas/pop3/pop3.c
--- a/sys/src/cmd/upas/pop3/pop3.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/pop3/pop3.c	Sat Sep 19 20:33:27 2020 -0700
@@ -102,6 +102,8 @@
 	Binit(&in, 0, OREAD);
 	Binit(&out, 1, OWRITE);
 
+	tmfmtinstall();
+
 	ARGBEGIN{
 	case 'a':
 		loggedin = 1;
diff -r 730a2ee35853 sys/src/cmd/upas/scanmail/scanmail.c
--- a/sys/src/cmd/upas/scanmail/scanmail.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/scanmail/scanmail.c	Sat Sep 19 20:33:27 2020 -0700
@@ -400,18 +400,16 @@
 opendump(char *sender)
 {
 	int i;
+	Tm tm;
 	ulong h;
 	char buf[512];
 	Biobuf *b;
-	char *cp;
+	char *cp, mon[8], day[4];
 
-	cp = ctime(time(0));
-	cp[7] = 0;
-	cp[10] = 0;
-	if(cp[8] == ' ')
-		snprint(buf, sizeof buf, "%s/queue.dump/%s%c", SPOOL, cp+4, cp[9]);
-	else
-		snprint(buf, sizeof buf, "%s/queue.dump/%s%c%c", SPOOL, cp+4, cp[8], cp[9]);
+	tmnow(&tm, nil);
+	snprint(mon, sizeof(mon), "%τ", tmfmt(&tm, "MMM"));
+	snprint(day, sizeof(day), "%τ", tmfmt(&tm, "D"));
+	snprint(buf, sizeof buf, "%s/queue.dump/%s%s", SPOOL, mon, day);
 	cp = buf+strlen(buf);
 	if(access(buf, 0) < 0 && sysmkdir(buf, 0777) < 0){
 		syslog(0, "smtpd", "couldn't dump mail from %s: %r", sender);
diff -r 730a2ee35853 sys/src/cmd/upas/send/main.c
--- a/sys/src/cmd/upas/send/main.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/send/main.c	Sat Sep 19 20:33:27 2020 -0700
@@ -66,6 +66,7 @@
 		usage();
 	}ARGEND
 
+	tmfmtinstall();
 	if(*argv == 0)
 		usage();
 	dp = 0;
@@ -404,20 +405,22 @@
 replymsg(String *errstring, message *mp, dest *dp)
 {
 	message *refp = m_new();
+	String *boundary;
 	dest *ndp;
-	char *rcvr;
+	char *rcvr, now[128];
 	int rv;
-	String *boundary;
+	Tm tm;
 
 	boundary = mkboundary();
 
 	refp->bulk = 1;
 	refp->rfc822headers = 1;
+	snprint(now, sizeof(now), "%τ", thedate(&tm));
 	rcvr = dp->status==d_eloop ? "postmaster" : s_to_c(mp->replyaddr);
 	ndp = d_new(s_copy(rcvr));
 	s_append(refp->sender, "postmaster");
 	s_append(refp->replyaddr, "/dev/null");
-	s_append(refp->date, thedate());
+	s_append(refp->date, now);
 	refp->haveto = 1;
 	s_append(refp->body, "To: ");
 	s_append(refp->body, rcvr);
diff -r 730a2ee35853 sys/src/cmd/upas/send/message.c
--- a/sys/src/cmd/upas/send/message.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/send/message.c	Sat Sep 19 20:33:27 2020 -0700
@@ -21,10 +21,12 @@
 int
 default_from(message *mp)
 {
-	char *cp, *lp;
+	char *cp, *lp, now[128];
+	Tm tm;
 
 	cp = getenv("upasname");
 	lp = getlog();
+	snprint(now, sizeof(now), "%τ", thedate(&tm));
 	if(lp == nil){
 		free(cp);
 		return -1;
@@ -34,7 +36,7 @@
 	else
 		s_append(mp->sender, lp);
 	free(cp);
-	s_append(mp->date, thedate());
+	s_append(mp->date, now);
 	return 0;
 }
 
diff -r 730a2ee35853 sys/src/cmd/upas/smtp/smtp.c
--- a/sys/src/cmd/upas/smtp/smtp.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/smtp/smtp.c	Sat Sep 19 20:33:27 2020 -0700
@@ -131,8 +131,10 @@
 	int i, ok, rcvrs, bustedmx;
 	String *from, *fromm, *sender;
 	Mx mx;
+	Tm tm;
 
 	alarmscale = 60*1000;	/* minutes */
+	tmfmtinstall();
 	quotefmtinstall();
 	mailfmtinstall();		/* 2047 encoding */
 	fmtinstall('D', Dfmt);
@@ -309,7 +311,7 @@
 	/*
 	 *  here when some but not all rcvrs failed
 	 */
-	fprint(2, "%s connect to %s: %D %s:\n", thedate(), addr, &mx, phase);
+	fprint(2, "%τ connect to %s: %D %s:\n", thedate(&tm), addr, &mx, phase);
 	for(i = 0; i < rcvrs; i++){
 		if(errs[i]){
 			syslog(0, "smtp.fail", "delivery to %s at %s %D %s, failed: %s",
@@ -335,7 +337,7 @@
 	}
 	syslog(0, "smtp.fail", "%s %s at %s %D %s failed: %s",
 		deliverytype(), allrx, addr, &mx, phase, s_to_c(reply));
-	fprint(2, "%s connect to %s %D %s:\n%s\n", thedate(), addr, &mx, phase, s_to_c(reply));
+	fprint(2, "%τ connect to %s %D %s:\n%s\n", thedate(&tm), addr, &mx, phase, s_to_c(reply));
 	if(!filter)
 		quit(rv);
 	exits(rv);
diff -r 730a2ee35853 sys/src/cmd/upas/smtp/smtpd.c
--- a/sys/src/cmd/upas/smtp/smtpd.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/smtp/smtpd.c	Sat Sep 19 20:33:27 2020 -0700
@@ -92,8 +92,10 @@
 {
 	char *netdir;
 	char buf[1024];
+	Tm tm;
 
 	netdir = nil;
+	tmfmtinstall();
 	quotefmtinstall();
 	fmtinstall('I', eipfmt);
 	fmtinstall('[', encodefmt);
@@ -163,7 +165,7 @@
 		snprint(buf, sizeof(buf), "%s/smtpd.db", UPASLOG);
 		if (open(buf, OWRITE) >= 0) {
 			seek(2, 0, 2);
-			fprint(2, "%d smtpd %s\n", getpid(), thedate());
+			fprint(2, "%d smtpd %τ\n", getpid(), thedate(&tm));
 		} else
 			debug = 0;
 	}
@@ -1169,6 +1171,7 @@
 	char *cp;
 	int n, nbytes, sawdot, status;
 	String *hdr, *line;
+	Tm tm;
 
 	pipesig(&status);	/* set status to 1 on write to closed pipe */
 	sawdot = 0;
@@ -1180,12 +1183,12 @@
 	 *  add a 'From ' line as envelope and Received: stamp
 	 */
 	nbytes = 0;
-	nbytes += Bprint(pp->std[0]->fp, "From %s %s remote from \n",
-		s_to_c(senders.first->p), thedate());
+	nbytes += Bprint(pp->std[0]->fp, "From %s %τ remote from \n",
+		s_to_c(senders.first->p), thedate(&tm));
 	nbytes += Bprint(pp->std[0]->fp, "Received: from %s ", him);
 	if(nci->rsys)
 		nbytes += Bprint(pp->std[0]->fp, "([%s]) ", nci->rsys);
-	nbytes += Bprint(pp->std[0]->fp, "by %s; %s\n", me, thedate());
+	nbytes += Bprint(pp->std[0]->fp, "by %s; %τ\n", me, thedate(&tm));
 
 	/*
 	 *  read first 16k obeying '.' escape.  we're assuming
diff -r 730a2ee35853 sys/src/cmd/upas/smtp/spam.c
--- a/sys/src/cmd/upas/smtp/spam.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/smtp/spam.c	Sat Sep 19 20:33:27 2020 -0700
@@ -417,17 +417,15 @@
 dumpfile(char *sender)
 {
 	int i, fd;
+	Tm tm;
 	ulong h;
 	static char buf[512];
-	char *cp;
+	char *cp, mon[8], day[4];
 
 	if (sflag == 1){
-		cp = ctime(time(0));
-		cp[7] = 0;
-		if(cp[8] == ' ')
-			sprint(buf, "%s/queue.dump/%s%c", SPOOL, cp + 4, cp[9]);
-		else
-			sprint(buf, "%s/queue.dump/%s%c%c", SPOOL, cp + 4, cp[8], cp[9]);
+		snprint(mon, sizeof(mon), "%τ", tmfmt(&tm, "MMM"));
+		snprint(day, sizeof(day), "%τ", tmfmt(&tm, "D"));
+		snprint(buf, sizeof buf, "%s/queue.dump/%s%s", SPOOL, mon, day);
 		cp = buf + strlen(buf);
 		if(access(buf, 0) < 0 && sysmkdir(buf, 0777) < 0)
 			return "/dev/null";
diff -r 730a2ee35853 sys/src/cmd/upas/vf/vf.c
--- a/sys/src/cmd/upas/vf/vf.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/cmd/upas/vf/vf.c	Sat Sep 19 20:33:27 2020 -0700
@@ -372,7 +372,7 @@
 save(Part *p, char *file)
 {
 	int fd;
-	char *cp;
+	Tm tm;
 
 	Bterm(&out);
 	memset(&out, 0, sizeof(out));
@@ -382,9 +382,7 @@
 		return -1;
 	seek(fd, 0, 2);
 	Binit(&out, fd, OWRITE);
-	cp = ctime(time(0));
-	cp[28] = 0;
-	Bprint(&out, "From virusfilter %s\n", cp);
+	Bprint(&out, "From virusfilter %τ\n", thedate(&tm));
 	writeheader(p, 0);
 	bodyoff = Boffset(&out);
 	passbody(p, 1);
diff -r 730a2ee35853 sys/src/libc/port/date.c
--- a/sys/src/libc/port/date.c	Thu Sep 17 16:11:10 2020 -0700
+++ b/sys/src/libc/port/date.c	Sat Sep 19 20:33:27 2020 -0700
@@ -428,6 +428,9 @@
 		switch(c0){
 		case 0:
 			break;
+		/* Ignore '?' so we can share parse and format strings */
+		case '?':
+			continue;
 		case 'Y':
 			switch(w){
 			case 1:	n += fmtprint(f, "%*d", pad, tm->year + 1900);		break;



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2020-09-20  3:34 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-19 18:53 Upas: Complete date library conversion ori
2020-09-19 18:55 ` [9front] " ori
2020-09-20  0:38   ` ori
2020-09-20  1:46     ` Anthony Martin
2020-09-20  1:51       ` ori
2020-09-20  3:34         ` ori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).