(* time.ml - Don Yang (uguu.org) 10/02/07 *) (* Regular expressions for matching time strings *) let re_full_time = Str.regexp ("^\\([0-9][0-9][0-9][0-9]\\)-" ^ "\\([0-9][0-9]?\\)-" ^ "\\([0-9][0-9]?\\) " ^ "\\([0-9][0-9]?\\):" ^ "\\([0-9][0-9]?\\):" ^ "\\([0-9][0-9]?\\)$");; let re_full_time_no_second = Str.regexp ("^\\([0-9][0-9][0-9][0-9]\\)-" ^ "\\([0-9][0-9]?\\)-" ^ "\\([0-9][0-9]?\\) " ^ "\\([0-9][0-9]?\\):" ^ "\\([0-9][0-9]?\\)$");; let re_partial_time = Str.regexp ("^\\([0-9][0-9]?\\):\\([0-9][0-9]?\\):\\([0-9][0-9]?\\)$");; let re_partial_time_no_second = Str.regexp ("^\\([0-9][0-9]?\\):\\([0-9][0-9]?\\)$");; (* Convert list of time components to scalar time *) let tm_to_time year month day hour minute second = let t = {Unix.tm_year = year - 1900; Unix.tm_mon = month - 1; Unix.tm_mday = day; Unix.tm_hour = hour; Unix.tm_min = minute; Unix.tm_sec = second; Unix.tm_wday = 0; Unix.tm_yday = 0; Unix.tm_isdst = false} in fst (Unix.mktime t);; (* Convert fully specified time from last matched regular expression *) let convert_full_time time_str seconds = tm_to_time (int_of_string (Str.matched_group 1 time_str)) (int_of_string (Str.matched_group 2 time_str)) (int_of_string (Str.matched_group 3 time_str)) (int_of_string (Str.matched_group 4 time_str)) (int_of_string (Str.matched_group 5 time_str)) seconds;; (* Convert partially specified time from last matched regular expression *) let convert_partial_time reference_time time_str seconds = (* Use date components from reference time *) let r = Unix.localtime reference_time in let s = {Unix.tm_year = r.Unix.tm_year; Unix.tm_mon = r.Unix.tm_mon; Unix.tm_mday = r.Unix.tm_mday; Unix.tm_hour = (int_of_string (Str.matched_group 1 time_str)); Unix.tm_min = (int_of_string (Str.matched_group 2 time_str)); Unix.tm_sec = seconds; Unix.tm_wday = 0; Unix.tm_yday = 0; Unix.tm_isdst = false} in let t = fst (Unix.mktime s) in (* Reconstruct time so that it's past the reference time *) if t < reference_time then if t >= reference_time -. 60.0 then reference_time else t +. 86400.0 else t;; (* Convert string time to UTC seconds, return -1.0 on error *) let decode_time reference_time time_str = try ( if (Str.string_match re_full_time time_str 0) then ( (* Fully specified time *) convert_full_time time_str (int_of_string (Str.matched_group 6 time_str)) ) else if (Str.string_match re_full_time_no_second time_str 0) then ( (* Fully specified time, assume zero seconds *) convert_full_time time_str 0 ) else if (Str.string_match re_partial_time time_str 0) then ( (* Partially specified time *) convert_partial_time reference_time time_str (int_of_string (Str.matched_group 3 time_str)) ) else if (Str.string_match re_partial_time_no_second time_str 0) then ( (* Partially specified time, arbitrary seconds. Note that modulus happens before converting to int, since OCaml ints do not have enough precision to hold UTC seconds. *) convert_partial_time reference_time time_str (int_of_float (mod_float reference_time 60.0)) ) else ( (* Can not parse time *) -1.0 ) ) with _ -> -1.0;; (* Format scalar time to string time *) let encode_time time = let t = Unix.localtime time in Printf.sprintf "%04d-%02d-%02d %02d:%02d:%02d" (t.Unix.tm_year + 1900) (t.Unix.tm_mon + 1) t.Unix.tm_mday t.Unix.tm_hour t.Unix.tm_min t.Unix.tm_sec;; (* Format time duration as string *) let format_time_length time = let minute = int_of_float (time /. 60.0) in Printf.sprintf "%8d (%dh %dm)" (int_of_float time) (minute / 60) (minute mod 60);;