From d07975335d6f1635a23848fb16427a286d0e4e6e Mon Sep 17 00:00:00 2001 From: Miccah Date: Sun, 19 Dec 2021 11:32:42 -0600 Subject: [PATCH] time: add Duration.str() (#12897) * time: add str() method to Duration * add Duration.str tests, move time.infinite to time.v, to be visible to the JS backend Co-authored-by: Delyan Angelov --- vlib/time/duration_test.v | 33 ++++++++++++++++++++++ vlib/time/time.c.v | 4 --- vlib/time/time.v | 59 +++++++++++++++++++++++++++++++++------ 3 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 vlib/time/duration_test.v diff --git a/vlib/time/duration_test.v b/vlib/time/duration_test.v new file mode 100644 index 0000000000..b4fb2d8397 --- /dev/null +++ b/vlib/time/duration_test.v @@ -0,0 +1,33 @@ +import time + +fn test_duration_str() { + assert time.Duration(1 * time.nanosecond).str() == '1ns' + assert time.Duration(999 * time.nanosecond).str() == '999ns' + assert time.Duration(1000 * time.nanosecond).str() == '1.000us' + // + assert time.Duration(1 * time.microsecond).str() == '1.000us' + assert time.Duration(999 * time.microsecond).str() == '999.000us' + assert time.Duration(1000 * time.microsecond).str() == '1.000ms' + // + assert time.Duration(1 * time.second).str() == '1.000s' + assert time.Duration(999 * time.second).str() == '16:39.000' + assert time.Duration(1000 * time.second).str() == '16:40.000' + // + assert time.Duration(1 * time.minute).str() == '1:00.000' + assert time.Duration(999 * time.minute).str() == '16:39:00' + assert time.Duration(1000 * time.minute).str() == '16:40:00' + // + assert time.Duration(1 * time.hour).str() == '1:00:00' + assert time.Duration(999 * time.hour).str() == '999:00:00' + assert time.Duration(1000 * time.hour).str() == '1000:00:00' + // + assert time.Duration(1 * time.microsecond + 7 * time.nanosecond).str() == '1.007us' + // + assert time.Duration(1 * time.second + 5 * time.nanosecond).str() == '1.000s' + assert time.Duration(1 * time.second + 5 * time.microsecond).str() == '1.000s' + assert time.Duration(1 * time.second + 5 * time.millisecond).str() == '1.005s' + // + assert time.Duration(1 * time.hour + 5 * time.millisecond).str() == '1:00:00' + assert time.Duration(1 * time.hour + 5 * time.second).str() == '1:00:05' + assert time.Duration(168 * time.hour + 5 * time.minute + 7 * time.second).str() == '168:05:07' +} diff --git a/vlib/time/time.c.v b/vlib/time/time.c.v index 1bee15046c..89d2142752 100644 --- a/vlib/time/time.c.v +++ b/vlib/time/time.c.v @@ -119,7 +119,3 @@ fn convert_ctime(t C.tm, microsecond int) Time { unix: make_unix_time(t) } } - -pub const ( - infinite = Duration(C.INT64_MAX) -) diff --git a/vlib/time/time.v b/vlib/time/time.v index 6e445c0f07..3a7eff3a59 100644 --- a/vlib/time/time.v +++ b/vlib/time/time.v @@ -7,7 +7,7 @@ pub const ( // The unsigned zero year for internal calculations. // Must be 1 mod 400, and times before it will not compute correctly, // but otherwise can be changed at will. - absolute_zero_year = i64(-292277022399) // as i64 + absolute_zero_year = i64(-292277022399) seconds_per_minute = 60 seconds_per_hour = 60 * seconds_per_minute seconds_per_day = 24 * seconds_per_hour @@ -258,14 +258,19 @@ pub fn (t Time) debug() string { // A lot of these are taken from the Go library. pub type Duration = i64 -pub const ( - nanosecond = Duration(1) - microsecond = Duration(1000 * nanosecond) - millisecond = Duration(1000 * microsecond) - second = Duration(1000 * millisecond) - minute = Duration(60 * second) - hour = Duration(60 * minute) -) +pub const nanosecond = Duration(1) + +pub const microsecond = Duration(1000 * nanosecond) + +pub const millisecond = Duration(1000 * microsecond) + +pub const second = Duration(1000 * millisecond) + +pub const minute = Duration(60 * second) + +pub const hour = Duration(60 * minute) + +pub const infinite = Duration(i64(9223372036854775807)) // nanoseconds returns the duration as an integer number of nanoseconds. pub fn (d Duration) nanoseconds() i64 { @@ -305,6 +310,42 @@ pub fn (d Duration) hours() f64 { return f64(hr) + f64(nsec) / (60 * 60 * 1e9) } +// str pretty prints the duration. +pub fn (d Duration) str() string { + if d == time.infinite { + return 'inf' + } + mut t := i64(d) + hr := t / time.hour + t -= hr * time.hour + min := t / time.minute + t -= min * time.minute + sec := t / time.second + t -= sec * time.second + ms := t / time.millisecond + t -= ms * time.millisecond + us := t / time.microsecond + t -= us * time.microsecond + ns := t + + if hr > 0 { + return '$hr:${min:02}:${sec:02}' + } + if min > 0 { + return '$min:${sec:02}.${ms:03}' + } + if sec > 0 { + return '${sec}.${ms:03}s' + } + if ms > 0 { + return '${ms}.${us:03}ms' + } + if us > 0 { + return '${us}.${ns:03}us' + } + return '${ns}ns' +} + // offset returns time zone UTC offset in seconds. pub fn offset() int { t := now()