]> git.lizzy.rs Git - plan9front.git/commitdiff
libc: reverting previous change until ori can fix it
authorcinap_lenrek <cinap_lenrek@felloff.net>
Sun, 14 Jun 2020 02:47:22 +0000 (04:47 +0200)
committercinap_lenrek <cinap_lenrek@felloff.net>
Sun, 14 Jun 2020 02:47:22 +0000 (04:47 +0200)
sys/include/libc.h
sys/man/2/tmdate [deleted file]
sys/src/cmd/seconds.c
sys/src/libc/9sys/mkfile
sys/src/libc/port/date.c [deleted file]
sys/src/libc/port/gmtime.c [deleted file]
sys/src/libc/port/mkfile

index 820d684b2278668a115fc5a4e290bf679a79559b..7a270053970a17c3e42aeaca34024ab422e0c653 100644 (file)
@@ -314,45 +314,22 @@ extern    double  fmod(double, double);
 /*
  * Time-of-day
  */
-typedef struct Tzone Tzone;
-#pragma incomplete Tzone
-
 
 typedef
 struct Tm
 {
-       vlong   abs;            /* seconds since Jan 1 1970, GMT */
-       int     nsec;           /* nseconds (range 0...1e9) */
-       int     sec;            /* seconds (range 0..60) */
-       int     min;            /* minutes (0..59) */
-       int     hour;           /* hours (0..23) */
-       int     mday;           /* day of the month (1..31) */
-       int     mon;            /* month of the year (0..11) */
-       int     year;           /* year A.D. */
-       int     wday;           /* day of week (0..6, Sunday = 0) */
-       int     yday;           /* day of year (0..365) */
-       char    zone[16];       /* time zone name */
-       int     tzoff;          /* time zone delta from GMT */
-       Tzone   *tz;            /* time zone associated with this date */
+       int     sec;
+       int     min;
+       int     hour;
+       int     mday;
+       int     mon;
+       int     year;
+       int     wday;
+       int     yday;
+       char    zone[4];
+       int     tzoff;
 } Tm;
 
-typedef
-struct Tmfmt {
-       char    *fmt;
-       Tm      *tm;
-} Tmfmt;
-
-#pragma varargck       type    "τ"    Tmfmt
-
-extern Tzone*  tmgetzone(char *name);
-extern Tm*     tmnow(Tm*, Tzone*);
-extern Tm*     tmtime(Tm*, vlong, Tzone*);
-extern Tm*     tmtimens(Tm*, vlong, int, Tzone*);
-extern Tm*     tmparse(Tm*, char*, char*, Tzone*);
-extern Tm*     tmnorm(Tm*);
-extern Tmfmt   tmfmt(Tm*, char*);
-extern void    tmfmtinstall(void);
-
 extern Tm*     gmtime(long);
 extern Tm*     localtime(long);
 extern char*   asctime(Tm*);
