diff options
Diffstat (limited to 'appl/svc/webget/date.b')
| -rw-r--r-- | appl/svc/webget/date.b | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/appl/svc/webget/date.b b/appl/svc/webget/date.b new file mode 100644 index 00000000..71248954 --- /dev/null +++ b/appl/svc/webget/date.b @@ -0,0 +1,266 @@ +implement Date; + +include "sys.m"; + sys: Sys; + +include "daytime.m"; + daytime : Daytime; + +Tm: import daytime; + +include "date.m"; + + # print dates in the format + # Wkd, DD Mon YYYY HH:MM:SS GMT + # parse dates of formats + # Wkd, DD Mon YYYY HH:MM:SS GMT + # Weekday, DD-Mon-YY HH:MM:SS GMT + # Wkd Mon ( D|DD) HH:MM:SS YYYY + # plus anything similar + +SEC2MIN: con 60; +SEC2HOUR: con (60*SEC2MIN); +SEC2DAY: con (24*SEC2HOUR); + +# days per month plus days/year + +dmsize := array[] of { + 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +ldmsize := array[] of { + 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + + +# return the days/month for the given year + + +weekdayname := array[] of { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" +}; + +wdayname := array[] of { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + + +monname := array[] of { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +init() +{ + daytime = load Daytime Daytime->PATH; + sys = load Sys "$Sys"; + if (daytime==nil) + sys->print("daytime load: %r\n"); +} + +# internals.... +dateindex : fn(nil: string, nill:array of string): int; +gmtm2sec : fn(tm: Tm): int; + + +yrsize(yr : int): array of int { + if(yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)) + return ldmsize; + else + return dmsize; +} + +tolower(c: int): int { + if(c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + return c; +} + + +isalpha(c: int): int{ + return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'; +} + + +isdig(c: int): int { + return c >= '0' && c <= '9'; +} + + +dateconv(t: int): string { + tm : ref Tm; + tm = daytime->gmt(t); + return sys->sprint("%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT", + wdayname[tm.wday], tm.mday, monname[tm.mon], tm.year+1900, + tm.hour, tm.min, tm.sec); +} + + +dateword(date : string): (string,string) { + p : string; + i:=0; + p = ""; + while((i<len date) && !isalpha(date[i]) && !isdig(date[i])) + i++; + while((i<len date) && isalpha(date[i])){ + p[len p] = tolower(date[i]); + i++; + } + rest := ""; + if(i < len date) + rest = date[i:]; + return (rest,p); +} + + +datenum(date : string): (string, int){ + n, i : int; + i=0; + while((i<len date) && !isdig(date[i])) + i++; + if(i == len date) + return (nil, -1); + n = 0; + while((i<len date) && isdig(date[i])){ + n = n * 10 + date[i] - '0'; + i++; + } + return (date[i:], n); +} + + + # parse a date and return the seconds since the epoch + # return 0 for a failure + +# could be big? +date2sec(date : string): int { + tm : Tm; + buf : string; + + # Weekday|Wday + + (date,buf) = dateword(date); + tm.wday = dateindex(buf, wdayname); + if(tm.wday < 0) + tm.wday = dateindex(buf, weekdayname); + + if(tm.wday < 0) + return 0; + + # check for the two major formats + + (date,buf) = dateword(date); + tm.mon = dateindex(buf, monname); + if(tm.mon >= 0){ + # MM + (date, tm.mday) = datenum(date); + if(tm.mday < 1 || tm.mday > 31) + return 0; + + # HH:MM:SS + (date, tm.hour) = datenum(date); + if(tm.hour < 0 || tm.hour >= 24) + return 0; + (date, tm.min) = datenum(date); + if(tm.min < 0 || tm.min >= 60) + return 0; + (date, tm.sec) = datenum(date); + if(tm.sec < 0 || tm.sec >= 60) + return 0; + + + # YYYY + (nil, tm.year) = datenum(date); + if(tm.year < 70 || tm.year > 99 && tm.year < 1970) + return 0; + if(tm.year >= 1970) + tm.year -= 1900; + }else{ + # MM-Mon-(YY|YYYY) + (date, tm.mday) = datenum(date); + if(tm.mday < 1 || tm.mday > 31) + return 0; + (date,buf) = dateword(date); + tm.mon = dateindex(buf, monname); + if(tm.mon < 0 || tm.mon >= 12) + return 0; + (date, tm.year) = datenum(date); + if(tm.year < 70 || tm.year > 99 && tm.year < 1970) + return 0; + if(tm.year >= 1970) + tm.year -= 1900; + + # HH:MM:SS + (date, tm.hour) = datenum(date); + if(tm.hour < 0 || tm.hour >= 24) + return 0; + (date, tm.min) = datenum(date); + if(tm.min < 0 || tm.min >= 60) + return 0; + (date, tm.sec) = datenum(date); + if(tm.sec < 0 || tm.sec >= 60) + return 0; + + # timezone + (date,buf)=dateword(date); + if(len buf >= 3 && lowercase(buf[0:3])!="gmt") + return 0; + } + + tm.zone="GMT"; + return gmtm2sec(tm); +} + +lowercase(name:string): string { + p: string; + for(i:=0;i<len name;i++) + p[i]=tolower(name[i]); + return p; +} + +dateindex(d : string, tab : array of string): int{ + for(i := 0; i < len tab; i++) + if (lowercase(tab[i]) == d) + return i; + return -1; +} + + +# compute seconds since Jan 1 1970 GMT + +gmtm2sec(tm:Tm): int +{ + secs,i : int; + d2m: array of int; + sys = load Sys "$Sys"; + secs=0; + + #seconds per year + tm.year += 1900; + if(tm.year < 1970) + return 0; + for(i = 1970; i < tm.year; i++){ + d2m = yrsize(i); + secs += d2m[0] * SEC2DAY; + } + + + #seconds per month + d2m = yrsize(tm.year); + for(i = 0; i < tm.mon; i++) + secs += d2m[i+1] * SEC2DAY; + + #secs in last month + secs += (tm.mday-1) * SEC2DAY; + + #hours, minutes, seconds + secs += tm.hour * SEC2HOUR; + secs += tm.min * SEC2MIN; + secs += tm.sec; + + return secs; +} + +now(): int +{ + return daytime->now(); +} |
