refactor: replace predicate-based event matching with collector pipeline
- Simplify `.ocamlformat` to use `default` profile with fewer overrides - Extract shared types and utilities into a `remind_sync` library (`icalendar_augmented`, `ptime_augmented`, `timedesc_augmented`, `result_augmented`, `utf8`) - Replace `eventTransformer.ml` and the predicate system in `eventPredicates.ml` with a sequential collector pipeline (`collect_uuid`, `collect_summary`, `collect_start_end_duration`, etc.) - Simplify `Remind.rem` to a flat record with `Timedesc` date/time fields and replace `rem_to_string` with a leaner `string_of_rem` - Add `separate_master_and_recurrence` and `get_recurrence_id` helpers to `utils.ml` - Wire `main.ml` to call `EventPredicates.remind_of_event` per UID group and print results directly - Remove `eventTransformer` module from `bin/dune` and enable the `remind_sync` library dependency
This commit is contained in:
106
bin/utils.ml
106
bin/utils.ml
@@ -1,36 +1,74 @@
|
||||
open Remind_sync
|
||||
open Icalendar
|
||||
|
||||
let spf = Printf.sprintf
|
||||
|
||||
let get_uid ev =
|
||||
let _, uid = ev.uid in
|
||||
uid
|
||||
|
||||
(* Questa funzione serve solo da esempio per copia e incolla *)
|
||||
let unpack_date_or_datetime (d_or_dt : Icalendar.date_or_datetime) =
|
||||
match d_or_dt with
|
||||
| `Datetime (`Local _ptime_ts) -> ()
|
||||
| `Datetime (`Utc _ts) -> ()
|
||||
| `Datetime (`With_tzid (_ts, (_b, _tz_name))) -> ()
|
||||
| `Date (_year, _month, _day) -> ()
|
||||
|
||||
(* Questa funzione serve solo da esempio per copia e incolla *)
|
||||
let unpack_dtend_or_duration dtend_or_dur =
|
||||
match dtend_or_dur with
|
||||
| None -> ()
|
||||
| Some (`Dtend (_, date_or_datetime)) -> unpack_date_or_datetime date_or_datetime
|
||||
| Some (`Duration (_, _duration)) -> ()
|
||||
|
||||
let string_of_time (t : Timedesc.Time.t) : string =
|
||||
let view = Timedesc.Time.view t in
|
||||
let hour, minute = (view.Timedesc.Time.hour, view.Timedesc.Time.minute) in
|
||||
spf "%02d:%02d" hour minute
|
||||
|
||||
let string_of_span (sp : Timedesc.Span.t) : string =
|
||||
let view = Timedesc.Span.For_human.view sp in
|
||||
let hours, minutes = (view.Timedesc.Span.For_human.hours, view.Timedesc.Span.For_human.minutes) in
|
||||
spf "%02d:%02d" hours minutes
|
||||
|
||||
let timedesc_of_timestamp (ts : timestamp) : Timedesc.t =
|
||||
let local_tz = Timedesc.Time_zone.local_exn () in
|
||||
match ts with
|
||||
| `Local t -> t |> Timedesc.Utils.timestamp_of_ptime |> Timedesc.of_timestamp_exn ~tz_of_date_time:local_tz
|
||||
(* this case is not present in my current dataset… *)
|
||||
| `Utc t -> t |> Timedesc.Utils.timestamp_of_ptime |> Timedesc.of_timestamp_exn ~tz_of_date_time:local_tz
|
||||
| `With_tzid (ts, (_b, tz_name)) ->
|
||||
(* Qui il timestamp è SCRITTO come se fosse UTC (+00:00) ma in realtà va interpretato con
|
||||
il fuso orario indicato da tz_name. *)
|
||||
let tz = Timedesc.Time_zone.make_exn tz_name in
|
||||
let wrong_ts = Timedesc.Utils.timestamp_of_ptime ts in
|
||||
let date = Timedesc.date (Timedesc.of_timestamp_exn ~tz_of_date_time:Timedesc.Time_zone.utc wrong_ts) in
|
||||
let year, month, day = (Timedesc.Date.year date, Timedesc.Date.month date, Timedesc.Date.day date) in
|
||||
let time = Timedesc.time_view (Timedesc.of_timestamp_exn ~tz_of_date_time:Timedesc.Time_zone.utc wrong_ts) in
|
||||
let hour, minute, second = (time.Timedesc.Time.hour, time.Timedesc.Time.minute, time.Timedesc.Time.second) in
|
||||
Timedesc.make_exn ~year ~month ~day ~hour ~minute ~second ~tz ()
|
||||
|
||||
let timedesc_of_date_or_datetime (t : date_or_datetime) : Timedesc.t =
|
||||
match t with
|
||||
| `Datetime (`Local _ptime_ts) ->
|
||||
(* TODO: this case is not present in my current dataset… *)
|
||||
failwith "Unhandled case: `Local datetime"
|
||||
(* this case is not present in my current dataset… *)
|
||||
failwith "Unhandled case: `Local datetime"
|
||||
| `Datetime (`Utc ts) ->
|
||||
Timedesc.Utils.timestamp_of_ptime ts |> Timedesc.of_timestamp_exn ~tz_of_date_time:(Timedesc.Time_zone.local_exn ())
|
||||
Timedesc.Utils.timestamp_of_ptime ts
|
||||
|> Timedesc.of_timestamp_exn ~tz_of_date_time:(Timedesc.Time_zone.local_exn ())
|
||||
| `Datetime (`With_tzid (ts, (_b, tz_name))) ->
|
||||
(* Qui il timestamp è SCRITTO come se fosse UTC (+00:00) ma in realtà va interpretato con
|
||||
(* Qui il timestamp è SCRITTO come se fosse UTC (+00:00) ma in realtà va interpretato con
|
||||
il fuso orario indicato da tz_name. *)
|
||||
let tz = Timedesc.Time_zone.make_exn tz_name in
|
||||
let wrong_ts = Timedesc.Utils.timestamp_of_ptime ts in
|
||||
let date = Timedesc.date (Timedesc.of_timestamp_exn ~tz_of_date_time:Timedesc.Time_zone.utc wrong_ts) in
|
||||
let year, month, day = (Timedesc.Date.year date, Timedesc.Date.month date, Timedesc.Date.day date) in
|
||||
let time = Timedesc.time_view (Timedesc.of_timestamp_exn ~tz_of_date_time:Timedesc.Time_zone.utc wrong_ts) in
|
||||
let hour, minute, second = (time.Timedesc.Time.hour, time.Timedesc.Time.minute, time.Timedesc.Time.second) in
|
||||
Timedesc.make_exn ~year ~month ~day ~hour ~minute ~second ~tz ()
|
||||
let tz = Timedesc.Time_zone.make_exn tz_name in
|
||||
let wrong_ts = Timedesc.Utils.timestamp_of_ptime ts in
|
||||
let date = Timedesc.date (Timedesc.of_timestamp_exn ~tz_of_date_time:Timedesc.Time_zone.utc wrong_ts) in
|
||||
let year, month, day = (Timedesc.Date.year date, Timedesc.Date.month date, Timedesc.Date.day date) in
|
||||
let time = Timedesc.time_view (Timedesc.of_timestamp_exn ~tz_of_date_time:Timedesc.Time_zone.utc wrong_ts) in
|
||||
let hour, minute, second = (time.Timedesc.Time.hour, time.Timedesc.Time.minute, time.Timedesc.Time.second) in
|
||||
Timedesc.make_exn ~year ~month ~day ~hour ~minute ~second ~tz ()
|
||||
| `Date (year, month, day) ->
|
||||
Timedesc.make_exn ~year ~month ~day ~hour:0 ~minute:0 ~second:0 ~tz:(Timedesc.Time_zone.local_exn ()) ()
|
||||
|
||||
let get_y_m_d_from_timedesc (t : Timedesc.t) : int * int * int =
|
||||
let date = Timedesc.date t in
|
||||
(Timedesc.Date.year date, Timedesc.Date.month date, Timedesc.Date.day date)
|
||||
|
||||
let get_start ev =
|
||||
let _, start = ev.dtstart in
|
||||
timedesc_of_date_or_datetime start
|
||||
Timedesc.make_exn ~year ~month ~day ~hour:0 ~minute:0 ~second:0 ~tz:(Timedesc.Time_zone.local_exn ()) ()
|
||||
|
||||
let get_exdates ev =
|
||||
let event_props = ev.props in
|
||||
@@ -67,8 +105,32 @@ let get_rdates ev =
|
||||
| `Datetimes ts_list -> List.map (fun ts -> `Datetime ts) ts_list
|
||||
| `Dates date_list -> List.map (fun date -> `Date date) date_list
|
||||
| `Periods _ ->
|
||||
(* TODO: Ignored for now, does not appear in my current dataset *)
|
||||
failwith "Unhandled case: `Periods in RDATE"
|
||||
(* Ignored for now, does not appear in my current dataset *)
|
||||
failwith "Unhandled case: `Periods in RDATE"
|
||||
in
|
||||
added @ acc)
|
||||
|> List.map timedesc_of_date_or_datetime
|
||||
|
||||
let get_recurrence_id ev =
|
||||
List.find_map
|
||||
(fun prop ->
|
||||
match prop with
|
||||
| `Recur_id (_, date_or_datetime) -> Some date_or_datetime
|
||||
| _ -> None)
|
||||
ev.props
|
||||
|
||||
let separate_master_and_recurrence (events : Icalendar.event list) : Icalendar.event * Icalendar.event list =
|
||||
(* List.iteri (fun i e -> Printf.eprintf "%02d: %s\n" (i + 1) (Icalendar.show_component (`Event e))) events; *)
|
||||
let recur_ids = List.map (fun ev -> (ev, get_recurrence_id ev)) events in
|
||||
|
||||
let master_and_recurrences =
|
||||
List.partition_map
|
||||
(fun (ev, recur_id_opt) ->
|
||||
match recur_id_opt with
|
||||
| None -> Right ev
|
||||
| Some _ -> Left ev)
|
||||
recur_ids
|
||||
in
|
||||
match master_and_recurrences with
|
||||
| [], _ -> failwith "No master event found"
|
||||
| master :: _, recurrences -> (master, recurrences)
|
||||
|
||||
Reference in New Issue
Block a user