Establishes version control for the personal Logseq DB fork before starting the server-client architecture migration and domain features described in docs/agent-guide and the approved implementation plan. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
90 lines
2.8 KiB
OCaml
90 lines
2.8 KiB
OCaml
type span = float
|
|
type date = Js.Date.t
|
|
|
|
let finite value =
|
|
match classify_float value with FP_nan | FP_infinite -> false | _ -> true
|
|
|
|
let invalid_time () = invalid_arg "invalid POSIX timestamp"
|
|
let invalid_span () = invalid_arg "invalid POSIX time span"
|
|
|
|
let time_of_epoch_ms_float ms =
|
|
if finite ms then
|
|
let time = Js.Date.fromFloat ms in
|
|
if finite (Js.Date.getTime time) then time else invalid_time ()
|
|
else invalid_time ()
|
|
|
|
let now () = Js.Date.make ()
|
|
let epoch = time_of_epoch_ms_float 0.
|
|
let max_time = time_of_epoch_ms_float 8_640_000_000_000_000.
|
|
let time_of_epoch_ms ms = time_of_epoch_ms_float (Int64.to_float ms)
|
|
let time_to_epoch_ms time = Int64.of_float (Js.Date.getTime time)
|
|
let time_to_epoch_seconds time = Int64.of_float (Js.Date.getTime time /. 1000.)
|
|
let time_to_epoch_seconds_float time = Js.Date.getTime time /. 1000.
|
|
|
|
let compare_time left right =
|
|
Float.compare (Js.Date.getTime left) (Js.Date.getTime right)
|
|
|
|
let span_of_ms ms =
|
|
let span = Int64.to_float ms in
|
|
if finite span then span else invalid_span ()
|
|
|
|
let span_to_ms span = Int64.of_float span
|
|
let zero_span = 0.
|
|
let compare_span = Float.compare
|
|
let add_span_value left right = left +. right
|
|
|
|
let add_span time span =
|
|
let ms = Js.Date.getTime time +. span in
|
|
if finite ms then Some (Js.Date.fromFloat ms) else None
|
|
|
|
let local_date time =
|
|
( int_of_float (Js.Date.getFullYear time),
|
|
int_of_float (Js.Date.getMonth time) + 1,
|
|
int_of_float (Js.Date.getDate time) )
|
|
|
|
let utc_date_time time =
|
|
( int_of_float (Js.Date.getUTCFullYear time),
|
|
int_of_float (Js.Date.getUTCMonth time) + 1,
|
|
int_of_float (Js.Date.getUTCDate time),
|
|
int_of_float (Js.Date.getUTCHours time),
|
|
int_of_float (Js.Date.getUTCMinutes time),
|
|
int_of_float (Js.Date.getUTCSeconds time) )
|
|
|
|
let non_negative_diff ~start_time ~end_time =
|
|
max 0. (Js.Date.getTime end_time -. Js.Date.getTime start_time)
|
|
|
|
let avg_span span count =
|
|
if count <= 0 then zero_span else span /. float_of_int count
|
|
|
|
let rfc3339_millis time = Js.Date.toISOString time
|
|
|
|
let valid_parsed_ms ms =
|
|
try Some (time_of_epoch_ms_float ms) with Invalid_argument _ -> None
|
|
|
|
let parse_rfc3339 text =
|
|
let valid_shape =
|
|
String.length text >= 20
|
|
&& text.[4] = '-'
|
|
&& text.[7] = '-'
|
|
&& (text.[10] = 'T' || text.[10] = 't')
|
|
&& text.[13] = ':'
|
|
&& text.[16] = ':'
|
|
in
|
|
if valid_shape then valid_parsed_ms (Js.Date.parseAsFloat text) else None
|
|
|
|
let parse_date_as_utc text =
|
|
if String.length text = 10 && text.[4] = '-' && text.[7] = '-' then
|
|
parse_rfc3339 (text ^ "T00:00:00Z")
|
|
else None
|
|
|
|
let parse_time text =
|
|
let text = String.trim text in
|
|
if text = "" then None
|
|
else
|
|
match parse_rfc3339 text with
|
|
| Some _ as time -> time
|
|
| None -> (
|
|
match Int64.of_string_opt text with
|
|
| Some ms -> Some (time_of_epoch_ms ms)
|
|
| None -> parse_date_as_utc text)
|