123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194(*---------------------------------------------------------------------------
Copyright (c) 2015 The mtime programmers. All rights reserved.
Distributed under the ISC license, see terms at the end of the file.
---------------------------------------------------------------------------*)(* Time scale conversion *)letns_to_s=1e-9letus_to_s=1e-6letms_to_s=1e-3letmin_to_s=60.lethour_to_s=3600.letday_to_s=86_400.letyear_to_s=31_557_600.lets_to_ns=1e9lets_to_us=1e6lets_to_ms=1e3lets_to_min=1./.min_to_slets_to_hour=1./.hour_to_slets_to_day=1./.day_to_slets_to_year=1./.year_to_s(* 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_compare(* 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=nsletunsafe_of_uint64_ns_optionnsopt=nsoptletto_nss=(Int64.to_floats)letto_uss=(Int64.to_floats)*.1e-3letto_mss=(Int64.to_floats)*.1e-6letto_ss=(Int64.to_floats)*.1e-9letns_to_min=ns_to_s*.s_to_minletto_mins=(Int64.to_floats)*.ns_to_minletns_to_hour=ns_to_s*.s_to_hourletto_hours=(Int64.to_floats)*.ns_to_hourletns_to_day=ns_to_s*.s_to_dayletto_days=(Int64.to_floats)*.ns_to_dayletns_to_year=ns_to_s*.s_to_yearletto_years=(Int64.to_floats)*.ns_to_year(* Formatting
Maybe one day we could replace this by B00_std.Fmt.uint64_ns_span
which does all the arithmetic on uint64. *)letroundx=floor(x+.0.5)letround_dfracdx=(* rounds [x] to the [d]th decimal digit *)ifx-.(roundx)=0.thenxelse(* x is an integer. *)letm=10.**(floatd)in(* m moves 10^-d to 1. *)(floor((x*.m)+.0.5))/.mletpp_float_sppfspan=letm=abs_floatspaninifm<ms_to_sthen(* m < 1ms, if < 100us, print us with 3 frac digit w.o. trailing zeros
if >= 100us, print us without frac digit *)letus=span/.us_to_sinletus=ifabs_floatus<100.thenround_dfrac3uselseroundusinifabs_floatus>=1000.thenFormat.fprintfppf"%gms"(copysign1.us)elseFormat.fprintfppf"%gus"uselseifm<1.then(* m < 1s, if < 100ms, print ms with 3 frac digit w.o. trailing zeros
if >= 100ms, print ms without frac digit *)letms=span/.ms_to_sinletms=ifabs_floatms<100.thenround_dfrac3mselseroundmsinifabs_floatms>=1000.thenFormat.fprintfppf"%gs"(copysign1.ms)elseFormat.fprintfppf"%gms"mselseifm<min_to_sthen(* m < 1min, print [s] with 3 frac digit w.o. trailing zeros *)lets=round_dfrac3spaninifabs_floats>=60.thenFormat.fprintfppf"%gmin"(copysign1.s)elseFormat.fprintfppf"%gs"selse(* m >= 1min
From here on we show the two (or one if the second is zero) largest
significant units and no longer care about rounding the lowest unit,
we just truncate. *)ifm<hour_to_sthenletm,rem=truncate(span/.min_to_s),mod_floatspanmin_to_sinlets=truncatereminifs=0thenFormat.fprintfppf"%dmin"melseFormat.fprintfppf"%dmin%ds"m(abss)elseifm<day_to_sthenleth,rem=truncate(span/.hour_to_s),mod_floatspanhour_to_sinletm=truncate(rem/.min_to_s)inifm=0thenFormat.fprintfppf"%dh"helseFormat.fprintfppf"%dh%dmin"h(absm)elseifm<year_to_sthenletd,rem=truncate(span/.day_to_s),mod_floatspanday_to_sinleth=truncate(rem/.hour_to_s)inifh=0thenFormat.fprintfppf"%dd"delseFormat.fprintfppf"%dd%dh"d(absh)elselety,rem=truncate(span/.year_to_s),mod_floatspanyear_to_sinletd=truncate(rem/.day_to_s)inifd=0thenFormat.fprintfppf"%da"yelseFormat.fprintfppf"%da%dd"y(absd)letppppfs=pp_float_sppf(to_ss)letdumpppfs=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(*---------------------------------------------------------------------------
Copyright (c) 2015 The mtime programmers
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
---------------------------------------------------------------------------*)