We were discussing the internal representation of time, and I suggested we change from U128
to I64
for the internal representation as this was what @Hannes is using for the DateTime lib. I've started looking at updating roc-lang/basic-cli
to make this change for Utc.roc
and have remembered why I used U128
. The Rust library provides nanoseconds with U128
e.g. core::time::Duration::as_nanos(&self) -> u128
and the platform currently measures time at that level of precision. Is this an issue that needs to be resolved? I assume we can always just use Num.toI64 : Int * -> I64
as required. when converting to a DateTime.
interesting, I wonder why they chose that :face_with_raised_eyebrow:
Duration has historically lacked a way to get the actual number of nanoseconds it contained as a normal Rust type because u64 was of insufficient range, and f64 of insufficient precision. The u128 type solves both issues, so I propose adding an as_nanos function to expose the capability.
looking at https://man7.org/linux/man-pages/man2/clock_gettime.2.html and https://stackoverflow.com/a/471287 it appears that if you get the time in Linux, the answer is specified as:
i32
or i64
(it's up to the particular C implementation which to choose; if they choose i32
they are susceptible to the Year 2038 problem)i32
That's how I've defined duration in my datetime library:
Duration : { seconds : I64, nanoseconds : U32 }
copied from Rust's chrono crate.
so I guess if you're storing seconds as i64
and nanoseconds as i32
then if you want to combine those into one single nanoseconds value, I think you need another 30 bits (1 nanosecond is 1e9 seconds, 2^30 is a little over 1e9)
if nanoseconds is u32
and seconds is i64
then I think putting them together you should be able to just barely fit them both into a single i128
number of nanoseconds unless my math is wrong :sweat_smile:
The maximum value that can be stored is Num.maxI64 seconds + 999_999_999 nanoseconds = 2^63 seconds
, which I think is more than Num.maxI128 nanoseconds = (2^127 − 1) nanoseconds
image.png
The way chrono
handles this is if you try to convert a duration to nanoseconds that is longer than i64::MAX nanoseconds
it returns None
No, it fits: 2^63*10^9+999,999,999
= 9...e+27
and 2^127
= 1...e+38
your result has a negative amount of days because the nanoseconds being subtracted are bigger than the amount of seconds.
They fit with tons of extra space, right? You need only 93 bits. So you have 34 bits to spare.
2^93-(2^63*10^9+999,999,999)
= 6.80148277428e+26
. So everything fits in the 93 bits if I understand correctly.
Ah, yes, you're correct. I got the right result but interpreted the negative sign wrong!
Last updated: Jul 06 2025 at 12:14 UTC