137da2899SCharles.Forsythimplement Daytime; 237da2899SCharles.Forsyth# 337da2899SCharles.Forsyth# These routines convert time as follows: 437da2899SCharles.Forsyth# 537da2899SCharles.Forsyth# The epoch is 0000 Jan 1 1970 GMT. 637da2899SCharles.Forsyth# The argument time is in microseconds since then. 737da2899SCharles.Forsyth# The local(t) entry returns a reference to an ADT 837da2899SCharles.Forsyth# containing 937da2899SCharles.Forsyth# 1037da2899SCharles.Forsyth# seconds (0-59) 1137da2899SCharles.Forsyth# minutes (0-59) 1237da2899SCharles.Forsyth# hours (0-23) 1337da2899SCharles.Forsyth# day of month (1-31) 1437da2899SCharles.Forsyth# month (0-11) 1537da2899SCharles.Forsyth# year-1900 1637da2899SCharles.Forsyth# weekday (0-6, Sun is 0) 1737da2899SCharles.Forsyth# day of the year 1837da2899SCharles.Forsyth# daylight savings flag 1937da2899SCharles.Forsyth# 2037da2899SCharles.Forsyth# The routine gets the daylight savings time from the file /locale/timezone. 2137da2899SCharles.Forsyth# 2237da2899SCharles.Forsyth# text(tvec) 2337da2899SCharles.Forsyth# where tvec is produced by local 2437da2899SCharles.Forsyth# returns a string that has the time in the form 2537da2899SCharles.Forsyth# 2637da2899SCharles.Forsyth# Thu Jan 01 00:00:00 GMT 1970n0 2737da2899SCharles.Forsyth# 012345678901234567890123456789 2837da2899SCharles.Forsyth# 0 1 2 2937da2899SCharles.Forsyth# 3037da2899SCharles.Forsyth# time() just reads the time from /dev/time 3137da2899SCharles.Forsyth# and then calls localtime, then asctime. 3237da2899SCharles.Forsyth# 3337da2899SCharles.Forsyth# The sign bit of second times will turn on 68 years from the epoch ->2038 3437da2899SCharles.Forsyth# 3537da2899SCharles.Forsythinclude "sys.m"; 3637da2899SCharles.Forsythinclude "string.m"; 3737da2899SCharles.Forsythinclude "daytime.m"; 3837da2899SCharles.Forsyth 3937da2899SCharles.ForsythS: String; 4037da2899SCharles.Forsythsys: Sys; 4137da2899SCharles.Forsyth 4237da2899SCharles.Forsythdmsize := array[] of { 4337da2899SCharles.Forsyth 31, 28, 31, 30, 31, 30, 4437da2899SCharles.Forsyth 31, 31, 30, 31, 30, 31 4537da2899SCharles.Forsyth}; 4637da2899SCharles.Forsythldmsize := array[] of { 4737da2899SCharles.Forsyth 31, 29, 31, 30, 31, 30, 4837da2899SCharles.Forsyth 31, 31, 30, 31, 30, 31 4937da2899SCharles.Forsyth}; 5037da2899SCharles.Forsyth 5137da2899SCharles.ForsythTimezone: adt 5237da2899SCharles.Forsyth{ 5337da2899SCharles.Forsyth stname: string; 5437da2899SCharles.Forsyth dlname: string; 5537da2899SCharles.Forsyth stdiff: int; 5637da2899SCharles.Forsyth dldiff: int; 5737da2899SCharles.Forsyth dlpairs: array of int; 5837da2899SCharles.Forsyth}; 5937da2899SCharles.Forsyth 6037da2899SCharles.Forsythtimezone: ref Timezone; 6137da2899SCharles.Forsyth 6237da2899SCharles.Forsythnow(): int 6337da2899SCharles.Forsyth{ 6437da2899SCharles.Forsyth if(sys == nil) 6537da2899SCharles.Forsyth sys = load Sys Sys->PATH; 6637da2899SCharles.Forsyth 6737da2899SCharles.Forsyth fd := sys->open("/dev/time", sys->OREAD); 6837da2899SCharles.Forsyth if(fd == nil) 6937da2899SCharles.Forsyth return 0; 7037da2899SCharles.Forsyth buf := array[128] of byte; 7137da2899SCharles.Forsyth n := sys->read(fd, buf, len buf); 7237da2899SCharles.Forsyth if(n < 0) 7337da2899SCharles.Forsyth return 0; 7437da2899SCharles.Forsyth 7537da2899SCharles.Forsyth t := (big string buf[0:n]) / big 1000000; 7637da2899SCharles.Forsyth return int t; 7737da2899SCharles.Forsyth} 7837da2899SCharles.Forsyth 7937da2899SCharles.Forsythtime(): string 8037da2899SCharles.Forsyth{ 8137da2899SCharles.Forsyth t := now(); 8237da2899SCharles.Forsyth tm := local(t); 8337da2899SCharles.Forsyth return text(tm); 8437da2899SCharles.Forsyth} 8537da2899SCharles.Forsyth 8637da2899SCharles.Forsythlocal(tim: int): ref Tm 8737da2899SCharles.Forsyth{ 8837da2899SCharles.Forsyth ct: ref Tm; 8937da2899SCharles.Forsyth 9037da2899SCharles.Forsyth if(timezone == nil) 9137da2899SCharles.Forsyth timezone = readtimezone(nil); 9237da2899SCharles.Forsyth 9337da2899SCharles.Forsyth t := tim + timezone.stdiff; 9437da2899SCharles.Forsyth dlflag := 0; 9537da2899SCharles.Forsyth for(i := 0; i+1 < len timezone.dlpairs; i += 2) { 9637da2899SCharles.Forsyth if(t >= timezone.dlpairs[i] && t < timezone.dlpairs[i+1]) { 9737da2899SCharles.Forsyth t = tim + timezone.dldiff; 9837da2899SCharles.Forsyth dlflag++; 9937da2899SCharles.Forsyth break; 10037da2899SCharles.Forsyth } 10137da2899SCharles.Forsyth } 10237da2899SCharles.Forsyth ct = gmt(t); 10337da2899SCharles.Forsyth if(dlflag) { 10437da2899SCharles.Forsyth ct.zone = timezone.dlname; 10537da2899SCharles.Forsyth ct.tzoff = timezone.dldiff; 10637da2899SCharles.Forsyth } 10737da2899SCharles.Forsyth else { 10837da2899SCharles.Forsyth ct.zone = timezone.stname; 10937da2899SCharles.Forsyth ct.tzoff = timezone.stdiff; 11037da2899SCharles.Forsyth } 11137da2899SCharles.Forsyth return ct; 11237da2899SCharles.Forsyth} 11337da2899SCharles.Forsyth 11437da2899SCharles.Forsythgmt(tim: int): ref Tm 11537da2899SCharles.Forsyth{ 11637da2899SCharles.Forsyth xtime := ref Tm; 11737da2899SCharles.Forsyth 11837da2899SCharles.Forsyth # break initial number into days 11937da2899SCharles.Forsyth hms := tim % 86400; 12037da2899SCharles.Forsyth day := tim / 86400; 12137da2899SCharles.Forsyth if(hms < 0) { 12237da2899SCharles.Forsyth hms += 86400; 12337da2899SCharles.Forsyth day -= 1; 12437da2899SCharles.Forsyth } 12537da2899SCharles.Forsyth 12637da2899SCharles.Forsyth # generate hours:minutes:seconds 12737da2899SCharles.Forsyth xtime.sec = hms % 60; 12837da2899SCharles.Forsyth d1 := hms / 60; 12937da2899SCharles.Forsyth xtime.min = d1 % 60; 13037da2899SCharles.Forsyth d1 /= 60; 13137da2899SCharles.Forsyth xtime.hour = d1; 13237da2899SCharles.Forsyth 13337da2899SCharles.Forsyth # day is the day number. 13437da2899SCharles.Forsyth # generate day of the week. 13537da2899SCharles.Forsyth # The addend is 4 mod 7 (1/1/1970 was Thursday) 13637da2899SCharles.Forsyth xtime.wday = (day + 7340036) % 7; 13737da2899SCharles.Forsyth 13837da2899SCharles.Forsyth # year number 13937da2899SCharles.Forsyth if(day >= 0) 14037da2899SCharles.Forsyth for(d1 = 70; day >= dysize(d1+1900); d1++) 14137da2899SCharles.Forsyth day -= dysize(d1+1900); 14237da2899SCharles.Forsyth else 14337da2899SCharles.Forsyth for (d1 = 70; day < 0; d1--) 14437da2899SCharles.Forsyth day += dysize(d1+1900-1); 14537da2899SCharles.Forsyth xtime.year = d1; 14637da2899SCharles.Forsyth d0 := day; 14737da2899SCharles.Forsyth xtime.yday = d0; 14837da2899SCharles.Forsyth 14937da2899SCharles.Forsyth # generate month 15037da2899SCharles.Forsyth if(dysize(d1+1900) == 366) 15137da2899SCharles.Forsyth dmsz := ldmsize; 15237da2899SCharles.Forsyth else 15337da2899SCharles.Forsyth dmsz = dmsize; 15437da2899SCharles.Forsyth for(d1 = 0; d0 >= dmsz[d1]; d1++) 15537da2899SCharles.Forsyth d0 -= dmsz[d1]; 15637da2899SCharles.Forsyth xtime.mday = d0 + 1; 15737da2899SCharles.Forsyth xtime.mon = d1; 15837da2899SCharles.Forsyth xtime.zone = "GMT"; 15937da2899SCharles.Forsyth xtime.tzoff = 0; 16037da2899SCharles.Forsyth return xtime; 16137da2899SCharles.Forsyth} 16237da2899SCharles.Forsyth 16337da2899SCharles.Forsythwkday := array[] of { 16437da2899SCharles.Forsyth "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 16537da2899SCharles.Forsyth}; 16637da2899SCharles.Forsyth 16737da2899SCharles.Forsythweekday := array[] of { 16837da2899SCharles.Forsyth "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" 16937da2899SCharles.Forsyth}; 17037da2899SCharles.Forsyth 17137da2899SCharles.Forsythmonth := array[] of { 17237da2899SCharles.Forsyth "Jan", "Feb", "Mar", "Apr", "May", "Jun", 17337da2899SCharles.Forsyth "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 17437da2899SCharles.Forsyth}; 17537da2899SCharles.Forsyth 17637da2899SCharles.Forsythtext(t: ref Tm): string 17737da2899SCharles.Forsyth{ 17837da2899SCharles.Forsyth if(sys == nil) 17937da2899SCharles.Forsyth sys = load Sys Sys->PATH; 18037da2899SCharles.Forsyth 18137da2899SCharles.Forsyth year := 1900+t.year; 18237da2899SCharles.Forsyth 18337da2899SCharles.Forsyth return sys->sprint("%s %s %.2d %.2d:%.2d:%.2d %s %d", 18437da2899SCharles.Forsyth wkday[t.wday], 18537da2899SCharles.Forsyth month[t.mon], 18637da2899SCharles.Forsyth t.mday, 18737da2899SCharles.Forsyth t.hour, 18837da2899SCharles.Forsyth t.min, 18937da2899SCharles.Forsyth t.sec, 19037da2899SCharles.Forsyth t.zone, 19137da2899SCharles.Forsyth year); 19237da2899SCharles.Forsyth} 19337da2899SCharles.Forsyth 19437da2899SCharles.Forsythfilet(now: int, file: int): string 19537da2899SCharles.Forsyth{ 19637da2899SCharles.Forsyth if(sys == nil) 19737da2899SCharles.Forsyth sys = load Sys Sys->PATH; 19837da2899SCharles.Forsyth 19937da2899SCharles.Forsyth t := local(file); 20037da2899SCharles.Forsyth if(now - file < 6*30*24*3600) 20137da2899SCharles.Forsyth return sys->sprint("%s %.2d %.2d:%.2d", 20237da2899SCharles.Forsyth month[t.mon], t.mday, t.hour, t.min); 20337da2899SCharles.Forsyth 20437da2899SCharles.Forsyth year := 1900+t.year; 20537da2899SCharles.Forsyth 20637da2899SCharles.Forsyth return sys->sprint("%s %.2d %d", month[t.mon], t.mday, year); 20737da2899SCharles.Forsyth} 20837da2899SCharles.Forsyth 20937da2899SCharles.Forsythdysize(y: int): int 21037da2899SCharles.Forsyth{ 21137da2899SCharles.Forsyth if(y%4 == 0 && (y%100 != 0 || y%400 == 0)) 21237da2899SCharles.Forsyth return 366; 21337da2899SCharles.Forsyth return 365; 21437da2899SCharles.Forsyth} 21537da2899SCharles.Forsyth 21637da2899SCharles.Forsythreadtimezone(fname: string): ref Timezone 21737da2899SCharles.Forsyth{ 21837da2899SCharles.Forsyth if(sys == nil) 21937da2899SCharles.Forsyth sys = load Sys Sys->PATH; 22037da2899SCharles.Forsyth 22137da2899SCharles.Forsyth tz := ref Timezone; 22237da2899SCharles.Forsyth tz.stdiff = 0; 22337da2899SCharles.Forsyth tz.stname = "GMT"; 22437da2899SCharles.Forsyth 225*af1b61f5SCharles.Forsyth s: string; 22637da2899SCharles.Forsyth if(fname == nil){ 227*af1b61f5SCharles.Forsyth s = readfile("/env/timezone"); 228*af1b61f5SCharles.Forsyth if(s == nil) 229*af1b61f5SCharles.Forsyth s = readfile("/locale/timezone"); 230*af1b61f5SCharles.Forsyth }else{ 231*af1b61f5SCharles.Forsyth if(fname[0] != '/' && fname[0] != '#') 232*af1b61f5SCharles.Forsyth fname = "/locale/" + fname; 233*af1b61f5SCharles.Forsyth s = readfile(fname); 234*af1b61f5SCharles.Forsyth } 235*af1b61f5SCharles.Forsyth if(s == nil) 23637da2899SCharles.Forsyth return tz; 237*af1b61f5SCharles.Forsyth if(s[0] == '/' || s[0] == '#'){ 238*af1b61f5SCharles.Forsyth if(s[len s-1] == '\n') 239*af1b61f5SCharles.Forsyth s = s[0: len s-1]; 240*af1b61f5SCharles.Forsyth s = readfile(s); 241*af1b61f5SCharles.Forsyth if(s == nil) 24237da2899SCharles.Forsyth return tz; 243*af1b61f5SCharles.Forsyth } 244*af1b61f5SCharles.Forsyth (n, val) := sys->tokenize(s, "\t \n\r"); 24537da2899SCharles.Forsyth if(n < 4) 24637da2899SCharles.Forsyth return tz; 24737da2899SCharles.Forsyth 24837da2899SCharles.Forsyth tz.stname = hd val; 24937da2899SCharles.Forsyth val = tl val; 25037da2899SCharles.Forsyth tz.stdiff = int hd val; 25137da2899SCharles.Forsyth val = tl val; 25237da2899SCharles.Forsyth tz.dlname = hd val; 25337da2899SCharles.Forsyth val = tl val; 25437da2899SCharles.Forsyth tz.dldiff = int hd val; 25537da2899SCharles.Forsyth val = tl val; 25637da2899SCharles.Forsyth 25737da2899SCharles.Forsyth tz.dlpairs = array[n-4] of {* => 0}; 25837da2899SCharles.Forsyth for(j := 0; val != nil; val = tl val) 25937da2899SCharles.Forsyth tz.dlpairs[j++] = int hd val; 26037da2899SCharles.Forsyth return tz; 26137da2899SCharles.Forsyth} 26237da2899SCharles.Forsyth 263*af1b61f5SCharles.Forsythreadfile(name: string): string 264*af1b61f5SCharles.Forsyth{ 265*af1b61f5SCharles.Forsyth fd := sys->open(name, Sys->OREAD); 266*af1b61f5SCharles.Forsyth if(fd == nil) 267*af1b61f5SCharles.Forsyth return nil; 268*af1b61f5SCharles.Forsyth buf := array[2048] of byte; 269*af1b61f5SCharles.Forsyth n := sys->read(fd, buf, len buf); 270*af1b61f5SCharles.Forsyth if(n <= 0) 271*af1b61f5SCharles.Forsyth return nil; 272*af1b61f5SCharles.Forsyth return string buf[0:n]; 273*af1b61f5SCharles.Forsyth} 274*af1b61f5SCharles.Forsyth 27537da2899SCharles.ForsythSEC2MIN: con 60; 27637da2899SCharles.ForsythSEC2HOUR: con 60*SEC2MIN; 27737da2899SCharles.ForsythSEC2DAY: con 24*SEC2HOUR; 27837da2899SCharles.Forsyth 27937da2899SCharles.Forsythtm2epoch(tm: ref Tm): int 28037da2899SCharles.Forsyth{ 28137da2899SCharles.Forsyth secs := 0; 28237da2899SCharles.Forsyth 28337da2899SCharles.Forsyth # 28437da2899SCharles.Forsyth # seconds per year 28537da2899SCharles.Forsyth # 28637da2899SCharles.Forsyth yr := tm.year + 1900; 28737da2899SCharles.Forsyth if(yr < 1970) 28837da2899SCharles.Forsyth for(i := yr; i < 1970; i++) 28937da2899SCharles.Forsyth secs -= dysize(i) * SEC2DAY; 29037da2899SCharles.Forsyth else 29137da2899SCharles.Forsyth for(i = 1970; i < yr; i++) 29237da2899SCharles.Forsyth secs += dysize(i) * SEC2DAY; 29337da2899SCharles.Forsyth # 29437da2899SCharles.Forsyth # seconds per month 29537da2899SCharles.Forsyth # 29637da2899SCharles.Forsyth if(dysize(yr) == 366) 29737da2899SCharles.Forsyth dmsz := ldmsize; 29837da2899SCharles.Forsyth else 29937da2899SCharles.Forsyth dmsz = dmsize; 30037da2899SCharles.Forsyth for(i = 0; i < tm.mon; i++) 30137da2899SCharles.Forsyth secs += dmsz[i] * SEC2DAY; 30237da2899SCharles.Forsyth 30337da2899SCharles.Forsyth # 30437da2899SCharles.Forsyth # secs in last month 30537da2899SCharles.Forsyth # 30637da2899SCharles.Forsyth secs += (tm.mday-1) * SEC2DAY; 30737da2899SCharles.Forsyth 30837da2899SCharles.Forsyth # 30937da2899SCharles.Forsyth # hours, minutes, seconds 31037da2899SCharles.Forsyth # 31137da2899SCharles.Forsyth secs += tm.hour * SEC2HOUR; 31237da2899SCharles.Forsyth secs += tm.min * SEC2MIN; 31337da2899SCharles.Forsyth secs += tm.sec; 31437da2899SCharles.Forsyth 31537da2899SCharles.Forsyth # 31637da2899SCharles.Forsyth # time zone offset includes daylight savings time 31737da2899SCharles.Forsyth # 31837da2899SCharles.Forsyth return secs - tm.tzoff; 31937da2899SCharles.Forsyth} 32037da2899SCharles.Forsyth 32137da2899SCharles.Forsyth# handle three formats (we'll be a bit more tolerant) 32237da2899SCharles.Forsyth# Sun, 06 Nov 1994 08:49:37 TZ (rfc822+rfc1123) 32337da2899SCharles.Forsyth# Sunday, 06-Nov-94 08:49:37 TZ (rfc850, obsoleted by rfc1036) 32437da2899SCharles.Forsyth# Sun Nov 6 08:49:37 1994 (ANSI C's asctime() format, assume GMT) 32537da2899SCharles.Forsyth# 32637da2899SCharles.Forsyth# return nil on parsing error 32737da2899SCharles.Forsyth# 32837da2899SCharles.Forsythstring2tm(date: string): ref Tm 32937da2899SCharles.Forsyth{ 33037da2899SCharles.Forsyth buf: string; 33137da2899SCharles.Forsyth ok: int; 33237da2899SCharles.Forsyth tm := ref Tm; 33337da2899SCharles.Forsyth 33437da2899SCharles.Forsyth if(S == nil) 33537da2899SCharles.Forsyth S = load String String->PATH; 33637da2899SCharles.Forsyth 33737da2899SCharles.Forsyth # Weekday|Wday 33837da2899SCharles.Forsyth (date, buf) = dateword(date); 33937da2899SCharles.Forsyth tm.wday = strlookup(wkday, buf); 34037da2899SCharles.Forsyth if(tm.wday < 0) 34137da2899SCharles.Forsyth tm.wday = strlookup(weekday, buf); 34237da2899SCharles.Forsyth if(tm.wday < 0) 34337da2899SCharles.Forsyth return nil; 34437da2899SCharles.Forsyth 34537da2899SCharles.Forsyth # Try Mon 34637da2899SCharles.Forsyth odate := date; 34737da2899SCharles.Forsyth (date, buf) = dateword(date); 34837da2899SCharles.Forsyth tm.mon = strlookup(month, buf); 34937da2899SCharles.Forsyth if(tm.mon >= 0) { 35037da2899SCharles.Forsyth # Mon was OK, so asctime() format 35137da2899SCharles.Forsyth # DD 35237da2899SCharles.Forsyth (date, tm.mday) = datenum(date); 35337da2899SCharles.Forsyth if(tm.mday < 1 || tm.mday > 31) 35437da2899SCharles.Forsyth return nil; 35537da2899SCharles.Forsyth 35637da2899SCharles.Forsyth # HH:MM:SS 35737da2899SCharles.Forsyth (ok, date) = hhmmss(date, tm); 35837da2899SCharles.Forsyth if(!ok) 35937da2899SCharles.Forsyth return nil; 36037da2899SCharles.Forsyth 3614252603cSCharles.Forsyth # optional time zone 3624252603cSCharles.Forsyth while(date != nil && date[0] == ' ') 3634252603cSCharles.Forsyth date = date[1:]; 3644252603cSCharles.Forsyth if(date != nil && !(date[0] >= '0' && date[0] <= '9')){ 3654252603cSCharles.Forsyth for(i := 0; i < len date; i++) 3664252603cSCharles.Forsyth if(date[i] == ' '){ 3674252603cSCharles.Forsyth (tm.zone, tm.tzoff) = tzinfo(date[0: i]); 3684252603cSCharles.Forsyth date = date[i:]; 3694252603cSCharles.Forsyth break; 3704252603cSCharles.Forsyth } 3714252603cSCharles.Forsyth } 3724252603cSCharles.Forsyth 37337da2899SCharles.Forsyth # YY|YYYY 3744252603cSCharles.Forsyth (nil, tm.year) = datenum(date); 37537da2899SCharles.Forsyth if(tm.year > 1900) 37637da2899SCharles.Forsyth tm.year -= 1900; 3774252603cSCharles.Forsyth if(tm.zone == ""){ 3784252603cSCharles.Forsyth tm.zone = "GMT"; 3794252603cSCharles.Forsyth tm.tzoff = 0; 3804252603cSCharles.Forsyth } 38137da2899SCharles.Forsyth } else { 38237da2899SCharles.Forsyth # Mon was not OK 38337da2899SCharles.Forsyth date = odate; 38437da2899SCharles.Forsyth # DD Mon YYYY or DD-Mon-(YY|YYYY) 38537da2899SCharles.Forsyth (date, tm.mday) = datenum(date); 38637da2899SCharles.Forsyth if(tm.mday < 1 || tm.mday > 31) 38737da2899SCharles.Forsyth return nil; 38837da2899SCharles.Forsyth (date, buf) = dateword(date); 38937da2899SCharles.Forsyth tm.mon = strlookup(month, buf); 39037da2899SCharles.Forsyth if(tm.mon < 0 || tm.mon >= 12) 39137da2899SCharles.Forsyth return nil; 39237da2899SCharles.Forsyth (date, tm.year) = datenum(date); 39337da2899SCharles.Forsyth if(tm.year > 1900) 39437da2899SCharles.Forsyth tm.year -= 1900; 39537da2899SCharles.Forsyth 39637da2899SCharles.Forsyth # HH:MM:SS 39737da2899SCharles.Forsyth (ok, buf) = hhmmss(date, tm); 39837da2899SCharles.Forsyth if(!ok) 39937da2899SCharles.Forsyth return nil; 40037da2899SCharles.Forsyth (tm.zone, tm.tzoff) = tzinfo(buf); 40137da2899SCharles.Forsyth if(tm.zone == "") 40237da2899SCharles.Forsyth return nil; 4034252603cSCharles.Forsyth } 40437da2899SCharles.Forsyth 40537da2899SCharles.Forsyth return tm; 40637da2899SCharles.Forsyth} 40737da2899SCharles.Forsyth 40837da2899SCharles.Forsythdateword(date: string): (string, string) 40937da2899SCharles.Forsyth{ 41037da2899SCharles.Forsyth notalnum: con "^A-Za-z0-9"; 41137da2899SCharles.Forsyth 41237da2899SCharles.Forsyth date = S->drop(date, notalnum); 41337da2899SCharles.Forsyth (w, rest) := S->splitl(date, notalnum); 41437da2899SCharles.Forsyth return (rest, w); 41537da2899SCharles.Forsyth} 41637da2899SCharles.Forsyth 41737da2899SCharles.Forsythdatenum(date: string): (string, int) 41837da2899SCharles.Forsyth{ 41937da2899SCharles.Forsyth notdig: con "^0-9"; 42037da2899SCharles.Forsyth 42137da2899SCharles.Forsyth date = S->drop(date, notdig); 42237da2899SCharles.Forsyth (num, rest) := S->splitl(date, notdig); 42337da2899SCharles.Forsyth return (rest, int num); 42437da2899SCharles.Forsyth} 42537da2899SCharles.Forsyth 42637da2899SCharles.Forsythstrlookup(a: array of string, s: string): int 42737da2899SCharles.Forsyth{ 42837da2899SCharles.Forsyth n := len a; 42937da2899SCharles.Forsyth for(i := 0; i < n; i++) { 43037da2899SCharles.Forsyth if(s == a[i]) 43137da2899SCharles.Forsyth return i; 43237da2899SCharles.Forsyth } 43337da2899SCharles.Forsyth return -1; 43437da2899SCharles.Forsyth} 43537da2899SCharles.Forsyth 43637da2899SCharles.Forsythhhmmss(date: string, tm: ref Tm): (int, string) 43737da2899SCharles.Forsyth{ 43837da2899SCharles.Forsyth err := (0, ""); 43937da2899SCharles.Forsyth 44037da2899SCharles.Forsyth (date, tm.hour) = datenum(date); 44137da2899SCharles.Forsyth if(tm.hour < 0 || tm.hour >= 24) 44237da2899SCharles.Forsyth return err; 44337da2899SCharles.Forsyth (date, tm.min) = datenum(date); 44437da2899SCharles.Forsyth if(tm.min < 0 || tm.min >= 60) 44537da2899SCharles.Forsyth return err; 44637da2899SCharles.Forsyth (date, tm.sec) = datenum(date); 44737da2899SCharles.Forsyth if(tm.sec < 0 || tm.sec >= 60) 44837da2899SCharles.Forsyth return err; 44937da2899SCharles.Forsyth 45037da2899SCharles.Forsyth return (1, date); 45137da2899SCharles.Forsyth} 45237da2899SCharles.Forsyth 45337da2899SCharles.Forsythtzinfo(tz: string): (string, int) 45437da2899SCharles.Forsyth{ 45537da2899SCharles.Forsyth # strip leading and trailing whitespace 45637da2899SCharles.Forsyth WS: con " \t"; 45737da2899SCharles.Forsyth tz = S->drop(tz, WS); 45837da2899SCharles.Forsyth for(n := len tz; n > 0; n--) { 45937da2899SCharles.Forsyth if(S->in(tz[n-1], WS) == 0) 46037da2899SCharles.Forsyth break; 46137da2899SCharles.Forsyth } 46237da2899SCharles.Forsyth if(n < len tz) 46337da2899SCharles.Forsyth tz = tz[:n]; 46437da2899SCharles.Forsyth 46537da2899SCharles.Forsyth # if no timezone, default to GMT 46637da2899SCharles.Forsyth if(tz == nil) 46737da2899SCharles.Forsyth return ("GMT", 0); 46837da2899SCharles.Forsyth 46937da2899SCharles.Forsyth # GMT aliases 47037da2899SCharles.Forsyth case tz { 47137da2899SCharles.Forsyth "GMT" or 47237da2899SCharles.Forsyth "UT" or 47337da2899SCharles.Forsyth "UTC" or 47437da2899SCharles.Forsyth "Z" => 47537da2899SCharles.Forsyth return ("GMT", 0); 47637da2899SCharles.Forsyth } 47737da2899SCharles.Forsyth 47837da2899SCharles.Forsyth # [+-]hhmm (hours and minutes offset from GMT) 47937da2899SCharles.Forsyth if(len tz == 5 && (tz[0] == '+' || tz[0] == '-')) { 48037da2899SCharles.Forsyth h := int tz[1:3]; 48137da2899SCharles.Forsyth m := int tz[3:5]; 48237da2899SCharles.Forsyth if(h > 23 || m > 59) 48337da2899SCharles.Forsyth return ("", 0); 48437da2899SCharles.Forsyth tzoff := h*SEC2HOUR + m*SEC2MIN; 48537da2899SCharles.Forsyth if(tz[0] == '-') 48637da2899SCharles.Forsyth tzoff = -tzoff; 48737da2899SCharles.Forsyth return ("GMT", tzoff); 48837da2899SCharles.Forsyth } 48937da2899SCharles.Forsyth 49037da2899SCharles.Forsyth # try continental US timezones 49137da2899SCharles.Forsyth filename: string; 49237da2899SCharles.Forsyth case tz { 49337da2899SCharles.Forsyth "CST" or "CDT" => 49437da2899SCharles.Forsyth filename = "CST.CDT"; 49537da2899SCharles.Forsyth "EST" or "EDT" => 49637da2899SCharles.Forsyth filename = "EST.EDT"; 49737da2899SCharles.Forsyth "MST" or "MDT" => 49837da2899SCharles.Forsyth filename = "MST.MDT"; 49937da2899SCharles.Forsyth "PST" or "PDT" => 50037da2899SCharles.Forsyth filename = "PST.PDT"; 50137da2899SCharles.Forsyth * => 50237da2899SCharles.Forsyth ; # default to local timezone 50337da2899SCharles.Forsyth } 50437da2899SCharles.Forsyth tzdata := readtimezone(filename); 50537da2899SCharles.Forsyth if(tzdata.stname == tz) 50637da2899SCharles.Forsyth return (tzdata.stname, tzdata.stdiff); 50737da2899SCharles.Forsyth if(tzdata.dlname == tz) 50837da2899SCharles.Forsyth return (tzdata.dlname, tzdata.dldiff); 50937da2899SCharles.Forsyth 51037da2899SCharles.Forsyth return ("", 0); 51137da2899SCharles.Forsyth} 512