123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173(*---------------------------------------------------------------------------
Copyright (c) 2015 The mtime programmers. All rights reserved.
SPDX-License-Identifier: ISC
---------------------------------------------------------------------------*)(* Time spans
Time spans are in nanoseconds and we represent them by an unsigned
64-bit integer. This allows to represent spans for:
(2^64-1) / 1_000_000_000 / (24 * 3600 * 365.25) ≅ 584.5 Julian years *)typespan=int64(* unsigned nanoseconds *)moduleSpan=structtypet=spanletzero=0Lletone=1Lletmin_span=zeroletmax_span=-1L(* Predicates *)letequal=Int64.equalletcompare=Int64.unsigned_compareletis_shorters~than=comparesthan<0letis_longers~than=comparesthan>0(* Arithmetic *)letadd=Int64.addletabs_diffs0s1=ifcompares0s1<0thenInt64.subs1s0elseInt64.subs0s1(* Durations *)let(*)ns=Int64.mul(Int64.of_intn)sletns=1Lletus=1_000Lletms=1_000_000Llets=1_000_000_000Lletmin=60_000_000_000Llethour=3600_000_000_000Lletday=86400_000_000_000Lletyear=31_557_600_000_000_000L(* Converting *)letto_uint64_nss=sletof_uint64_nsns=nsletmax_float_int=9007199254740992.(* 2^53. *)letint64_min_int_float=Int64.to_floatInt64.min_intletint64_max_int_float=Int64.to_floatInt64.max_intletof_float_nssf=ifsf<0.||sf>=max_float_int||not(Float.is_finitesf)thenNoneelseSome(Int64.of_floatsf)letto_float_nss=ifInt64.compare0Ls<=0thenInt64.to_floatselseint64_max_int_float+.(-.int64_min_int_float+.Int64.to_floats)letunsafe_of_uint64_ns_optionnsopt=nsopt(* Formatting *)letpf=Format.fprintfletrecpp_si_spanunit_strunit_str_lensi_unitsi_higher_unitppfspan=letgeqxy=Int64.unsigned_comparexy>=0inletm=Int64.unsigned_divspansi_unitinletn=Int64.unsigned_remspansi_unitinletpp_unitppf()=Format.pp_print_asppfunit_str_lenunit_strinmatchmwith|mwhengeqm100L->(* No fractional digit *)letm_up=ifInt64.equaln0LthenmelseInt64.succminletspan'=Int64.mulm_upsi_unitinifgeqspan'si_higher_unitthenppppfspan'else(pfppf"%Ld"m_up;pp_unitppf())|mwhengeqm10L->(* One fractional digit w.o. trailing zero *)letf_factor=Int64.unsigned_divsi_unit10Linletf_m=Int64.unsigned_divnf_factorinletf_n=Int64.unsigned_remnf_factorinletf_m_up=ifInt64.equalf_n0Lthenf_melseInt64.succf_minbeginmatchf_m_upwith|0L->pfppf"%Ld"m;pp_unitppf()|fwhengeqf10L->ppppfInt64.(add(mulmsi_unit)(mulff_factor))|f->pfppf"%Ld.%Ld"mf;pp_unitppf()end|m->(* Two or zero fractional digits w.o. trailing zero *)letf_factor=Int64.unsigned_divsi_unit100Linletf_m=Int64.unsigned_divnf_factorinletf_n=Int64.unsigned_remnf_factorinletf_m_up=ifInt64.equalf_n0Lthenf_melseInt64.succf_minmatchf_m_upwith|0L->pfppf"%Ld"m;pp_unitppf()|fwhengeqf100L->ppppfInt64.(add(mulmsi_unit)(mulff_factor))|fwhenInt64.equal(Int64.remf10L)0L->pfppf"%Ld.%Ld"m(Int64.divf10L);pp_unitppf()|f->pfppf"%Ld.%02Ld"mf;pp_unitppf()andpp_non_siunit_strunitunit_lo_strunit_lounit_lo_sizeppfspan=letgeqxy=Int64.unsigned_comparexy>=0inletm=Int64.unsigned_divspanunitinletn=Int64.unsigned_remspanunitinifInt64.equaln0Lthenpfppf"%Ld%s"munit_strelseletf_m=Int64.unsigned_divnunit_loinletf_n=Int64.unsigned_remnunit_loinletf_m_up=ifInt64.equalf_n0Lthenf_melseInt64.succf_minmatchf_m_upwith|fwhengeqfunit_lo_size->ppppfInt64.(add(mulmunit)(mulfunit_lo))|f->pfppf"%Ld%s%Ld%s"munit_strfunit_lo_strandppppfspan=letgeqxy=Int64.unsigned_comparexy>=0inletltxy=Int64.unsigned_comparexy=-1inmatchspanwith|spwhenltspus->pfppf"%Ldns"sp|spwhenltspms->pp_si_span"\xCE\xBCs"2usmsppfsp|spwhenltsps->pp_si_span"ms"2mssppfsp|spwhenltspmin->pp_si_span"s"1sminppfsp|spwhenltsphour->pp_non_si"min"min"s"s60Lppfsp|spwhenltspday->pp_non_si"h"hour"min"min60Lppfsp|spwhenltspyear->pp_non_si"d"day"h"hour24Lppfsp|sp->letm=Int64.unsigned_divspyearinletn=Int64.unsigned_remspyearinifInt64.equaln0Lthenpfppf"%Lda"melseletf_m=Int64.unsigned_divndayinletf_n=Int64.unsigned_remndayinletf_m_up=ifInt64.equalf_n0Lthenf_melseInt64.succf_minmatchf_m_upwith|fwhengeqf366L->pfppf"%Lda"(Int64.succm)|f->pfppf"%Lda%Ldd"mfletdumpppfs=Format.fprintfppf"%Lu"send(* Monotonic timestamps *)typet=int64letto_uint64_nss=sletof_uint64_nsns=nsletmin_stamp=0Lletmax_stamp=-1L(* Predicates *)letequal=Int64.equalletcompare=Int64.unsigned_compareletis_earliert~than=comparetthan<0letis_latert~than=comparetthan>0(* Arithmetic *)letspant0t1=ifcomparet0t1<0thenInt64.subt1t0elseInt64.subt0t1letadd_spants=letsum=Int64.addtsinifcomparetsum<=0thenSomesumelseNoneletsub_spants=ifcomparets<0thenNoneelseSome(Int64.subts)(* Formatters *)letppppfns=Format.fprintfppf"%Luns"nsletdumpppfns=Format.fprintfppf"%Lu"ns