Task

Given the date string "March 7 2009 7:30pm EST", 

output the time 12 hours later in any human-readable format.

As extra credit, display the resulting time in a time zone different from your own.




link datetime
 
procedure main()
write("input      = ",s := "March 7 2009 7:30pm EST" )
write("+12 hours  = ",SecToTZDateLine(s := TZDateLineToSec(s) + 12*3600,"EST")) 
write("           = ",SecToTZDateLine(s,"UTC"))
write("           = ",SecToTZDateLine(s,"NST"))    
end
 
procedure SecToTZDateLine(s,tz)   #: returns dateline + time zone given seconds
return NormalizedDate(SecToDateLine(s+\(_TZdata("table")[\tz|"UTC"]))||" "|| tz)
end
 
procedure TZDateLineToSec(s)  #: returns seconds given dateline (and time zone)
   return ( 
      NormalizedDate(s) ? (
         d  := tab(find("am"|"pm")+2),tab(many('\t ,')),
         tz := \_TZdata("table")[tab(0)]
         ),
      DateLineToSec(d) - tz)
end
 
procedure NormalizedDate(s)  #: returns a consistent dateline
static D,M
initial {
   D := ["Saturday","Sunday","Monday","Tuesday","Wednesday","Thursday","Friday"]
   M := ["January","February","March","April","May","June",
         "July","August","September","October","November","December"]
   } 
 
map(s) ? {                               # parse and build consistent dateline
   ds := 1(x := !D, =map(x)) | ""                                    # Weekday 
   ds ||:= 1(", ", tab(many('\t ,')|&pos))
   ds ||:= 1(x := !M, =map(x))                 | fail                # Month
   ds ||:= 1(" ", tab(many('\t ,')|&pos))
   ds ||:= tab(many(&digits))                  | fail                # day
   ds ||:= 1(", ", tab(many('\t ,')))          | fail
   ds ||:= tab(many(&digits))                  | fail                # year  
   ds ||:= 1(" ", tab(many('\t ,')))           | fail
   ds ||:= tab(many(&digits))||(=":"||tab(many(&digits))|&null) | fail # time   
   ds ||:= 1(" ", tab(many('\t ,')|&pos))
   ds ||:= =("am"|"pm")                        | fail                # halfday   
   ds ||:= 1(" ", tab(many('\t ,')|&pos))
   tz := map(=!_TZdata("list"),&lcase,&ucase)
   }
 
if ds[1] == "," then 
   ds := SecToDateLine(DateLineToSec("Sunday"||ds))   # get IPL to fix weekday
 
return ds ||:=  " " || \tz|"UTC"   
end
 
procedure _TZdata(x)    #: internal return TZ data (demo version incomplete)
static TZ,AZ
initial {
   TZ := table()  
   AZ := []
   "UTC/0;ACDT/+10.5;CET/1;EST/-5;NPT/+5.75;NST/-3.5;PST/-8;" ?
      while (  a := tab(find("/")), move(1), o := tab(find(";")), move(1) ) do {
         TZ[map(a)] := TZ[a] := integer(3600*o)
         put(AZ,a,map(a))
         }
      every TZ[&null|""] := TZ["UTC"]     
   }
return case x of { "list"  : AZ ; "table" : TZ }
end