(* camlp4r ./pa_html.cmo *) (* $Id: date.ml,v 4.21 2004/12/14 09:30:11 ddr Exp $ *) (* Copyright (c) 1998-2005 INRIA *) open Def; open Util; open Gutil; open Config; value nbsp = " "; value code_date conf encoding d m y = let apply_date_code = fun [ 'd' -> string_of_int d | 'm' -> transl_nth conf "(month)" (m - 1) | 'y' -> string_of_int y | c -> "%" ^ String.make 1 c ] in let rec loop i = if i = String.length encoding then "" else let (s, i) = match encoding.[i] with [ '%' when i + 1 < String.length encoding -> let s = apply_date_code encoding.[i + 1] in (s, i + 1) | '[' when i + 5 < String.length encoding && encoding.[i + 3] = ']' && encoding.[i + 4] = '%' -> let s = apply_date_code encoding.[i + 5] in let s1 = if start_with_vowel s then String.make 1 encoding.[i + 2] else String.make 1 encoding.[i + 1] ^ " " in (s1 ^ s, i + 5) | c -> (String.make 1 c, i) ] in s ^ loop (i + 1) in loop 0 ; value code_dmy conf d = let encoding = let n = if d.day = 1 then 0 else if d.day != 0 then 1 else if d.month != 0 then 2 else 3 in transl_nth conf "(date)" n in code_date conf encoding d.day d.month d.year ; value code_year conf y = code_date conf (transl_nth conf "(date)" 3) 0 0 y ; value default_french_month = let tab = [| "Vendemiaire"; "Brumaire"; "Frimaire"; "Nivose"; "Pluviose"; "Ventose"; "Germinal"; "Floreal"; "Prairial"; "Messidor"; "Thermidor"; "Fructidor"; "Extra" |] in fun m -> tab.(m) ; value default_hebrew_month = let tab = [| "Tishri"; "Heshvan"; "Kislev"; "Tevet"; "Shevat"; "AdarI"; "AdarII"; "Nisan"; "Iyyar"; "Sivan"; "Tammuz"; "Av"; "Elul" |] in fun m -> tab.(m) ; value french_month conf m = let r = transl_nth conf "(french revolution month)" m in if r = "[(french revolution month)]" then "[" ^ default_french_month m ^ "]" else r ; value hebrew_month conf m = let r = transl_nth conf "(hebrew month)" m in if r = "[(hebrew month)]" then "[" ^ default_hebrew_month m ^ "]" else r ; value code_french_year conf y = transl_nth conf "year/month/day" 3 ^ " " ^ (if y >= 1 && y < 4000 then roman_of_arabian y else string_of_int y) ; value code_french_date conf d m y = let s = if d = 0 then "" else string_of_int d ^ (if d = 1 then "er" else "") in let s = if m = 0 then "" else s ^ (if s = "" then "" else " ") ^ french_month conf (m - 1) in s ^ (if s = "" then "" else " ") ^ code_french_year conf y ; value code_hebrew_date conf d m y = let s = if d = 0 then "" else string_of_int d in let s = if m = 0 then "" else s ^ (if s = "" then "" else " ") ^ hebrew_month conf (m - 1) in s ^ (if s = "" then "" else " ") ^ string_of_int y ; value string_of_on_prec_dmy_aux conf code_year sy d = match d.prec with [ Sure -> if d.day = 0 && d.month = 0 then transl conf "in (year)" ^ " " ^ sy else if d.day = 0 then transl_decline conf "in (month year)" sy else transl_decline conf "on (day month year)" sy | About | Before | After -> let s = sy in if d.prec = About then transl_decline conf "about (date)" s else if d.prec = Before then transl_decline conf "before (date)" s else transl_decline conf "after (date)" s | Maybe -> let s = if d.day = 0 && d.month = 0 then transl conf "in (year)" ^ " " ^ sy else if d.day = 0 then transl_decline conf "in (month year)" sy else transl_decline conf "on (day month year)" sy in transl_decline conf "possibly (date)" s | OrYear z -> let s = if d.day = 0 && d.month = 0 then transl conf "in (year)" ^ " " ^ sy else if d.day = 0 then transl_decline conf "in (month year)" sy else transl_decline conf "on (day month year)" sy in s ^ " " ^ transl conf "or" ^ " " ^ nominative (code_year conf z) | YearInt z -> let s = if d.day = 0 && d.month = 0 then sy else if d.day = 0 then sy else transl_decline conf "on (day month year)" sy in transl conf "between (date)" ^ " " ^ s ^ " " ^ transl_nth conf "and" 0 ^ " " ^ nominative (code_year conf z) ] ; value replace_spaces_by_nbsp s = loop 0 0 where rec loop i len = if i = String.length s then Buff.get len else if s.[i] = ' ' then loop (i + 1) (Buff.mstore len " ") else loop (i + 1) (Buff.store len s.[i]) ; value string_of_on_prec_dmy conf code_dmy sy d = let r = string_of_on_prec_dmy_aux conf code_dmy sy d in replace_spaces_by_nbsp r ; value string_of_on_dmy conf d = let sy = code_dmy conf d in string_of_on_prec_dmy conf code_year sy d ; value string_of_on_french_dmy conf d = let sy = code_french_date conf d.day d.month d.year in string_of_on_prec_dmy conf code_french_year sy d ; value string_of_on_hebrew_dmy conf d = let sy = code_hebrew_date conf d.day d.month d.year in string_of_on_prec_dmy conf code_year sy d ; value string_of_prec_dmy conf s d = match d.prec with [ Sure -> nominative s | About -> transl_decline conf "about (date)" s | Before -> transl_decline conf "before (date)" s | After -> transl_decline conf "after (date)" s | Maybe -> transl_decline conf "possibly (date)" s | OrYear z -> s ^ " " ^ transl conf "or" ^ " " ^ nominative (code_date conf (transl_nth conf "(date)" 3) 0 0 z) | YearInt z -> transl conf "between (date)" ^ " " ^ s ^ " " ^ transl_nth conf "and" 0 ^ " " ^ nominative (code_date conf (transl_nth conf "(date)" 3) 0 0 z) ] ; value string_of_dmy conf d = let sy = code_dmy conf d in string_of_prec_dmy conf sy d ; value gregorian_precision conf d = if d.delta = 0 then string_of_dmy conf d else let d2 = Calendar.gregorian_of_sdn d.prec (Calendar.sdn_of_gregorian d + d.delta) in transl conf "between (date)" ^ " " ^ string_of_on_dmy conf d ^ " " ^ transl_nth conf "and" 0 ^ " " ^ string_of_on_dmy conf d2 ; value string_of_ondate conf = fun [ Dgreg d Dgregorian -> string_of_on_dmy conf d | Dgreg d Djulian -> let cal_prec = if d.year < 1582 then "" else " (" ^ gregorian_precision conf d ^ ")" in let d1 = Calendar.julian_of_gregorian d in string_of_on_dmy conf d1 ^ " " ^ transl_nth conf "gregorian/julian/french/hebrew" 1 ^ cal_prec | Dgreg d Dfrench -> let d1 = Calendar.french_of_gregorian d in let s = string_of_on_french_dmy conf d1 in match d.prec with [ Sure -> s ^ " " ^ " (" ^ gregorian_precision conf d ^ ")" | About | Before | After | Maybe | OrYear _ | YearInt _ -> s ] | Dgreg d Dhebrew -> let d1 = Calendar.hebrew_of_gregorian d in let s = string_of_on_hebrew_dmy conf d1 in match d.prec with [ Sure -> s ^ " " ^ " (" ^ gregorian_precision conf d ^ ")" | About | Before | After | Maybe | OrYear _ | YearInt _ -> s ] | Dtext t -> "(" ^ t ^ ")" ] ; (* value string_of_ondate conf d = match d with [ Dgreg {day = day; month = month; year = year} _ when day <> 0 && month <> 0 && not conf.cancel_links -> "" ^ string_of_ondate conf d ^ "" | _ -> string_of_ondate conf d ] ; *) value string_of_date conf = fun [ Dgreg d _ -> string_of_dmy conf d | Dtext t -> "(" ^ t ^ ")" ] ; value string_of_age conf a = match a with [ {day = 0; month = 0; year = y} -> if y > 1 then string_of_int y ^ " " ^ transl conf "years old" else if y = 1 then transl conf "one year old" else transl conf "birth" | {day = 0; month = m; year = y} -> if y >= 2 then string_of_int y ^ " " ^ transl conf "years old" else if y > 0 || m > 1 then string_of_int (y * 12 + m) ^ " " ^ transl conf "months old" else if m = 1 then transl conf "one month old" else transl conf "less than one month old" | {day = d; month = m; year = y} -> if y >= 2 then string_of_int y ^ " " ^ transl conf "years old" else if y > 0 || m > 1 then string_of_int (y * 12 + m) ^ " " ^ transl conf "months old" else if m = 1 then transl conf "one month old" else if d >= 2 then string_of_int d ^ " " ^ transl conf "days old" else if d == 1 then transl conf "one day old" else "0" ] ; value year_text d = let s = match d.prec with [ Before -> "/" | About | Maybe -> "ca " | _ -> "" ] in let s = s ^ string_of_int (year_of d) in match d.prec with [ After -> s ^ "/" | OrYear x -> s ^ "/" ^ string_of_int x | YearInt x -> s ^ "/" ^ string_of_int x | _ -> s ] ; value of_course_died conf p = match Adef.od_of_codate p.birth with [ Some (Dgreg d _) -> conf.Config.today.year - d.year > 120 | _ -> False ] ; value get_birth_death_date p = let (birth_date, approx) = match Adef.od_of_codate p.birth with [ None -> (Adef.od_of_codate p.baptism, True) | x -> (x, False) ] in let (death_date, approx) = match date_of_death p.death with [ Some d -> (Some d, approx) | _ -> match p.burial with [ Buried cd -> (Adef.od_of_codate cd, True) | Cremated cd -> (Adef.od_of_codate cd, True) | _ -> (None, approx) ] ] in (birth_date, death_date, approx) ; value short_dates_text conf base p = if authorized_age conf base p then let (birth_date, death_date, _) = get_birth_death_date p in let s = "" in let s = match birth_date with [ Some (Dgreg d _) -> s ^ year_text d | _ -> s ] in let s = match (birth_date, death_date) with [ (Some _, Some _) -> s ^ "-" | (Some _, None) -> if p.death = NotDead then s ^ "-" else s | _ -> match p.death with [ Death _ _ | DeadDontKnowWhen | DeadYoung -> if s = "" then "+" else s ^ nbsp ^ "+" | _ -> s ] ] in let s = match death_date with [ Some (Dgreg d _) -> s ^ year_text d | _ -> s ] in if s <> "" then " " ^ s ^ "" else s else "" ; value short_marriage_date_text conf base fam p1 p2 = if authorized_age conf base p1 && authorized_age conf base p2 then match Adef.od_of_codate fam.marriage with [ Some (Dgreg d _) -> "" ^ year_text d ^ "" | _ -> "" ] else "" ; value string_of_place conf pl = Util.string_with_macros conf False [] pl ; value print_dates conf base p = let cap s = ", " ^ s in let is = index_of_sex p.sex in do { let birth_place = sou base p.birth_place in match Adef.od_of_codate p.birth with [ Some d -> do { Wserver.wprint "%s " (cap (transl_nth conf "born" is)); Wserver.wprint "%s" (string_of_ondate conf d); if birth_place <> "" then Wserver.wprint ",\n" else (); } | None -> if birth_place <> "" then Wserver.wprint "%s\n- " (cap (transl_nth conf "born" is)) else () ]; if birth_place <> "" then Wserver.wprint "%s" (string_of_place conf birth_place) else (); let baptism = Adef.od_of_codate p.baptism in let baptism_place = sou base p.baptism_place in match baptism with [ Some d -> do { Wserver.wprint "%s " (cap (transl_nth conf "baptized" is)); Wserver.wprint "%s" (string_of_ondate conf d); if baptism_place <> "" then Wserver.wprint ",\n" else (); } | None -> if baptism_place <> "" then Wserver.wprint "%s\n- " (cap (transl_nth conf "baptized" is)) else () ]; if baptism_place <> "" then Wserver.wprint "%s" (string_of_place conf baptism_place) else (); let death_place = sou base p.death_place in match p.death with [ Death dr d -> let dr_w = match dr with [ Unspecified -> transl_nth conf "died" is | Murdered -> transl_nth conf "murdered" is | Killed -> transl_nth conf "killed (in action)" is | Executed -> transl_nth conf "executed (legally killed)" is | Disappeared -> transl_nth conf "disappeared" is ] in let d = Adef.date_of_cdate d in do { Wserver.wprint "%s " (cap dr_w); Wserver.wprint "%s" (string_of_ondate conf d); if death_place <> "" then Wserver.wprint ",\n" else (); } | DeadYoung -> do { Wserver.wprint "%s" (cap (transl_nth conf "died young" is)); if death_place <> "" then Wserver.wprint "\n- " else (); } | DeadDontKnowWhen -> match (death_place, p.burial) with [ ("", Buried _ | Cremated _) -> () | _ -> if death_place <> "" || not (of_course_died conf p) then do { Wserver.wprint "%s" (cap (transl_nth conf "died" is)); if death_place <> "" then Wserver.wprint "\n- " else (); } else () ] | DontKnowIfDead | NotDead -> () ]; if death_place <> "" then Wserver.wprint "%s" (string_of_place conf death_place) else (); let burial_date_place cod = let place = sou base p.burial_place in do { match Adef.od_of_codate cod with [ Some d -> do { Wserver.wprint " %s" (string_of_ondate conf d); if place <> "" then Wserver.wprint ",\n" else (); } | None -> if place <> "" then Wserver.wprint " - " else () ]; if place <> "" then Wserver.wprint "%s" (string_of_place conf place) else (); } in match p.burial with [ Buried cod -> do { Wserver.wprint "%s" (cap (transl_nth conf "buried" is)); burial_date_place cod; } | Cremated cod -> do { Wserver.wprint "%s" (cap (transl_nth conf "cremated" is)); burial_date_place cod; } | UnknownBurial -> () ]; let (birth_date, death_date, approx) = get_birth_death_date p in match (birth_date, death_date) with [ (Some (Dgreg ({prec = Sure | About | Maybe} as d1) _), Some (Dgreg ({prec = Sure | About | Maybe} as d2) _)) when d1 <> d2 -> let a = time_gone_by d1 d2 in if a.year < 0 || a.year = 0 && a.month = 0 then () else do { Wserver.wprint "\n("; Wserver.wprint "%s " (transl conf "age at death:"); if not approx && d1.prec = Sure && d2.prec = Sure then () else Wserver.wprint "%s " (transl_decline conf "possibly (date)" ""); Wserver.wprint "%s)" (string_of_age conf a); } | _ -> () ]; } ; (* Calendar request *) value gregorian_month_name conf n = capitale (nominative (transl_nth conf "(month)" n)) ; value julian_month_name = gregorian_month_name; value french_month_name conf n = capitale (nominative (french_month conf n)); value hebrew_month_name conf n = capitale (nominative (hebrew_month conf n)); value print_year date var = do { tag "td" begin Wserver.wprint "" var; end; tag "td" begin Wserver.wprint "" var date.year; end; tag "td" begin Wserver.wprint "\n" var; end } ; value print_month conf date month_name n_months var = do { tag "td" begin Wserver.wprint "" var; end; tag "td" "align=center" begin tag "select" "name=m%s" var begin for i = 1 to n_months do { Wserver.wprint "