summaryrefslogtreecommitdiff
path: root/sys/src/libc/9sys/tm2sec.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2020-06-15 00:12:57 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2020-06-15 00:12:57 +0200
commitfebe84af755d8b6941c6e59c1b350f889c4fccb0 (patch)
tree45cb13daa2c1ef116613a7e461e0c59fda1d5bd6 /sys/src/libc/9sys/tm2sec.c
parent8b3efcfc4e3b38eab3f0ff503e573c072ff890f5 (diff)
libc: revert date change again. this is getting ridicuoulus.
this breaks the sample from the seconds manpage, and overall produces funky results. this needs alot more testing. term% seconds '23 may 2011' seconds: tmparse: invalid date 23 may 2011 near 'may 2011' term% seconds '2019-01-01 00:00:00' -118370073600
Diffstat (limited to 'sys/src/libc/9sys/tm2sec.c')
-rw-r--r--sys/src/libc/9sys/tm2sec.c197
1 files changed, 195 insertions, 2 deletions
diff --git a/sys/src/libc/9sys/tm2sec.c b/sys/src/libc/9sys/tm2sec.c
index 96d4c3d61..20bebd0c8 100644
--- a/sys/src/libc/9sys/tm2sec.c
+++ b/sys/src/libc/9sys/tm2sec.c
@@ -1,9 +1,202 @@
#include <u.h>
#include <libc.h>
+#define TZSIZE 150
+static void readtimezone(void);
+static int rd_name(char**, char*);
+static int rd_long(char**, long*);
+static
+struct
+{
+ char stname[4];
+ char dlname[4];
+ long stdiff;
+ long dldiff;
+ long dlpairs[TZSIZE];
+} timezone;
+
+#define SEC2MIN 60L
+#define SEC2HOUR (60L*SEC2MIN)
+#define SEC2DAY (24L*SEC2HOUR)
+
+/*
+ * days per month plus days/year
+ */
+static int dmsize[] =
+{
+ 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+static int ldmsize[] =
+{
+ 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * return the days/month for the given year
+ */
+static int *
+yrsize(int y)
+{
+ if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
+ return ldmsize;
+ else
+ return dmsize;
+}
+
+/*
+ * compute seconds since Jan 1 1970 GMT
+ * and convert to our timezone.
+ */
long
tm2sec(Tm *tm)
{
- tmnorm(tm);
- return tm->abs;
+ long secs, *p;
+ int i, yday, year, *d2m;
+
+ if(strcmp(tm->zone, "GMT") != 0 && timezone.stname[0] == 0)
+ readtimezone();
+ secs = 0;
+
+ /*
+ * seconds per year
+ */
+ year = tm->year + 1900;
+ for(i = 1970; i < year; i++){
+ d2m = yrsize(i);
+ secs += d2m[0] * SEC2DAY;
+ }
+
+ /*
+ * if mday is set, use mon and mday to compute yday
+ */
+ if(tm->mday){
+ yday = 0;
+ d2m = yrsize(year);
+ for(i=0; i<tm->mon; i++)
+ yday += d2m[i+1];
+ yday += tm->mday-1;
+ }else{
+ yday = tm->yday;
+ }
+ secs += yday * SEC2DAY;
+
+ /*
+ * hours, minutes, seconds
+ */
+ secs += tm->hour * SEC2HOUR;
+ secs += tm->min * SEC2MIN;
+ secs += tm->sec;
+
+ /*
+ * Only handles zones mentioned in /env/timezone,
+ * but things get too ambiguous otherwise.
+ */
+ if(strcmp(tm->zone, timezone.stname) == 0)
+ secs -= timezone.stdiff;
+ else if(strcmp(tm->zone, timezone.dlname) == 0)
+ secs -= timezone.dldiff;
+ else if(tm->zone[0] == 0){
+ secs -= timezone.dldiff;
+ for(p = timezone.dlpairs; *p; p += 2)
+ if(secs >= p[0] && secs < p[1])
+ break;
+ if(*p == 0){
+ secs += timezone.dldiff;
+ secs -= timezone.stdiff;
+ }
+ }
+ return secs;
+}
+
+static
+void
+readtimezone(void)
+{
+ char buf[TZSIZE*11+30], *p;
+ int i;
+
+ memset(buf, 0, sizeof(buf));
+ i = open("/env/timezone", 0);
+ if(i < 0)
+ goto error;
+ if(read(i, buf, sizeof(buf)) >= sizeof(buf))
+ goto error;
+ close(i);
+ p = buf;
+ if(rd_name(&p, timezone.stname))
+ goto error;
+ if(rd_long(&p, &timezone.stdiff))
+ goto error;
+ if(rd_name(&p, timezone.dlname))
+ goto error;
+ if(rd_long(&p, &timezone.dldiff))
+ goto error;
+ for(i=0; i<TZSIZE; i++) {
+ if(rd_long(&p, &timezone.dlpairs[i]))
+ goto error;
+ if(timezone.dlpairs[i] == 0)
+ return;
+ }
+
+error:
+ timezone.stdiff = 0;
+ strcpy(timezone.stname, "GMT");
+ timezone.dlpairs[0] = 0;
+}
+
+static int
+rd_name(char **f, char *p)
+{
+ int c, i;
+
+ for(;;) {
+ c = *(*f)++;
+ 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
+rd_long(char **f, long *p)
+{
+ int c, s;
+ long l;
+
+ s = 0;
+ for(;;) {
+ c = *(*f)++;
+ if(c == '-') {
+ s++;
+ continue;
+ }
+ 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;
}