code: regress

Download patch

ref: ef3d02cda8c74294c9461c0ef45497781a118d63
author: Ori Bernstein <ori@eigenstate.org>
date: Mon Jun 15 01:47:17 EDT 2020

regress: initial commit for date code

diff: cannot open b/cmd//null: file does not exist: 'b/cmd//null' diff: cannot open b/libc//null: file does not exist: 'b/libc//null'
--- /dev/null
+++ b/cmd/date.rc
@@ -1,0 +1,44 @@
+#!/bin/rc
+
+nl='
+'
+
+fn check {
+	r=`$nl{seconds $1}
+	if(! ~ $r $2){
+		>[1=2] echo fail: $1: got $r expected $2
+		exit 'fail'
+	}
+}
+
+# examples from manpage, and shuffles
+check '23 may 2011' 			1306108800
+check 'may 23 2011' 			1306108800
+check 'may 2011 23' 			1306108800
+check '23 2011 may' 			1306108800
+check '2011 may 23'			1306108800
+check '2011 23 may'			1306108800
+
+# now with timezones
+check '23 may 2011 edt'			1306123200
+check '23 may 2011 gmt'			1306108800
+
+# now with times
+check 'may 23 2011 0'			1306108800
+check 'may 23 2011 0:1'			1306108860
+check 'may 23 2011 0:1:2'		1306108862
+
+# now with times and timezones
+check '23 may 2011 edt'			1306123200
+check '23 may 2011 gmt'			1306108800
+
+# formats from date(1)
+check 'Sun, 14 Jun 2020 22:08:48 -0700'	1592197728
+check 'Sun, 14 Jun 2020 -0700'		1592118000
+check '2020-06-14'			1592092800
+check '2020-06-14T22:14:17-07:00'	1592198057
+
+# colloquial american formats (eww)
+check '06/14/2020'			1592092800
+
+exit ''
--- /dev/null
+++ b/cmd/mkfile
@@ -1,0 +1,6 @@
+</$objtype/mkfile
+
+TEST=\
+	date
+
+<../regress
\ No newline at end of file
--- /dev/null
+++ b/libc/date.c
@@ -1,0 +1,236 @@
+#include <u.h>
+#include <libc.h>
+
+int failed;
+
+/*
+ * For debugging
+ */
+void
+printtm(Tm *tm)
+{
+	fprint(2, "abs=%lld sec=%d min=%d hour=%d mday=%d mon=%d"
+		" year=%d day=%d yday=%d zone=%s tzoff=%d\n",
+		tm->abs, /* milliseconds since Jan 1 1970, GMT */
+		tm->sec, /* seconds (range 0..59) */
+		tm->min, /* minutes (0..59) */
+		tm->hour,     /* hours (0..23) */
+		tm->mday,     /* day of the month (1..31) */
+		tm->mon, /* month of the year (0..11) */
+		tm->year,     /* year A.D. - 1900 */
+		tm->wday,     /* day of week (0..6, Sunday = 0) */
+		tm->yday,     /* day of year (0..365) */
+		tm->zone,   /* time zone name */
+		tm->tzoff);    /* time   zone delta from GMT */
+}
+
+void
+fail(char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	fprint(2, "failed: ");
+	vfprint(2, fmt, ap);
+	va_end(ap);
+	failed++;
+}
+
+void
+testtm(int i, int year, int mon, int mday, int hour, int min, int sec, Tm *tm){
+	if(tm->year != year-1900) fail("%d wrong year expected=%d actual=%d\n", i, year, tm->year);
+	if(tm->mon != mon)	fail("%d wrong month expected=%d actual=%d\n", i, mon, tm->mon);
+	if(tm->mday != mday)	fail("%d wrong mday expected=%d actual=%d\n", i, mday, tm->mday);
+	if(tm->hour != hour)	fail("%d wrong hour expected=%d actual=%d\n", i, hour, tm->hour);
+	if(tm->min != min)	fail("%d wrong min expected=%d actual=%d\n", i, min, tm->min);
+	if(tm->sec != sec)	fail("%d wrong sec expected=%d actual=%d\n", i, sec, tm->sec);
+}
+
+void
+main(int, char **)
+{
+	Tm tm, tt;
+	Tzone *gmt, *us_arizona, *us_eastern;
+	Tm here, there;
+	Tzone *zl, *zp;
+	char buf[1024];
+	int i;
+
+	tmfmtinstall();
+	if((gmt = tmgetzone("GMT")) == nil)
+		sysfatal("nil gmt: %r\n");
+	if((us_arizona = tmgetzone("US_Arizona")) == nil)
+		sysfatal("nil us_arizona: %r\n");
+	if((us_eastern = tmgetzone("US_Eastern")) == nil)
+		sysfatal("nil us_eastern: %r\n");
+
+	if((zl = tmgetzone("local")) == nil)
+	     sysfatal("load zone: %r\n");
+	if((zp = tmgetzone("US_Pacific")) == nil)
+	     sysfatal("load zone: %r\n");
+	if(tmnow(&here, zl) == nil)
+	     sysfatal("get time: %r\n");
+	if(tmtime(&there, here.abs, zp) == nil)
+	     sysfatal("shift time: %r\n");
+
+	tmtime(&tm, 1586574870, gmt);
+	testtm(1, 2020, 3, 11, 3, 14, 30, &tm);
+	tmtime(&tm, 1586574870, us_arizona);
+	testtm(1, 2020, 3, 10, 20, 14, 30, &tm);
+
+	tmtime(&tm, 0, gmt);
+	testtm(3, 1970, 0, 1, 0, 0, 0, &tm);
+	tmnorm(&tm);
+	testtm(4, 1970, 0, 1, 0, 0, 0, &tm);
+
+	tmtime(&tm, 84061, gmt);
+	testtm(5, 1970, 0, 1, 23, 21, 1, &tm);
+	tmnorm(&tm);
+	testtm(6, 1970, 0, 1, 23, 21, 1, &tm);
+
+	tmtime(&tm, 1586574870, us_arizona);
+	testtm(7, 2020, 3, 10, 20, 14, 30, &tm);
+	tmnorm(&tm);
+	testtm(8, 2020, 3, 10, 20, 14, 30, &tm);
+
+	tmtime(&tm, 1586574870, us_eastern);
+	testtm(9, 2020, 3, 10, 23, 14, 30, &tm);
+	tmnorm(&tm);
+	testtm(10, 2020, 3, 10, 23, 14, 30, &tm);
+
+	if(tmparse(&tm, "hhmm", "1600", gmt) == nil)
+		sysfatal("failed parse: %r\n");
+	testtm(99, 1970, 0, 1, 16, 0, 0, &tm);
+
+	if(tmparse(&tm, "YYYY-MM-DD hh:mm:ss Z", "1969-12-31 16:00:00 -0800", nil) == nil)
+		fail("parse failed: %r\n");
+	if(tm.abs != 0)
+		fail("wrong result: %lld != 0\n", tm.abs);
+
+	if(tmparse(&tm, "YYYY MM DD", "1990,01,03", nil) == nil)
+		fail("comma parse failed");
+	if(tm.abs != 631324800)
+		fail("wrong result");
+	if(tmparse(&tm, "YYYY MM DD", "1990 ,\t01,03", nil) == nil)
+		fail("comma parse failed");
+	if(tm.abs != 631324800)
+		fail("wrong result");
+
+	if(tmparse(&tm, "YYYY MM DD hh:mm:ss", "1969 12 31 16:00:00", gmt) == nil)
+		sysfatal("failed parse: %r\n");
+	testtm(100, 1969, 11, 31, 16, 0, 0, &tm);
+
+	if(tmparse(&tm, "YYYY MM DD hh:mm:ss", "1970 01 01 04:00:00", gmt) == nil)
+	fail("failed parse: %r\n");
+	testtm(101, 1970, 0, 1, 4, 0, 0, &tm);
+
+	if(tmparse(&tm, "YYYY MM DD", "1970 01 01", gmt) == nil)
+	fail("failed parse: %r\n");
+	testtm(102, 1970, 0, 1, 0, 0, 0, &tm);
+
+	if(tmparse(&tm, "YYYY MMMM DD WW hh:mm:ss",	 "2020 April 10 Friday 16:04:00", gmt) == nil)
+		sysfatal("failed parse: %r\n");
+	testtm(103, 2020, 3, 10, 16, 4, 0, &tm);
+
+	if(tmparse(&tm, "MM DD hh:mm:ss", "12 31 16:00:00", gmt) == nil)
+		sysfatal("failed parse: %r\n");
+	testtm(104, 1970, 11, 31, 16, 0, 0, &tm);
+
+	if(tmparse(&tm, "MM DD h:mm:ss", "12 31 4:00:00", gmt) == nil)
+		sysfatal("failed parse: %r\n");
+	testtm(105, 1970, 11, 31, 4, 0, 0, &tm);
+	if(tm.tzoff != 0) print("%d wrong tzoff expected=%d actual=%d\n", 6, 0, tm.tzoff);
+
+	if(tmparse(&tm, "YYYY MM DD hh:mm:ss", "2020 04 10 23:14:30", us_eastern) == nil)
+	fail("failed parse: %r\n");
+	testtm(106, 2020, 3, 10, 23, 14, 30, &tm);
+	tmtime(&tm, tm.abs, nil);
+
+	if(tmparse(&tm, "YYYY MM DD hh:mm:ss", "2020 04 10 20:14:30", us_arizona) == nil)
+		fail("failed parse: %r\n");
+	testtm(108, 2020, 3, 10, 20, 14, 30, &tm);
+
+	if(tmparse(&tm, "YYYY MM DD hh:mm:ss ZZZ", "2020 04 10 20:14:30 EST", us_arizona) == nil)
+		fail("failed parse: %r\n");
+	testtm(108, 2020, 3, 10, 17, 14, 30, &tm);
+
+	if(tmparse(&tm, "YYYY MM DD hh:mm:ss ZZZ", "2020 04 10 20:14:30 -0400", nil) == nil)
+		fail("failed parse: %r\n");
+	testtm(108, 2020, 3, 10, 20, 14, 30, &tm);
+	snprint(buf, sizeof(buf), "%τ", tmfmt(&tm, "YYYY MM DD hh:mm:ss ZZZ"));
+	if(strcmp(buf, "2020 04 10 20:14:30 -0400") != 0)
+		fail("failed format: %s != 2020 04 10 20:14:30 -0400", buf);
+
+	/* edge case: leap year feb 29 */
+	if(tmparse(&tm, "YYYY MM DD hh:mm:ss ZZZ", "2020 02 29 20:14:30 -0400", nil) == nil)
+		fail("failed leap year feb 29: %r\n");
+	testtm(109, 2020, 1, 29, 20, 14, 30, &tm);
+	if(tmparse(&tm, "YYYY MM DD hh:mm:ss ZZZ", "2021 02 29 20:14:30 -0400", nil) != nil)
+		fail("incorrectly accepted non-leap year feb 29\n");
+
+	/* lots of round trips: Jan 1960 => Jun 2020, in almost-11 day increments */
+	for(i = -315619200; i < 1592179806; i += 23*3600 + 1732){
+		if(tmtime(&tm, i, nil) == nil)
+			fail("load time %d\n", i);
+		if(tm.abs != i)
+			fail("wrong load time: %d\n", i);
+		if(snprint(buf, sizeof(buf), "%τ", tmfmt(&tm, "W MMM DD hh:mm:ss Z YYYY")) == -1)
+			fail("format: %r\n");
+		if(tmparse(&tt, "W MMM DD hh:mm:ss Z YYYY", buf, nil) == nil)
+			fail("parse: %r\n");
+		if(tm.abs != tt.abs)
+			fail("parse: wrong time (%lld != %lld)\n", tm.abs, tt.abs);
+	}
+
+	/* lots of round trips: Jan 1960 => Jun 2020, in almost-dailyincrements, now with timezone */
+	for(i = -315619200; i < 1592179806; i += 23*3600 + 1732){
+		if(tmtime(&tm, i, us_eastern) == nil)
+			fail("load time %d\n", i);
+		if(tm.abs != i)
+			fail("wrong load time: %d\n", i);
+		if(snprint(buf, sizeof(buf), "%τ", tmfmt(&tm, "W MMM DD hh:mm:ss Z YYYY")) == -1)
+			fail("format: %r\n");
+		if(tmparse(&tt, "W MMM DD hh:mm:ss Z YYYY", buf, us_arizona) == nil)
+			fail("parse: %r\n");
+		if(tm.abs != tt.abs)
+			fail("parse: wrong time (%lld != %lld)\n", tm.abs, tt.abs);
+	}
+
+	if(tmtime(&tm, -624623143, nil) == nil)
+		fail("tmtime: %r");
+	if(snprint(buf, sizeof(buf), "%τ", tmfmt(&tm, "W, DD MMM YYYY hh:mm:ss Z")) == -1)
+		fail("format: %r");
+	if(strcmp(buf, "Fri, 17 Mar 1950 13:34:17 +0000") != 0)
+		fail("wrong output: %s\n", buf);
+	if(tmtime(&tm, -624623143, us_eastern) == nil)
+		fail("tmtime: %r");
+	if(snprint(buf, sizeof(buf), "%τ", tmfmt(&tm, "W, DD MMM YYYY hh:mm:ss Z")) == -1)
+		fail("format: %r");
+	if(strcmp(buf, "Fri, 17 Mar 1950 08:34:17 -0500") != 0)
+		fail("wrong output: %s\n", buf);
+
+	/* flexible date parsing */
+	if(tmparse(&tm, "?YYYY ?MM DD hh:mm:ss ?ZZZ", "89 04 10 20:14:30 -0400", nil) == nil)
+		fail("failed parse: %r\n");
+	testtm(200, 1989, 3, 10, 20, 14, 30, &tm);
+	char **d, *flexdates[] = {
+		"2020 4 10 20:14:30 -0400",
+		"2020 04 10 20:14:30 -0400",
+		"2020 Apr 10 20:14:30 -0400",
+		"2020 Apr 10 20:14:30 -04:00"
+		"2020 Apr 10 20:14:30 -04:00",
+		"2020 Apr 10 20:14:30 -04:00",
+		"2020 April 10 20:14:30 EDT",
+		"20 April 10 20:14:30 EDT",
+		nil,
+	};
+	for(d = flexdates; *d; d++){
+		if(tmparse(&tm, "?YYYY ?MM DD hh:mm:ss ?ZZZ", "2020 04 10 20:14:30 -0400", nil) == nil)
+			fail("failed parse: %r\n");
+		testtm(201, 2020, 3, 10, 20, 14, 30, &tm);
+	}
+
+	if(failed)
+		exits("test failed");
+	exits(nil);
+}
--- /dev/null
+++ b/libc/mkfile
@@ -1,0 +1,6 @@
+</$objtype/mkfile
+
+TEST=\
+	date\
+
+<../regress
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,7 @@
+</$objtype/mkfile
+
+TEST=\
+	cmd\
+	libc\
+
+<./regress
--- /dev/null
+++ b/regress
@@ -1,0 +1,25 @@
+all:VQ:
+	echo $t
+	for(t in $TEST) @{
+		if(test -d $t)
+			@{cd $t && mk $MKFLAGS all}
+		if not
+			mk $t.test
+	}
+
+%.test:V: $O.%
+	./$O.$stem
+
+%.test:V: %.rc
+	./$stem.rc
+
+%.$O:	$HFILES		# don't combine with following %.$O rules
+
+%.$O:	%.c
+	$CC $CFLAGS $stem.c
+
+%.$O:	%.s
+	$AS $AFLAGS $stem.s
+
+$O.%:	%.$O $OFILES $LIB
+	$LD $LDFLAGS -o $target $prereq