diff --git a/sys/man/2/tmdate b/sys/man/2/tmdate
deleted file mode 100644 (file)
index 127a4e1..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-.TH TMDATE 2
-.SH NAME
-tmnow, tmgetzone, tmtime, tmparse, tmfmt, tmnorm, - convert date and time
-.SH SYNOPSIS
-.B #include <u.h>
-.br
-.B #include <libc.h>
-.PP
-.ft L
-.nf
-.EX
-typedef struct Tmd Tmd;
-typedef struct Tmfmt Tmfmt;
-
-struct {
-       vlong   abs;    /* seconds since Jan 1 1970, UTC */
-       int     nsec;   /* nanoseconds (range 0..1e9) */
-       int     sec;    /* seconds (range 0..59) */
-       int     min;    /* minutes (0..59) */
-       int     hour;   /* hours (0..23) */
-       int     mday;   /* day of the month (1..31) */
-       int     mon;    /* month of the year (0..11) */
-       int     year;   /* C.E year - 1900 */
-       int     wday;   /* day of week (0..6, Sunday = 0) */
-       int     yday;   /* day of year (0..365) */
-       char    zone[]; /* time zone name */
-       int     tzoff;  /* time zone delta from GMT, seconds */
-};
-
-Tzone *tmgetzone(char *name);
-Tm    *tmnow(Tm *tm, char *tz);
-Tm    *tmtime(Tm *tm, vlong abs, Tzone *tz);
-Tm    *tmtimens(Tm *tm, vlong abs, int ns, Tzone *tz);
-Tm    *tmparse(Tm *dst, char *fmt, char *tm, Tzone *zone);
-void   tmnorm(Tm *tm);
-Tmfmt  tmfmt(Tm *tm, char *fmt);
-void   tmfmtinstall(void);
-.EE
-.SH DESCRIPTION
-.PP
-This family of functions handles simple date and time manipulation.
-Times are represented as an absolute instant in time, combined with a time zone.
-.PP
-Time zones are loaded by as name.
-They can be specified as the abbreviated timezone name,
-the full timezone name, the path to a timezone file,
-or an absolute offset in the HHMM form.
-.PP
-When given as a timezone, any instant-dependent adjustments such as leap
-seconds and daylight savings time will be applied to the derived fields of
-struct tm, but will not affect the absolute time.
-The time zone name local always refers to the time in /env/timezone.
-The nil timezone always refers to GMT.
-.PP
-Tmgetzone loads a timezone by name. The returned timezone is
-cached for the lifetime of the program, and should not be freed.
-Loading a timezone repeatedly by name loads from the cache, and
-does not leak.
-.PP
-Tmnow gets the current time of day in the requested time zone.
-.PP
-Tmtime converts the millisecond-resolution timestamp 'abs'
-into a Tm struct in the requested timezone.
-Tmtimens does the same, but with a nanosecond accuracy.
-.PP
-Tmstime is identical to tmtime, but accepts the time in sec-
-onds.
-.PP
-Tmparse parses a time from a string according to the format argument.
-The result is returned in the timezone requested.
-If there is a timezone in the date, and a timezone is provided
-when parsing, then the zone is shifted to the provided timezone.
-Parsing is case-insensitive.
-.PP
-The format argument contains zero or more of the following components:
-.TP
-.B Y, YY, YYYY
-Represents the year.
-.I YY
-prints the year in 2 digit form.
-.TP
-.B M, MM, MMM, MMMM
-The month of the year, in unpadded numeric, padded numeric, short name, or long name,
-respectively.
-.TP
-.B D, DD
-The day of month in unpadded or padded numeric form, respectively.
-.TP
-.B W, WW
-The day of week in short or long name form, respectively.
-.TP
-.B h, hh
-The hour in unpadded or padded form, respectively
-.TP
-.B m, mm
-The minute in unpadded or padded form, respectively
-.TP
-.B s, ss
-The second in unpadded or padded form, respectively
-.TP
-.B z, Z, ZZ
-The timezone in named, [+-]HHMM and [+-]HH:MM form, respectively
-.TP
-.B a, A
-Lower and uppercase 'am' and 'pm' specifiers, respectively.
-.TP
-.B [...]
-Quoted text, copied directly to the output.
-.TP
-.B _
-When formatting, this inserts padding into the date format.
-The padded width of a field is the sum of format and specifier
-characters combined.
-For example,
-.I __h
-will format to a width of 3.
-.TP
-.B ?
-When parsing, this makes the following argument match fuzzily.
-Fuzzy matching means that all formats are tried, from most to least specific.
-For example, 
-.I ?M
-will match 
-.IR January ,
-.IR Jan ,
-.IR 01 ,
-and 
-.IR 1 ,
-in that order of preference.
-.TP
-.B ~
-When parsing a date, this slackens range enforcement, accepting
-out of range values such as January
-.IR 32 ,
-which would get normalized to February 1st.
-.PP
-Any characters not specified above are copied directly to output,
-without modification.
-
-
-
-.PP
-If the format argument is nil, it makes an
-attempt to parse common human readable date formats.  These
-formats include ISO-8601,RFC-3339 and RFC-2822 dates.
-.
-.PP
-Tmfmt produces a format description structure suitable for passing
-to
-.IR fmtprint (2) .
-If  fmt is nil, we default to the format used in
-.IR ctime (2).
-The format of the format string is identical to
-.IR tmparse.
-
-.PP
-When parsing, any amount of whitespace is treated as a single token.
-All string matches are case insensitive, and zero padding is optional.
-
-.PP
-Tmnorm takes a manually adjusted Tm structure, and recal-
-culates the absolute time from the
-.I year, mon, mday, hr, min
-and
-.I sec
-fields. Other fields are ignored.
-This recalculation respects the time zone stored in struct tm.
-Out of range values are wrapped. For example, December 32nd
-becomes January 1st.
-
-.PP
-Tmfmtinstall installs a time format specifier %τ. The time
-format behaves as in tmfmt
-
-.SH Examples
-.PP
-All examples assume tmfmtinstall has been called.
-.PP
-Get the current date in the local timezone, UTC, and
-US_Pacific time. Print it using the default format.
-
-.IP
-.EX
-Tm t;
-Tzone *zl, *zp;
-if((zl = tmgetzone("local") == nil)
-       sysfatal("load zone: %r");
-if((zp = tmgetzone("US_Pacific") == nil)
-       sysfatal("load zone: %r");
-print("local: %τ\\n", tmfmt(tmnow(&t, zl), nil));
-print("gmt: %τ\\n", tmfmt(tmnow(&t, nil), nil));
-print("eastern: %τ\\n", tmfmt(tmnow(&t, zp), nil));
-.EE
-.PP
-Compare if two times are the same, regardless of timezone.
-
-.IP
-.EX
-Tm a, b;
-
-tmparse(&a, nil, "Tue Dec 10 12:36:00 PST 2019");
-tmparse(&b, nil, "Tue Dec 10 15:36:00 EST 2019");
-if(a.abs == b.abs)
-       print("same\\n");
-else
-       print("different\\n");
-.EE
-
-.PP
-Convert from one timezone to another.
-
-.IP
-.EX
-Tm here, there;
-Tzone *zl, *zp;
-if((zl = tmgetzone("local")) == nil)
-       sysfatal("load zone: %r");
-if((zp = tmgetzone("US_Pacific")) == nil)
-       sysfatal("load zone: %r");
-if(tmnow(&here, zl) == nil)
-       sysfatal("get time: %r");
-if(tmtime(&there, here.abs, zp) == nil)
-       sysfatal("shift time: %r");
-.EE
-
-.PP
-Add a day to two times. Because we picked daylight savings
-time to adjust over, only 23 hours are added.
-
-.EX
-Tm t;
-tmparse(&t, "W MMM D hh:mm:ss z YYYY, "Sun Nov 2 13:11:11 PST 2019");
-tm.day++;
-tmrecalc(&t);
-print("%τ", &t); /*  Mon Nov 3 13:11:11 PST 2019 */
-.EE
-
-.SH BUGS
-.PP
-There is no way to format specifier for subsecond precision.
-.PP
-The timezone information that we ship is out of date.
-.PP
-The plan 9 timezone format can't express leap seconds.
index 2c5fc333372216ae414ff49be211d8a0967915f3..69e243301a0e8e70682e54ba83d0d9bb484724ae 100644 (file)
+/*
+ * seconds absolute_date ... - convert absolute_date to seconds since epoch
+ */
+
 #include <u.h>
 #include <libc.h>
+#include <ctype.h>
+
+typedef ulong Time;
+
+enum {
+       AM, PM, HR24,
+
+       /* token types */
+       Month = 1,
+       Year,
+       Day,
+       Timetok,
+       Tz,
+       Dtz,
+       Ignore,
+       Ampm,
+
+       Maxtok          = 6, /* only this many chars are stored in datetktbl */
+       Maxdateflds     = 25,
+};
 
 /*
- * seconds absolute_date ... - convert absolute_date to seconds since epoch
+ * macros for squeezing values into low 7 bits of "value".
+ * all timezones we care about are divisible by 10, and the largest value
+ * (780) when divided is 78.
  */
-char *formats[] = {
-       /* asctime */
-       "W MMM DD hh:mm:ss ?Z YYYY",
-       /* RFC5322 */
-       "?W ?DD ?MMM ?YYYY hh:mm:ss ?Z",
-       "?W, DD-?MM-YY hh:mm:ss ?Z",
-       /* RFC822/RFC8222 */
-       "DD MMM YY hh:mm ZZZ",
-       "DD MMM YY hh:mm Z",
-       /* RFC850 */
-       "W, DD-MMM-YY hh:mm:ss MST",
-       /* RFC1123 */
-       "WW, DD MMM YYYY hh:mm:ss ZZZ",
-       /* RFC1123Z */
-       "WW, DD MMM YYYY hh:mm:ss ZZ",
-       /* RFC3339 */
-       "YYYY-MM-DD[T]hh:mm:ss[Z]ZZ",
-       "YYYY-MM-DD[T]hh:mm:ss[Z]Z",
-       "YYYY-MM-DD[T]hh:mm:ss ZZ",
-       "YYYY-MM-DD[T]hh:mm:ss Z",
-       /* RFC 3339 and human-readable variants */
-       "YYYY-MM-DD hh:mm:ss",
-       "YYYY-MM-DD hh:mm:ss ?Z",
-       "YYYY-MM-DD [@] hh:mm:ss",
-       "YYYY-MM-DD [@] hh:mm:ss ?Z",
-       nil
-};
+#define TOVAL(tp, v)   ((tp)->value = (v) / 10)
+#define FROMVAL(tp)    ((tp)->value * 10)      /* uncompress */
+
+/* keep this struct small since we have an array of them */
+typedef struct {
+       char    token[Maxtok];
+       char    type;
+       schar   value;
+} Datetok;
+
+int dtok_numparsed;
+
+/* forwards */
+Datetok        *datetoktype(char *s, int *bigvalp);
+
+static Datetok datetktbl[];
+static unsigned szdatetktbl;
+
+/* parse 1- or 2-digit number, advance *cpp past it */
+static int
+eatnum(char **cpp)
+{
+       int c, x;
+       char *cp;
+
+       cp = *cpp;
+       c = *cp;
+       if (!isascii(c) || !isdigit(c))
+               return -1;
+       x = c - '0';
+
+       c = *++cp;
+       if (isascii(c) && isdigit(c)) {
+               x = 10*x + c - '0';
+               cp++;
+       }
+       *cpp = cp;
+       return x;
+}
+
+/* return -1 on failure */
+int
+parsetime(char *time, Tm *tm)
+{
+       tm->hour = eatnum(&time);
+       if (tm->hour == -1 || *time++ != ':')
+               return -1;                      /* only hour; too short */
+
+       tm->min = eatnum(&time);
+       if (tm->min == -1)
+               return -1;
+       if (*time++ != ':') {
+               tm->sec = 0;
+               return 0;                       /* no seconds; okay */
+       }
+
+       tm->sec = eatnum(&time);
+       if (tm->sec == -1)
+               return -1;
+
+       /* this may be considered too strict.  garbage at end of time? */
+       return *time == '\0' || isascii(*time) && isspace(*time)? 0: -1;
+}
+
+/*
+ * try to parse pre-split timestr in fields as an absolute date
+ */
+int
+tryabsdate(char **fields, int nf, Tm *now, Tm *tm)
+{
+       int i, mer = HR24, bigval = -1;
+       long flg = 0, ty;
+       Datetok *tp;
+
+       now = localtime(time(0));       /* default to local time (zone) */
+       tm->tzoff = now->tzoff;
+       strncpy(tm->zone, now->zone, sizeof tm->zone);
+
+       tm->mday = tm->mon = tm->year = -1;     /* mandatory */
+       tm->hour = tm->min = tm->sec = 0;
+       dtok_numparsed = 0;
+
+       for (i = 0; i < nf; i++) {
+               if (fields[i][0] == '\0')
+                       continue;
+               tp = datetoktype(fields[i], &bigval);
+               ty = (1L << tp->type) & ~(1L << Ignore);
+               if (flg & ty)
+                       return -1;              /* repeated type */
+               flg |= ty;
+               switch (tp->type) {
+               case Year:
+                       tm->year = bigval;
+                       if (tm->year < 1970 || tm->year > 2106)
+                               return -1;      /* can't represent in ulong */
+                       /* convert 4-digit year to 1900 origin */
+                       if (tm->year >= 1900)
+                               tm->year -= 1900;
+                       break;
+               case Day:
+                       tm->mday = bigval;
+                       break;
+               case Month:
+                       tm->mon = tp->value - 1; /* convert to zero-origin */
+                       break;
+               case Timetok:
+                       if (parsetime(fields[i], tm) < 0)
+                               return -1;
+                       break;
+               case Dtz:
+               case Tz:
+                       /* tm2sec mangles timezones, so we do our own handling */
+                       tm->tzoff = FROMVAL(tp);
+                       snprint(tm->zone, sizeof(tm->zone), "GMT");
+                       break;
+               case Ignore:
+                       break;
+               case Ampm:
+                       mer = tp->value;
+                       break;
+               default:
+                       return -1;      /* bad token type: CANTHAPPEN */
+               }
+       }
+       if (tm->year == -1 || tm->mon == -1 || tm->mday == -1)
+               return -1;              /* missing component */
+       if (mer == PM)
+               tm->hour += 12;
+       return 0;
+}
+
+int
+prsabsdate(char *timestr, Tm *now, Tm *tm)
+{
+       int nf;
+       char *fields[Maxdateflds];
+       static char delims[] = "- \t\n/,";
+
+       nf = gettokens(timestr, fields, nelem(fields), delims+1);
+       if (nf > nelem(fields))
+               return -1;
+       if (tryabsdate(fields, nf, now, tm) < 0) {
+               char *p = timestr;
+
+               /*
+                * could be a DEC-date; glue it all back together, split it
+                * with dash as a delimiter and try again.  Yes, this is a
+                * hack, but so are DEC-dates.
+                */
+               while (--nf > 0) {
+                       while (*p++ != '\0')
+                               ;
+                       p[-1] = ' ';
+               }
+               nf = gettokens(timestr, fields, nelem(fields), delims);
+               if (nf > nelem(fields) || tryabsdate(fields, nf, now, tm) < 0)
+                       return -1;
+       }
+       return 0;
+}
+
+int
+validtm(Tm *tm)
+{
+       if (tm->year < 0 || tm->mon < 0 || tm->mon > 11 ||
+           tm->mday < 1 || tm->hour < 0 || tm->hour >= 24 ||
+           tm->min < 0 || tm->min > 59 ||
+           tm->sec < 0 || tm->sec > 61)        /* allow 2 leap seconds */
+               return 0;
+       return 1;
+}
+
+Time
+seconds(char *timestr)
+{
+       Tm date;
+
+       memset(&date, 0, sizeof date);
+       if (prsabsdate(timestr, localtime(time(0)), &date) < 0)
+               return -1;
+       return validtm(&date)? tm2sec(&date) - 60*date.tzoff: -1;
+}
+
+int
+convert(char *timestr)
+{
+       char *copy;
+       Time tstime;
+
+       copy = strdup(timestr);
+       if (copy == nil)
+               sysfatal("out of memory");
+       tstime = seconds(copy);
+       free(copy);
+       if (tstime == -1) {
+               fprint(2, "%s: `%s' not a valid date\n", argv0, timestr);
+               return 1;
+       }
+       print("%lud\n", tstime);
+       return 0;
+}
 
 static void
 usage(void)
@@ -42,31 +242,225 @@ usage(void)
 void
 main(int argc, char **argv)
 {
-       Tm tm;
-       char **f, *fmt;
-       int i;
+       int i, sts;
 
-       fmt = nil;
+       sts = 0;
        ARGBEGIN{
-       case 'f':
-               fmt = EARGF(usage());
-               break;
        default:
                usage();
-       }ARGEND;
-
-       for(i = 0; i < argc; i++){
-               if(fmt != nil){
-                       if(tmparse(&tm, fmt, argv[i], nil) != nil)
-                               goto Found;
-               }else{
-                       for(f = formats; *f != nil; f++)
-                               if(tmparse(&tm, *f, argv[i], nil) != nil)
-                                       goto Found;
+       }ARGEND
+       if (argc == 0)
+               usage();
+       for (i = 0; i < argc; i++)
+               sts |= convert(argv[i]);
+       exits(sts != 0? "bad": 0);
+}
+
+/*
+ * Binary search -- from Knuth (6.2.1) Algorithm B.  Special case like this
+ * is WAY faster than the generic bsearch().
+ */
+Datetok *
+datebsearch(char *key, Datetok *base, unsigned nel)
+{
+       int cmp;
+       Datetok *last = base + nel - 1, *pos;
+
+       while (last >= base) {
+               pos = base + ((last - base) >> 1);
+               cmp = key[0] - pos->token[0];
+               if (cmp == 0) {
+                       cmp = strncmp(key, pos->token, Maxtok);
+                       if (cmp == 0)
+                               return pos;
                }
-               sysfatal("tmparse: %r");
-Found:
-               print("%lld\n", tm.abs);
+               if (cmp < 0)
+                       last = pos - 1;
+               else
+                       base = pos + 1;
        }
-       exits(nil);
+       return 0;
 }
+
+Datetok *
+datetoktype(char *s, int *bigvalp)
+{
+       char *cp = s;
+       char c = *cp;
+       static Datetok t;
+       Datetok *tp = &t;
+
+       if (isascii(c) && isdigit(c)) {
+               int len = strlen(cp);
+
+               if (len > 3 && (cp[1] == ':' || cp[2] == ':'))
+                       tp->type = Timetok;
+               else {
+                       if (bigvalp != nil)
+                               *bigvalp = atoi(cp); /* won't fit in tp->value */
+                       if (len == 4)
+                               tp->type = Year;
+                       else if (++dtok_numparsed == 1)
+                               tp->type = Day;
+                       else
+                               tp->type = Year;
+               }
+       } else if (c == '-' || c == '+') {
+               int val = atoi(cp + 1);
+               int hr =  val / 100;
+               int min = val % 100;
+
+               val = hr*60 + min;
+               TOVAL(tp, c == '-'? -val: val);
+               tp->type = Tz;
+       } else {
+               char lowtoken[Maxtok+1];
+               char *ltp = lowtoken, *endltp = lowtoken+Maxtok;
+
+               /* copy to lowtoken to avoid modifying s */
+               while ((c = *cp++) != '\0' && ltp < endltp)
+                       *ltp++ = (isascii(c) && isupper(c)? tolower(c): c);
+               *ltp = '\0';
+               tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
+               if (tp == nil) {
+                       tp = &t;
+                       tp->type = Ignore;
+               }
+       }
+       return tp;
+}
+
+
+/*
+ * to keep this table reasonably small, we divide the lexval for Tz and Dtz
+ * entries by 10 and truncate the text field at MAXTOKLEN characters.
+ * the text field is not guaranteed to be NUL-terminated.
+ */
+static Datetok datetktbl[] = {
+/*     text            token   lexval */
+       "acsst",        Dtz,    63,     /* Cent. Australia */
+       "acst",         Tz,     57,     /* Cent. Australia */
+       "adt",          Dtz,    -18,    /* Atlantic Daylight Time */
+       "aesst",        Dtz,    66,     /* E. Australia */
+       "aest",         Tz,     60,     /* Australia Eastern Std Time */
+       "ahst",         Tz,     60,     /* Alaska-Hawaii Std Time */
+       "am",           Ampm,   AM,
+       "apr",          Month,  4,
+       "april",        Month,  4,
+       "ast",          Tz,     -24,    /* Atlantic Std Time (Canada) */
+       "at",           Ignore, 0,      /* "at" (throwaway) */
+       "aug",          Month,  8,
+       "august",       Month,  8,
+       "awsst",        Dtz,    54,     /* W. Australia */
+       "awst",         Tz,     48,     /* W. Australia */
+       "bst",          Tz,     6,      /* British Summer Time */
+       "bt",           Tz,     18,     /* Baghdad Time */
+       "cadt",         Dtz,    63,     /* Central Australian DST */
+       "cast",         Tz,     57,     /* Central Australian ST */
+       "cat",          Tz,     -60,    /* Central Alaska Time */
+       "cct",          Tz,     48,     /* China Coast */
+       "cdt",          Dtz,    -30,    /* Central Daylight Time */
+       "cet",          Tz,     6,      /* Central European Time */
+       "cetdst",       Dtz,    12,     /* Central European Dayl.Time */
+       "cst",          Tz,     -36,    /* Central Standard Time */
+       "dec",          Month,  12,
+       "decemb",       Month,  12,
+       "dnt",          Tz,     6,      /* Dansk Normal Tid */
+       "dst",          Ignore, 0,
+       "east",         Tz,     -60,    /* East Australian Std Time */
+       "edt",          Dtz,    -24,    /* Eastern Daylight Time */
+       "eet",          Tz,     12,     /* East. Europe, USSR Zone 1 */
+       "eetdst",       Dtz,    18,     /* Eastern Europe */
+       "est",          Tz,     -30,    /* Eastern Standard Time */
+       "feb",          Month,  2,
+       "februa",       Month,  2,
+       "fri",          Ignore, 5,
+       "friday",       Ignore, 5,
+       "fst",          Tz,     6,      /* French Summer Time */
+       "fwt",          Dtz,    12,     /* French Winter Time  */
+       "gmt",          Tz,     0,      /* Greenwish Mean Time */
+       "gst",          Tz,     60,     /* Guam Std Time, USSR Zone 9 */
+       "hdt",          Dtz,    -54,    /* Hawaii/Alaska */
+       "hmt",          Dtz,    18,     /* Hellas ? ? */
+       "hst",          Tz,     -60,    /* Hawaii Std Time */
+       "idle",         Tz,     72,     /* Intl. Date Line, East */
+       "idlw",         Tz,     -72,    /* Intl. Date Line, West */
+       "ist",          Tz,     12,     /* Israel */
+       "it",           Tz,     22,     /* Iran Time */
+       "jan",          Month,  1,
+       "januar",       Month,  1,
+       "jst",          Tz,     54,     /* Japan Std Time,USSR Zone 8 */
+       "jt",           Tz,     45,     /* Java Time */
+       "jul",          Month,  7,
+       "july",         Month,  7,
+       "jun",          Month,  6,
+       "june",         Month,  6,
+       "kst",          Tz,     54,     /* Korea Standard Time */
+       "ligt",         Tz,     60,     /* From Melbourne, Australia */
+       "mar",          Month,  3,
+       "march",        Month,  3,
+       "may",          Month,  5,
+       "mdt",          Dtz,    -36,    /* Mountain Daylight Time */
+       "mest",         Dtz,    12,     /* Middle Europe Summer Time */
+       "met",          Tz,     6,      /* Middle Europe Time */
+       "metdst",       Dtz,    12,     /* Middle Europe Daylight Time*/
+       "mewt",         Tz,     6,      /* Middle Europe Winter Time */
+       "mez",          Tz,     6,      /* Middle Europe Zone */
+       "mon",          Ignore, 1,
+       "monday",       Ignore, 1,
+       "mst",          Tz,     -42,    /* Mountain Standard Time */
+       "mt",           Tz,     51,     /* Moluccas Time */
+       "ndt",          Dtz,    -15,    /* Nfld. Daylight Time */
+       "nft",          Tz,     -21,    /* Newfoundland Standard Time */
+       "nor",          Tz,     6,      /* Norway Standard Time */
+       "nov",          Month,  11,
+       "novemb",       Month,  11,
+       "nst",          Tz,     -21,    /* Nfld. Standard Time */
+       "nt",           Tz,     -66,    /* Nome Time */
+       "nzdt",         Dtz,    78,     /* New Zealand Daylight Time */
+       "nzst",         Tz,     72,     /* New Zealand Standard Time */
+       "nzt",          Tz,     72,     /* New Zealand Time */
+       "oct",          Month,  10,
+       "octobe",       Month,  10,
+       "on",           Ignore, 0,      /* "on" (throwaway) */
+       "pdt",          Dtz,    -42,    /* Pacific Daylight Time */
+       "pm",           Ampm,   PM,
+       "pst",          Tz,     -48,    /* Pacific Standard Time */
+       "sadt",         Dtz,    63,     /* S. Australian Dayl. Time */
+       "sast",         Tz,     57,     /* South Australian Std Time */
+       "sat",          Ignore, 6,
+       "saturd",       Ignore, 6,
+       "sep",          Month,  9,
+       "sept",         Month,  9,
+       "septem",       Month,  9,
+       "set",          Tz,     -6,     /* Seychelles Time ?? */
+       "sst",          Dtz,    12,     /* Swedish Summer Time */
+       "sun",          Ignore, 0,
+       "sunday",       Ignore, 0,
+       "swt",          Tz,     6,      /* Swedish Winter Time  */
+       "thu",          Ignore, 4,
+       "thur",         Ignore, 4,
+       "thurs",        Ignore, 4,
+       "thursd",       Ignore, 4,
+       "tue",          Ignore, 2,
+       "tues",         Ignore, 2,
+       "tuesda",       Ignore, 2,
+       "ut",           Tz,     0,
+       "utc",          Tz,     0,
+       "wadt",         Dtz,    48,     /* West Australian DST */
+       "wast",         Tz,     42,     /* West Australian Std Time */
+       "wat",          Tz,     -6,     /* West Africa Time */
+       "wdt",          Dtz,    54,     /* West Australian DST */
+       "wed",          Ignore, 3,
+       "wednes",       Ignore, 3,
+       "weds",         Ignore, 3,
+       "wet",          Tz,     0,      /* Western Europe */
+       "wetdst",       Dtz,    6,      /* Western Europe */
+       "wst",          Tz,     48,     /* West Australian Std Time */
+       "ydt",          Dtz,    -48,    /* Yukon Daylight Time */
+       "yst",          Tz,     -54,    /* Yukon Standard Time */
+       "zp4",          Tz,     -24,    /* GMT +4  hours. */
+       "zp5",          Tz,     -30,    /* GMT +5  hours. */
+       "zp6",          Tz,     -36,    /* GMT +6  hours. */
+};
+static unsigned szdatetktbl = nelem(datetktbl);
index 2f33a149a3cad52201491286ea2317e0a056a72e..686a7bd49c6731dc235bcff76bf4d6bc0756851e 100644 (file)
@@ -10,6 +10,7 @@ OFILES=\
        convM2S.$O\
        convS2M.$O\
        cputime.$O\
+       ctime.$O\
        dial.$O\
        dirfstat.$O\
        dirfwstat.$O\
@@ -46,6 +47,7 @@ OFILES=\
        sysname.$O\
        time.$O\
        times.$O\
+       tm2sec.$O\
        truerand.$O\
        wait.$O\
        waitpid.$O\
diff --git a/sys/src/libc/port/date.c b/sys/src/libc/port/date.c
deleted file mode 100644 (file)
index 3f06c18..0000000
+++ /dev/null
@@ -1,872 +0,0 @@
-#include <u.h>
-#include <libc.h>
-
-typedef struct Tzabbrev Tzabbrev;
-typedef struct Tzoffpair Tzoffpair;
-
-#define Ctimefmt "W MMM _D hh:mm:ss ZZZ YYYY\n"
-enum {
-       Tzsize          = 150,
-       Nsec            = 1000*1000*1000,
-       Daysec          = (vlong)24*3600,
-       Days400y        = 365*400 + 4*25 - 3,
-       Days4y          = 365*4 + 1,
-};
-
-enum {
-       Cend,
-       Cspace,
-       Cnum,
-       Cletter,
-       Cpunct,
-};
-       
-struct Tzone {
-       char    tzname[16];
-       char    stname[4];
-       char    dlname[4];
-       long    stdiff;
-       long    dldiff;
-       long    dlpairs[Tzsize];
-};
-
-static char tfmt[128];
-static QLock zlock;
-static int nzones;
-static Tzone **zones;
-static int mdays[] = {
-       31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-static char *wday[] = {
-       "Sunday","Monday","Tuesday",
-       "Wednesday","Thursday","Friday",
-       "Saturday", nil,
-};
-static char *month[] = {
-       "January", "February", "March",
-       "April", "May", "June", "July",
-       "August", "September", "October",
-       "November", "December", nil
-};
-
-struct Tzabbrev {
-       char *abbr;
-       char *name;
-};
-
-struct Tzoffpair {
-       char *abbr;
-       int off;
-};
-
-/* Obsolete time zone names. Hardcoded to match RFC5322 */
-static Tzabbrev tzabbrev[] = {
-       {"UT", "GMT"}, {"GMT", "GMT"}, {"UTC", "GMT"},
-       {"EST", "US_Eastern"}, {"EDT", "US_Eastern"},
-       {"CST", "US_Central"}, {"CDT", "US_Central"},
-       {"MST", "US_Mountain"}, {"MDT", "US_Mountain"},
-       {"PST", "US_Pacific"}, {"PDT", "US_Pacific"},
-       {nil},
-};
-
-/* Military timezone names */
-static Tzoffpair milabbrev[] = {
-       {"A", -1*3600},   {"B", -2*3600},   {"C", -3*3600},
-       {"D", -4*3600},   {"E", -5*3600},   {"F", -6*3600},
-       {"G", -7*3600},   {"H", -8*3600},   {"I", -9*3600},
-       {"K", -10*3600},  {"L", -11*3600},  {"M", -12*3600},
-       {"N", +1*3600},   {"O", +2*3600},   {"P", +3*3600},
-       {"Q", +4*3600},   {"R", +5*3600},   {"S", +6*3600},
-       {"T", +7*3600},   {"U", +8*3600},   {"V", +9*3600},
-       {"W", +10*3600},  {"X", +11*3600}, {"Y", +12*3600},
-       {"Z",   0}, {nil, 0}
-};
-
-static int
-isleap(int y)
-{
-       return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
-}
-
-static int
-rdname(char **f, char *p)
-{
-       int c, i;
-
-       while((c = *(*f)++) != 0)
-               if(c != ' ' && c != '\n')
-                       break;
-       for(i=0; i<3; i++) {
-               if(c == ' ' || c == '\n')
-                       return 1;
-               *p++ = c;
-               c = *(*f)++;
-       }
-       if(c != ' ' && c != '\n')
-               return 1;
-       *p = 0;
-       return 0;
-}
-
-static int
-rdlong(char **f, long *p)
-{
-       int c, s;
-       long l;
-
-       s = 0;
-       while((c = *(*f)++) != 0){
-               if(c == '-')
-                       s++;
-               else if(c != ' ' && c != '\n')
-                       break;
-       }
-       if(c == 0) {
-               *p = 0;
-               return 0;
-       }
-       l = 0;
-       for(;;) {
-               if(c == ' ' || c == '\n')
-                       break;
-               if(c < '0' || c > '9')
-                       return 1;
-               l = l*10 + c-'0';
-               c = *(*f)++;
-       }
-       if(s)
-               l = -l;
-       *p = l;
-       return 0;
-}
-
-static int
-loadzone(Tzone *tz, char *name)
-{
-       char buf[Tzsize*11+30], path[128], *p;
-       int i, f, r;
-
-       if(strcmp(name, "local") == 0)
-               snprint(path, sizeof(path), "/env/timezone");
-       else
-               snprint(path, sizeof(path), "/adm/timezone/%s", name);
-       memset(buf, 0, sizeof(buf));
-       if((f = open(path, 0)) == -1)
-               return -1;
-       r = read(f, buf, sizeof(buf));
-       close(f);
-       if(r == sizeof(buf) || r == -1)
-               return -1;
-       p = buf;
-       if(rdname(&p, tz->stname))
-               return -1;
-       if(rdlong(&p, &tz->stdiff))
-               return -1;
-       if(rdname(&p, tz->dlname))
-               return -1;
-       if(rdlong(&p, &tz->dldiff))
-               return -1;
-       for(i=0; i < Tzsize; i++) {
-               if(rdlong(&p, &tz->dlpairs[i]))
-                       return -1;
-               if(tz->dlpairs[i] == 0)
-                       return 0;
-       }
-       return -1;
-}
-
-Tzone*
-tmgetzone(char *tzname)
-{
-       Tzone *tz, **newzones;
-       int i;
-
-       if(tzname == nil)
-               tzname = "GMT";
-       qlock(&zlock);
-       for(i = 0; i < nzones; i++){
-               tz = zones[i];
-               if(strcmp(tz->stname, tzname) == 0)
-                       goto found;
-               if(strcmp(tz->dlname, tzname) == 0)
-                       goto found;
-               if(strcmp(tz->tzname, tzname) == 0)
-                       goto found;
-       }
-
-       tz = malloc(sizeof(Tzone));
-       if(tz == nil)
-               goto error;
-       newzones = realloc(zones, (nzones + 1) * sizeof(Tzone*));
-       if(newzones == nil)     
-               goto error;
-       if(loadzone(tz, tzname) != 0)
-               goto error;
-       if(snprint(tz->tzname, sizeof(tz->tzname), tzname) >= sizeof(tz->tzname)){
-               werrstr("timezone name too long");
-               return nil;
-       }
-       zones = newzones;
-       zones[nzones] = tz;
-       nzones++;
-found:
-       qunlock(&zlock);
-       return tz;
-error:
-       free(tz);
-       qunlock(&zlock);
-       return nil;
-}
-
-static void
-getzoneoff(Tzone *tz, vlong abs, Tm *tm)
-{
-       long dl, *p;
-       dl = 0;
-       if(tz == nil){
-               snprint(tm->zone, sizeof(tm->zone), "GMT");
-               tm->tzoff = 0;
-               return;
-       }
-       for(p = tz->dlpairs; *p; p += 2)
-               if(abs >= p[0] && abs < p[1])
-                       dl = 1;
-       if(dl){
-               snprint(tm->zone, sizeof(tm->zone), tz->dlname);
-               tm->tzoff = tz->dldiff;
-       }else{
-               snprint(tm->zone, sizeof(tm->zone), tz->stname);
-               tm->tzoff = tz->stdiff;
-       }
-}
-
-static Tm*
-tmfill(Tm *tm, vlong abs, vlong nsec)
-{
-       vlong zrel, j, y, m, d, t, e;
-       int i;
-
-       tm->abs = abs;
-       zrel = abs + tm->tzoff;
-       t = zrel % Daysec;
-       e = zrel / Daysec;
-       if(t < 0){
-               t += Daysec;
-               e -= 1;
-       }
-
-       t += nsec/Nsec;
-       tm->sec = t % 60;
-       t /= 60;
-       tm->min = t % 60;
-       t /= 60;
-       tm->hour = t;
-       tm->wday = (e + 4) % 7;
-
-       /*
-        * Split up year, month, day.
-        * 
-        * Implemented according to "Algorithm 199,
-        * conversions between calendar  date and
-        * Julian day number", Robert G. Tantzen,
-        * Air Force Missile Development
-        * Center, Holloman AFB, New Mex.
-        * 
-        * Lots of magic.
-        */
-       j = (zrel + 2440588 * Daysec) / (Daysec) - 1721119;
-       y = (4 * j - 1) / Days400y;
-       j = 4 * j - 1 - Days400y * y;
-       d = j / 4;
-       j = (4 * d + 3) / Days4y;
-       d = 4 * d + 3 - Days4y * j;
-       d = (d + 4) / 4 ;
-       m = (5 * d - 3) / 153;
-       d = 5 * d - 3 - 153 * m;
-       d = (d + 5) / 5;
-       y = 100 * y + j;
-
-       if(m < 10)
-               m += 3;
-       else{
-               m -= 9;
-               y++;
-       }
-
-       /* there's no year 0 */
-       if(y <= 0)
-               y--;
-       /* and if j negative, the day and month are also negative */
-       if(m < 0)
-               m += 12;
-       if(d < 0)
-               d += mdays[m - 1];
-
-       tm->yday = d;
-       for(i = 0; i < m - 1; i++)
-               tm->yday += mdays[i];
-       if(m > 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
-               tm->yday++;
-       tm->year = y - 1900;
-       tm->mon = m - 1;
-       tm->mday = d;
-       tm->nsec = nsec%Nsec;
-       return tm;
-}      
-
-
-Tm*
-tmtime(Tm *tm, vlong abs, Tzone *tz)
-{
-       return tmtimens(tm, abs, 0, tz);
-}
-
-Tm*
-tmtimens(Tm *tm, vlong abs, int ns, Tzone *tz)
-{
-       tm->tz = tz;
-       getzoneoff(tz, abs, tm);
-       return tmfill(tm, abs, ns);
-}
-
-Tm*
-tmnow(Tm *tm, Tzone *tz)
-{
-       vlong ns;
-
-       ns = nsec();
-       return tmtimens(tm, nsec()/Nsec, ns%Nsec, tz);
-}
-
-Tm*
-tmnorm(Tm *tm)
-{
-       vlong c, yadj, j, abs, y, m, d;
-
-       if(tm->mon > 1){
-               m = tm->mon - 2;
-               y = tm->year + 1900;
-       }else{
-               m = tm->mon + 10;
-               y = tm->year - 1901;
-       }
-       d = tm->mday;
-       c = y / 100;
-       yadj = y - 100 * c;
-       j = (c * Days400y / 4 + 
-               Days4y * yadj / 4 +
-               (153 * m + 2)/5 + d -
-               719469);
-       abs = j * Daysec;
-       abs += tm->hour * 3600;
-       abs += tm->min * 60;
-       abs += tm->sec;
-       abs -= tm->tzoff;
-       return tmfill(tm, abs, tm->nsec);
-}
-
-static int
-τconv(Fmt *f)
-{
-       int depth, n, w, h, m, c0, sgn, pad, off;
-       char *p, *am;
-       Tmfmt tf;
-       Tm *tm;
-
-       n = 0;
-       tf = va_arg(f->args, Tmfmt);
-       tm = tf.tm;
-       p = tf.fmt;
-       if(p == nil)
-               p = Ctimefmt;
-       while(*p){
-               w = 1;
-               pad = 0;
-               while(*p == '_'){
-                       pad++;
-                       p++;
-               }
-               c0 = *p++;
-               while(c0 && *p == c0){
-                       w++;
-                       p++;
-               }
-               pad += w;
-               switch(c0){
-               case 0:
-                       break;
-               case 'Y':
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*d", pad, tm->year + 1900);          break;
-                       case 2: n += fmtprint(f, "%*d", pad, tm->year % 100);           break;
-                       case 4: n += fmtprint(f, "%*d", pad, tm->year + 1900);          break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'M':
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*d", pad, tm->mon + 1);              break;
-                       case 2: n += fmtprint(f, "%*s%02d", pad-2, "", tm->mon + 1);    break;
-                       case 3: n += fmtprint(f, "%*.3s", pad, month[tm->mon]);         break;
-                       case 4: n += fmtprint(f, "%*s", pad, month[tm->mon]);           break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'D':
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*d", pad, tm->mday);                 break;
-                       case 2: n += fmtprint(f, "%*s%02d", pad-2, "", tm->mday);               break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'W':
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*.3s", pad, wday[tm->wday]); break;
-                       case 2: n += fmtprint(f, "%*s", pad, wday[tm->wday]);           break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'H':
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*d", pad, tm->hour % 12);            break;
-                       case 2: n += fmtprint(f, "%*s%02d", pad-2, "", tm->hour % 12);  break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'h':
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*d", pad, tm->hour);                 break;
-                       case 2: n += fmtprint(f, "%*s%02d", pad-2, "", tm->hour);       break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'm':
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*d", pad, tm->min);                  break;
-                       case 2: n += fmtprint(f, "%*s%02d", pad-2, "", tm->min);        break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 's':
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*d", pad, tm->sec);                  break;
-                       case 2: n += fmtprint(f, "%*s%02d", pad-2, "", tm->sec);        break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'z':
-                       if(w != 1)
-                               goto badfmt;
-               case 'Z':
-                       sgn = (tm->tzoff < 0) ? '-' : '+';
-                       off = (tm->tzoff < 0) ? -tm->tzoff : tm->tzoff;
-                       h = off/3600;
-                       m = (off/60)%60;
-                       if(w < 3 && pad < 5)
-                               pad = 5;
-                       switch(w){
-                       case 1: n += fmtprint(f, "%*s%c%02d%02d", pad-5, "", sgn, h, m); break;
-                       case 2: n += fmtprint(f, "%*s%c%02d:%02d", pad-5, "", sgn, h, m); break;
-                       case 3: n += fmtprint(f, "%*s", pad, tm->zone);                  break;
-                       }
-                       break;
-               case 'A':
-               case 'a':
-                       if(w != 1)
-                               goto badfmt;
-                       if(c0 == 'a')
-                               am = (tm->hour < 12) ? "am" : "pm";
-                       else
-                               am = (tm->hour < 12) ? "AM" : "PM";
-                       n += fmtprint(f, "%*s", pad, am);
-                       break;
-               case '[':
-                       depth = 1;
-                       while(*p){
-                               if(*p == '[')
-                                       depth++;
-                               if(*p == ']')
-                                       depth--;
-                               if(*p == '\\')
-                                       p++;
-                               if(depth == 0)
-                                       break;
-                               fmtrune(f, *p++);
-                       }
-                       if(*p++ != ']')
-                               goto badfmt;
-                       break;
-               default:
-                       n += fmtrune(f, c0);
-                       break;
-               }
-       }
-       return n;
-badfmt:
-       werrstr("garbled format %s", tf.fmt);
-       return -1;                      
-}
-
-static int
-getnum(char **ps, int maxw, int *ok)
-{
-       char *s, *e;
-       int n;
-
-       n = 0;
-       e = *ps + maxw;
-       for(s = *ps; s != e && *s >= '0' && *s <= '9'; s++){
-               n *= 10;
-               n += *s - '0';
-       }
-       *ok = s != *ps;
-       *ps = s;
-       return n;
-}
-
-static int
-lookup(char **s, char **tab, int len, int *ok)
-{
-       int nc, i;
-
-       *ok = 0;
-       for(i = 0; *tab; tab++){
-               nc = (len != -1) ? len : strlen(*tab);
-               if(cistrncmp(*s, *tab, nc) == 0){
-                       *s += nc;
-                       *ok = 1;
-                       return i;
-               }
-               i++;
-       }
-       *ok = 0;
-       return -1;
-}
-
-Tm*
-tmparse(Tm *tm, char *fmt, char *str, Tzone *tz)
-{
-       int depth, w, c0, zs, z0, z1, ampm, zoned, sloppy, tzo, ok;
-       char *s, *p, *q;
-       Tzone *zparsed;
-       Tzabbrev *a;
-       Tzoffpair *m;
-
-       p = fmt;
-       s = str;
-       tzo = 0;
-       ampm = -1;
-       zoned = 0;
-       zparsed = nil;
-       sloppy = 0;
-       /* Default all fields */
-       tmtime(tm, 0, nil);
-       if(*p == '~'){
-               sloppy = 1;
-               p++;
-       }
-       while(*p){
-               w = 1;
-               c0 = *p++;
-               if(c0 == '?'){
-                       w = -1;
-                       c0 = *p++;
-               }
-               while(*p == c0){
-                       if(w != -1) w++;
-                       p++;
-               }
-               ok = 1;
-               switch(c0){
-               case 'Y':
-                       switch(w){
-                       case -1:
-                               tm->year = getnum(&s, 4, &ok);
-                               if(tm->year > 100) tm->year -= 1900;
-                               break;
-                       case 1: tm->year = getnum(&s, 4, &ok) - 1900;   break;
-                       case 2: tm->year = getnum(&s, 2, &ok);          break;
-                       case 3:
-                       case 4: tm->year = getnum(&s, 4, &ok) - 1900;   break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'M':
-                       switch(w){
-                       case -1:
-                               tm->mon = getnum(&s, 2, &ok) - 1;
-                               if(!ok) tm->mon = lookup(&s, month, -1, &ok);
-                               if(!ok) tm->mon = lookup(&s, month, 3, &ok);
-                               break;
-                       case 1:
-                       case 2: tm->mon = getnum(&s, 2, &ok) - 1;       break;
-                       case 3: tm->mon = lookup(&s, month, 3, &ok);    break;
-                       case 4: tm->mon = lookup(&s, month, -1, &ok);   break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'D':
-                       switch(w){
-                       case -1:
-                       case 1:
-                       case 2: tm->mday = getnum(&s, 2, &ok);          break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'W':
-                       switch(w){
-                       case -1:
-                               tm->wday = lookup(&s, wday, -1, &ok);
-                               if(!ok) tm->wday = lookup(&s, wday, 3, &ok);
-                               break;
-                       case 1: tm->wday = lookup(&s, wday, 3, &ok);    break;
-                       case 2: tm->wday = lookup(&s, wday, -1, &ok);   break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'h':
-                       switch(w){
-                       case -1:
-                       case 1:
-                       case 2: tm->hour = getnum(&s, 2, &ok);          break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'm':
-                       switch(w){
-                       case -1:
-                       case 1:
-                       case 2: tm->min = getnum(&s, 2, &ok);           break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 's':
-                       switch(w){
-                       case -1:
-                       case 1:
-                       case 2: tm->sec = getnum(&s, 2, &ok);           break;
-                       default: goto badfmt;
-                       }
-                       break;
-               case 'z':
-                       if(w != 1)
-                               goto badfmt;
-               case 'Z':
-                       zs = 0;
-                       zoned = 1;
-                       switch(*s++){
-                       case '+': zs = 1; break;
-                       case '-': zs = -1; break;
-                       default: s--; break;
-                       }
-                       switch(w){
-                       case -1:
-                       case 3:
-                               for(a = tzabbrev; a->abbr; a++)
-                                       if(strncmp(s, a->abbr, strlen(a->abbr)) == 0)
-                                               break;
-                               if(a->abbr != nil){
-                                       s += strlen(a->abbr);
-                                       zparsed = tmgetzone(a->name);
-                                       if(zparsed == nil){
-                                               werrstr("unloadable zone %s (%s)", a->abbr, a->name);
-                                               return nil;
-                                       }
-                                       break;
-                               }
-                               for(m = milabbrev; m->abbr != nil; m++)
-                                       if(strncmp(s, m->abbr, strlen(m->abbr)) == 0)
-                                               break;
-                               if(m->abbr != nil){
-                                       snprint(tm->zone, sizeof(tm->zone), "%s", m->abbr);
-                                       tzo = m->off;
-                                       break;
-                               }
-                               /* fall through */
-                       case 1:
-                               /* offset: [+-]hhmm */
-                               q = s;
-                               z0 = getnum(&s, 4, &ok);
-                               if(s - q == 4){
-                                       z1 = z0 % 100;
-                                       if(z0/100 > 13 || z1 >= 60)
-                                               goto baddate;
-                                       tzo = zs*(3600*z0/100 + 60*z1);
-                                       snprint(tm->zone, sizeof(tm->zone), "%c%02d%02d", zs<0?'-':'+', z0/100, z1);
-                                       break;
-                               }
-                               if(w != -1)
-                                       goto baddate;
-                               s = q;
-                               /* fall through */
-                       case 2:
-                               /* offset: [+-]hh:mm */
-                               z0 = getnum(&s, 2, &ok);
-                               if(*s++ != ':')
-                                       goto baddate;
-                               z1 = getnum(&s, 2, &ok);
-                               if(z1 > 60)
-                                       goto baddate;
-                               tzo = zs*(3600*z0 + 60*z1);
-                               snprint(tm->zone, sizeof(tm->zone), "%c%d02:%02d", zs<0?'-':'+', z0, z1);
-                               break;
-                       }
-                       break;
-               case 'A':
-               case 'a':
-                       if(cistrncmp(s, "am", 2) == 0)
-                               ampm = 0;
-                       else if(cistrncmp(s, "pm", 2) == 0)
-                               ampm = 1;
-                       else
-                               goto baddate;
-                       break;
-               case '[':
-                       depth = 1;
-                       while(*p){
-                               if(*p == '[')
-                                       depth++;
-                               if(*p == ']')
-                                       depth--;
-                               if(*p == '\\')
-                                       p++;
-                               if(depth == 0)
-                                       break;
-                               if(*s == 0)
-                                       goto baddate;
-                               if(*s++ != *p++)
-                                       goto baddate;
-                       }
-                       if(*p != ']')
-                               goto badfmt;
-                       p++;
-                       break;
-               case ',':
-               case ' ':
-               case '\t':
-                       if(*s != ' ' && *s != '\t' && *s != ',')
-                               goto baddate;
-                       while(*p == ' ' || *p == '\t' || *p == ',')
-                               p++;
-                       while(*s == ' ' || *s == '\t' || *s == ',')
-                               s++;
-                       break;
-               default:
-                       if(*s == 0)
-                               goto baddate;
-                       if(*s++ != c0)
-                               goto baddate;
-                       break;
-               }
-               if(!ok)
-                       goto baddate;
-       }
-       
-       if(!sloppy && ampm != -1 && tm->hour > 12)
-               goto baddate;
-       if(ampm == 1)
-               tm->hour += 12;
-       /*
-        * If we're allowing sloppy date ranges,
-        * we'll normalize out of range values.
-        */
-       if(!sloppy){
-               if(tm->yday < 0 && tm->yday > 365 + isleap(tm->year + 1900))
-                       goto baddate;
-               if(tm->wday < 0 && tm->wday > 6)
-                       goto baddate;
-               if(tm->mon < 0 || tm->mon > 11)
-                       goto baddate;
-               if(tm->mday < 0 || tm->mday > mdays[tm->mon])
-                       goto baddate;
-               if(tm->hour < 0 || tm->hour > 24)
-                       goto baddate;
-               if(tm->min < 0 || tm->min > 59)
-                       goto baddate;
-               if(tm->sec < 0 || tm->sec > 60)
-                       goto baddate;
-               if(tm->nsec < 0 || tm->nsec > Nsec)
-                       goto baddate;
-       }
-
-       /*
-        * Normalizing gives us the local time,
-        * but because we havnen't applied the
-        * timezone, we think we're GMT. So, we
-        * need to shift backwards. Then, we move
-        * the "GMT that was local" back to local
-        * time.
-        */
-       tmnorm(tm);
-       tm->tzoff = tzo;
-       if(!zoned)
-               getzoneoff(tz, tm->abs, tm);
-       else if(zparsed != nil)
-               getzoneoff(zparsed, tm->abs, tm);
-       tm->abs -= tm->tzoff;
-       if(tz != nil || !zoned)
-               tmtime(tm, tm->abs, tz);
-       return tm;
-baddate:
-       werrstr("invalid date %s near '%s'", str, s);
-       return nil;
-badfmt:
-       werrstr("garbled format %s near '%s'", fmt, p);
-       return nil;                     
-}
-
-Tmfmt
-tmfmt(Tm *d, char *fmt)
-{
-       return (Tmfmt){fmt, d};
-}
-
-void
-tmfmtinstall(void)
-{
-       fmtinstall(L'τ', τconv);
-}
-
-/* These legacy functions need access to τconv */
-static char*
-dotmfmt(Fmt *f, ...)
-{
-       static char buf[30];
-       va_list ap;
-
-       va_start(ap, f);
-       f->runes = 0;
-       f->start = buf;
-       f->to = buf;
-       f->stop = buf + sizeof(buf) - 1;
-       f->flush = nil;
-       f->farg = nil;
-       f->nfmt = 0;
-       f->args = ap;
-       τconv(f);
-       va_end(ap);
-       buf[sizeof(buf) - 1] = 0;
-       return buf;
-}
-
-char*
-asctime(Tm* tm)
-{
-       Tmfmt tf;
-       Fmt f;
-
-       tf = tmfmt(tm, nil);
-       return dotmfmt(&f, tf);
-}
-
-char*
-ctime(long abs)
-{
-       Tzone *tz;
-       Tm tm;
-
-       /* No error checking: the API doesn't allow it. */
-       tz = tmgetzone("local");
-       tmtime(&tm, abs, tz);
-       return asctime(&tm);
-}
diff --git a/sys/src/libc/port/gmtime.c b/sys/src/libc/port/gmtime.c
deleted file mode 100644 (file)
index c13234c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#include<u.h>
-#include <libc.h>
-
-Tm*
-gmtime(long abs)
-{
-       static Tm tm;
-       return tmtime(&tm, abs, nil);
-}
-
-Tm*
-localtime(long abs)
-{
-       Tzone *tz;
-       static Tm tm;
-
-       /* No error checking: the API doesn't allow it. */
-       tz = tmgetzone("local");
-       return tmtime(&tm, abs, tz);
-}
-
-long
-tm2sec(Tm *tm)
-{
-       tmnorm(tm);
-       return tm->abs;
-}
index 8c9eb05748ecb4652f085a538025826324bf5bf4..4029904220c7787c3a9809f816230e1b8ace4757 100644 (file)
@@ -20,7 +20,6 @@ CFILES=\
        cleanname.c\
        crypt.c\
        ctype.c\
-       date.c\
        encodefmt.c\
        execl.c\
        exits.c\
@@ -33,7 +32,6 @@ CFILES=\
        getcallerpc.c\
        getfields.c\
        getuser.c\
-       gmtime.c\
        hangup.c\
        hypot.c\
        lnrand.c\