diff --git a/examples/datetime_human_tests.nbt b/examples/datetime_human_tests.nbt index c8a4fd99..535ffc91 100644 --- a/examples/datetime_human_tests.nbt +++ b/examples/datetime_human_tests.nbt @@ -23,17 +23,17 @@ assert((1 week -> human) == "7 days") assert((1.5 weeks -> human) == "10 days + 12 hours") assert((2 weeks -> human) == "14 days") -assert((2 month -> human) == "2 months") -assert((3 yr + 2 month -> human) == "3 years + 2 months") -assert((10 yr + 2 s -> human) == "10 years + 2 seconds") +assert((2 month -> human) == "60 days + 20 hours + 58 minutes + 7.509 seconds (approx. 2 months)") +assert((3 yr + 2 month -> human) == "1156 days + 14 hours + 24 minutes + 22.664 seconds (approx. 3 years + 2 months)") +assert((10 yr + 2 s -> human) == "3652 days + 10 hours + 7 minutes + 32.518 seconds (approx. 10 years + 2 seconds)") assert((1 sidereal_day -> human) == "23 hours + 56 minutes + 4.091 seconds") -assert((10000 days -> human) == "27 years + 4 months + 16 days + 17 hours + 7 minutes + 28.583 seconds") -assert((50 million days -> human) == "136_895 years + 5 months + 18 days + 11 hours + 25 minutes + 9.591 seconds") +assert((10000 days -> human) == "10000 days (approx. 27 years + 4 months + 16 days + 17 hours + 7 minutes + 28.583 seconds)") +assert((50 million days -> human) == "50_000_000 days (approx. 136_895 years + 5 months + 18 days + 11 hours + 25 minutes + 9.591 seconds)") -assert((1e12 days -> human) == "2_737_909_345 years + 12 days + 18 hours + 17 minutes + 24.141 seconds") -assert((1e15 days -> human) == "2_737_909_345_034 years + 11 months + 8 days + 22 hours + 40 minutes + 18.702 seconds") +assert((1e12 days -> human) == "1_000_000_000_000 days (approx. 2_737_909_345 years + 12 days + 18 hours + 17 minutes + 24.141 seconds)") +assert((1e15 days -> human) == "1.0e+15 days (approx. 2_737_909_345_034 years + 11 months + 8 days + 22 hours + 40 minutes + 18.702 seconds)") assert((1 ms -> human) == "0.001 seconds") assert((1 µs -> human) == "0.000001 seconds") diff --git a/numbat/modules/datetime/human.nbt b/numbat/modules/datetime/human.nbt index 6bd6bea8..faadd313 100644 --- a/numbat/modules/datetime/human.nbt +++ b/numbat/modules/datetime/human.nbt @@ -19,8 +19,6 @@ fn _human_hours(time: Time) -> String = "{(time -> hours) / hour // floor fn _human_minutes(time: Time) -> String = "{(time -> minutes) / minute // floor} minutes" -> _prettier fn _human_seconds(time: Time) -> String = str_replace("{(time -> seconds) / second} seconds", ".0 ", " ") -> _prettier -fn _human_manage_past(str: String, time: Time) = str_append(str, if time < 0 s then " ago" else "") - fn _human_recurse(t: Time, result: String, time_unit: String) -> String = if time_unit == "year" then _human_recurse(t - (t -> year // floor) -> ms // round, _human_join(result, t -> _human_years), "month") @@ -33,10 +31,17 @@ fn _human_recurse(t: Time, result: String, time_unit: String) -> String = else if time_unit == "minute" then _human_recurse(t - (t -> min // floor) -> ms // round, _human_join(result, t -> _human_minutes), "second") else _human_join(result, (t -> ms // round) -> _human_seconds) -# The seconds are roundother calculsed for durations larger than 1 month because -# we run into floating point precision problems at the nanosecond level at this point + +fn _human_manage_past(str: String, time: Time) = str_append(str, if time < 0 s then " ago" else "") + +fn _human_with_biggest_unit(time: Time, biggest_unit: String) -> String = + _human_manage_past(_human_recurse(abs(time), "", biggest_unit), time) + +fn _human_for_long_duration(human_days: String, human_years: String) -> String = + "{human_days} (approx. {human_years})" fn human(time: Time) -> String = if time == 0 s then "0 seconds" - else if abs(time) < 60 s then _human_manage_past(abs(time) -> _human_seconds, time) - else _human_manage_past(_human_recurse(abs(time), "", "year"), time) + else if abs(time) < 60 seconds then _human_manage_past(abs(time) -> _human_seconds, time) + else if abs(time) < 2 months then _human_with_biggest_unit(time, "day") + else _human_for_long_duration(_human_with_biggest_unit(time, "day"), _human_with_biggest_unit(time, "year"))