summaryrefslogtreecommitdiff
path: root/appl/svc/httpd/date.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/svc/httpd/date.b')
-rw-r--r--appl/svc/httpd/date.b264
1 files changed, 264 insertions, 0 deletions
diff --git a/appl/svc/httpd/date.b b/appl/svc/httpd/date.b
new file mode 100644
index 00000000..9a8ff10a
--- /dev/null
+++ b/appl/svc/httpd/date.b
@@ -0,0 +1,264 @@
+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()
+{
+ sys = load Sys Sys->PATH;
+ daytime = load Daytime Daytime->PATH;
+ if (daytime==nil){
+ sys->print("daytime load: %r\n");
+ exit;
+ }
+}
+
+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++;
+ }
+ return (date[i:],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(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;
+ 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;
+}