From bf43dbaf5a65bbf6fcaf0d2389da703cbc364614 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 27 Nov 2025 10:14:21 +0000 Subject: [PATCH] Add `@(require_results)` to `core:time` --- core/time/iso8601.odin | 3 +++ core/time/perf.odin | 7 ++++++ core/time/rfc3339.odin | 4 ++++ core/time/time.odin | 49 +++++++++++++++++++++++++++++++++++++++--- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/core/time/iso8601.odin b/core/time/iso8601.odin index f00107226..e2341f76d 100644 --- a/core/time/iso8601.odin +++ b/core/time/iso8601.odin @@ -27,6 +27,7 @@ is specified in the string, that timezone is applied to time. - Only 4-digit years are accepted. - Leap seconds are smeared into 23:59:59. */ +@(require_results) iso8601_to_time_utc :: proc(iso_datetime: string, is_leap: ^bool = nil) -> (res: Time, consumed: int) { offset: int res, offset, consumed = iso8601_to_time_and_offset(iso_datetime, is_leap) @@ -59,6 +60,7 @@ minutes. - Only 4-digit years are accepted. - Leap seconds are smeared into 23:59:59. */ +@(require_results) iso8601_to_time_and_offset :: proc(iso_datetime: string, is_leap: ^bool = nil) -> (res: Time, utc_offset: int, consumed: int) { moment, offset, leap_second, count := iso8601_to_components(iso_datetime) if count == 0 { @@ -102,6 +104,7 @@ minutes. e.g. it'll return hour = 25 if that's what it's given in the specified string. */ +@(require_results) iso8601_to_components :: proc(iso_datetime: string) -> (res: dt.DateTime, utc_offset: int, is_leap: bool, consumed: int) { moment, offset, count, leap_second, ok := _iso8601_to_components(iso_datetime) if !ok { diff --git a/core/time/perf.odin b/core/time/perf.odin index f4e1b4aa8..c2d3890ff 100644 --- a/core/time/perf.odin +++ b/core/time/perf.odin @@ -13,6 +13,7 @@ Tick :: struct { /* Obtain the current tick. */ +@(require_results) tick_now :: proc "contextless" () -> Tick { return _tick_now() } @@ -20,6 +21,7 @@ tick_now :: proc "contextless" () -> Tick { /* Add duration to a tick. */ +@(require_results) tick_add :: proc "contextless" (t: Tick, d: Duration) -> Tick { return Tick{t._nsec + i64(d)} } @@ -27,6 +29,7 @@ tick_add :: proc "contextless" (t: Tick, d: Duration) -> Tick { /* Obtain the difference between ticks. */ +@(require_results) tick_diff :: proc "contextless" (start, end: Tick) -> Duration { d := end._nsec - start._nsec return Duration(d) @@ -43,6 +46,7 @@ then the returned duration is 0. This procedure is meant to be used in a loop, or in other scenarios, where one might want to obtain time between multiple ticks at specific points. */ +@(require_results) tick_lap_time :: proc "contextless" (prev: ^Tick) -> Duration { d: Duration t := tick_now() @@ -56,6 +60,7 @@ tick_lap_time :: proc "contextless" (prev: ^Tick) -> Duration { /* Obtain the duration since last tick. */ +@(require_results) tick_since :: proc "contextless" (start: Tick) -> Duration { return tick_diff(start, tick_now()) } @@ -101,6 +106,7 @@ This procedure checks if the CPU contains an invariant TSC (Time stamp counter). Invariant TSC is a feature of modern processors that allows them to run their TSC at a fixed frequency, independent of ACPI state, and CPU frequency. */ +@(require_results) has_invariant_tsc :: proc "contextless" () -> bool { when ODIN_ARCH == .amd64 { return x86_has_invariant_tsc() @@ -122,6 +128,7 @@ dividing the readings from TSC by the duration of the sleep. The duration of sleep can be controlled by `fallback_sleep` parameter. */ +@(require_results) tsc_frequency :: proc "contextless" (fallback_sleep := 2 * Second) -> (u64, bool) { if !has_invariant_tsc() { return 0, false diff --git a/core/time/rfc3339.odin b/core/time/rfc3339.odin index 20e8ea0bb..3e0bab916 100644 --- a/core/time/rfc3339.odin +++ b/core/time/rfc3339.odin @@ -31,6 +31,7 @@ offset applied to it. - Only 4-digit years are accepted. - Leap seconds are smeared into 23:59:59. */ +@(require_results) rfc3339_to_time_utc :: proc(rfc_datetime: string, is_leap: ^bool = nil) -> (res: Time, consumed: int) { offset: int @@ -67,6 +68,7 @@ by the RFC 3339 string. - Only 4-digit years are accepted. - Leap seconds are smeared into 23:59:59. */ +@(require_results) rfc3339_to_time_and_offset :: proc(rfc_datetime: string, is_leap: ^bool = nil) -> (res: Time, utc_offset: int, consumed: int) { moment, offset, leap_second, count := rfc3339_to_components(rfc_datetime) if count == 0 { @@ -109,6 +111,7 @@ represented by the RFC 3339 string. Performs no validation on whether components are valid, e.g. it'll return hour = 25 if that's what it's given */ +@(require_results) rfc3339_to_components :: proc(rfc_datetime: string) -> (res: dt.DateTime, utc_offset: int, is_leap: bool, consumed: int) { moment, offset, count, leap_second, ok := _rfc3339_to_components(rfc_datetime) if !ok { @@ -198,6 +201,7 @@ The boolean `ok` is false if the `time` is not a valid datetime, or if allocatin - `utc_offset`: offset in minutes wrt UTC (ie. the timezone) - `include_nanos`: whether to include nanoseconds in the result. */ +@(require_results) time_to_rfc3339 :: proc(time: Time, utc_offset : int = 0, include_nanos := true, allocator := context.allocator) -> (res: string, ok: bool) { utc_offset := utc_offset diff --git a/core/time/time.odin b/core/time/time.odin index 2af11c755..542e4d242 100644 --- a/core/time/time.odin +++ b/core/time/time.odin @@ -116,6 +116,7 @@ Stopwatch :: struct { /* Obtain the current time. */ +@(require_results) now :: proc "contextless" () -> Time { return _now() } @@ -162,6 +163,7 @@ This procedure obtains the total time, counted by the stopwatch. If the stopwatc isn't stopped at the time of calling this procedure, the time between the last start and the current time is also accounted for. */ +@(require_results) stopwatch_duration :: proc "contextless" (stopwatch: Stopwatch) -> Duration { if !stopwatch.running { return stopwatch._accumulation @@ -172,6 +174,7 @@ stopwatch_duration :: proc "contextless" (stopwatch: Stopwatch) -> Duration { /* Calculate the duration elapsed between two times. */ +@(require_results) diff :: proc "contextless" (start, end: Time) -> Duration { d := end._nsec - start._nsec return Duration(d) @@ -180,6 +183,7 @@ diff :: proc "contextless" (start, end: Time) -> Duration { /* Calculate the duration elapsed since a specific time. */ +@(require_results) since :: proc "contextless" (start: Time) -> Duration { return diff(start, now()) } @@ -187,6 +191,7 @@ since :: proc "contextless" (start: Time) -> Duration { /* Obtain the number of nanoseconds in a duration. */ +@(require_results) duration_nanoseconds :: proc "contextless" (d: Duration) -> i64 { return i64(d) } @@ -194,6 +199,7 @@ duration_nanoseconds :: proc "contextless" (d: Duration) -> i64 { /* Obtain the number of microseconds in a duration. */ +@(require_results) duration_microseconds :: proc "contextless" (d: Duration) -> f64 { return duration_seconds(d) * 1e6 } @@ -201,6 +207,7 @@ duration_microseconds :: proc "contextless" (d: Duration) -> f64 { /* Obtain the number of milliseconds in a duration. */ +@(require_results) duration_milliseconds :: proc "contextless" (d: Duration) -> f64 { return duration_seconds(d) * 1e3 } @@ -208,6 +215,7 @@ duration_milliseconds :: proc "contextless" (d: Duration) -> f64 { /* Obtain the number of seconds in a duration. */ +@(require_results) duration_seconds :: proc "contextless" (d: Duration) -> f64 { sec := d / Second nsec := d % Second @@ -217,6 +225,7 @@ duration_seconds :: proc "contextless" (d: Duration) -> f64 { /* Obtain the number of minutes in a duration. */ +@(require_results) duration_minutes :: proc "contextless" (d: Duration) -> f64 { min := d / Minute nsec := d % Minute @@ -226,6 +235,7 @@ duration_minutes :: proc "contextless" (d: Duration) -> f64 { /* Obtain the number of hours in a duration. */ +@(require_results) duration_hours :: proc "contextless" (d: Duration) -> f64 { hour := d / Hour nsec := d % Hour @@ -249,6 +259,7 @@ Returns: Example: time.duration_round(my_duration, time.Second) */ +@(require_results) duration_round :: proc "contextless" (d, m: Duration) -> Duration { _less_than_half :: #force_inline proc "contextless" (x, y: Duration) -> bool { return u64(x)+u64(x) < u64(y) @@ -295,6 +306,7 @@ Returns: Example: time.duration_round(my_duration, time.Second) */ +@(require_results) duration_truncate :: proc "contextless" (d, m: Duration) -> Duration { return d if m <= 0 else d - d%m } @@ -302,6 +314,7 @@ duration_truncate :: proc "contextless" (d, m: Duration) -> Duration { /* Parse time into date components. */ +@(require_results) date :: proc "contextless" (t: Time) -> (year: int, month: Month, day: int) { year, month, day, _ = _abs_date(_time_abs(t), true) return @@ -310,6 +323,7 @@ date :: proc "contextless" (t: Time) -> (year: int, month: Month, day: int) { /* Obtain the year of the date specified by time. */ +@(require_results) year :: proc "contextless" (t: Time) -> (year: int) { year, _, _, _ = _date(t, true) return @@ -318,6 +332,7 @@ year :: proc "contextless" (t: Time) -> (year: int) { /* Obtain the month of the date specified by time. */ +@(require_results) month :: proc "contextless" (t: Time) -> (month: Month) { _, month, _, _ = _date(t, true) return @@ -326,6 +341,7 @@ month :: proc "contextless" (t: Time) -> (month: Month) { /* Obtain the day of the date specified by time. */ +@(require_results) day :: proc "contextless" (t: Time) -> (day: int) { _, _, day, _ = _date(t, true) return @@ -334,6 +350,7 @@ day :: proc "contextless" (t: Time) -> (day: int) { /* Obtain the week day of the date specified by time. */ +@(require_results) weekday :: proc "contextless" (t: Time) -> (weekday: Weekday) { abs := _time_abs(t) sec := (abs + u64(Weekday.Monday) * SECONDS_PER_DAY) % SECONDS_PER_WEEK @@ -353,6 +370,7 @@ precise_clock :: proc { precise_clock_from_time, precise_clock_from_duration, pr /* Obtain the time components from a time. */ +@(require_results) clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) { hour, min, sec, _ = precise_clock_from_time(t) return @@ -361,6 +379,7 @@ clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) { /* Obtain the time components from a time, including nanoseconds. */ +@(require_results) precise_clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec, nanos: int) { // Time in nanoseconds since 1-1-1970 00:00 _sec, _nanos := t._nsec / 1e9, t._nsec % 1e9 @@ -377,6 +396,7 @@ precise_clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec, nano /* Obtain the time components from a duration. */ +@(require_results) clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, sec: int) { return clock_from_seconds(u64(d/1e9)) } @@ -384,6 +404,7 @@ clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, sec: int) /* Obtain the time components from a duration, including nanoseconds. */ +@(require_results) precise_clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, sec, nanos: int) { return precise_clock_from_time({_nsec=i64(d)}) } @@ -391,6 +412,7 @@ precise_clock_from_duration :: proc "contextless" (d: Duration) -> (hour, min, s /* Obtain the time components from a stopwatch's total. */ +@(require_results) clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, sec: int) { return clock_from_duration(stopwatch_duration(s)) } @@ -398,6 +420,7 @@ clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, sec: in /* Obtain the time components from a stopwatch's total, including nanoseconds */ +@(require_results) precise_clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, sec, nanos: int) { return precise_clock_from_duration(stopwatch_duration(s)) } @@ -405,6 +428,7 @@ precise_clock_from_stopwatch :: proc "contextless" (s: Stopwatch) -> (hour, min, /* Obtain the time components from the number of seconds. */ +@(require_results) clock_from_seconds :: proc "contextless" (in_sec: u64) -> (hour, min, sec: int) { sec = int(in_sec % SECONDS_PER_DAY) hour = sec / SECONDS_PER_HOUR @@ -436,6 +460,7 @@ Example: now := time.now() fmt.println(time.to_string_hms(now, buf[:])) */ +@(require_results) time_to_string_hms :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_HMS_LEN) h, m, s := clock(t) @@ -469,6 +494,7 @@ Example: d := time.since(earlier) fmt.println(time.to_string_hms(now, buf[:])) */ +@(require_results) duration_to_string_hms :: proc(d: Duration, buf: []u8) -> (res: string) #no_bounds_check { return time_to_string_hms(Time{_nsec=i64(d)}, buf) } @@ -494,6 +520,7 @@ Example: fmt.println(time.to_string_hms_12(now, buf[:])) fmt.println(time.to_string_hms_12(now, buf[:], {"㏂", "㏘"})) */ +@(require_results) to_string_hms_12 :: proc(t: Time, buf: []u8, ampm: [2]string = {" am", " pm"}) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_HMS_LEN + max(len(ampm[0]), len(ampm[1]))) h, m, s := clock(t) @@ -532,6 +559,7 @@ Example: now := time.now() fmt.println(time.to_string_yyyy_mm_dd(now, buf[:])) */ +@(require_results) to_string_yyyy_mm_dd :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YYYY_DATE_LEN) y, _m, d := date(t) @@ -566,6 +594,7 @@ Example: now := time.now() fmt.println(time.to_string_yy_mm_dd(now, buf[:])) */ +@(require_results) to_string_yy_mm_dd :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YY_DATE_LEN) y, _m, d := date(t) @@ -598,6 +627,7 @@ Example: now := time.now() fmt.println(time.to_string_dd_mm_yyyy(now, buf[:])) */ +@(require_results) to_string_dd_mm_yyyy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YYYY_DATE_LEN) y, _m, d := date(t) @@ -632,6 +662,7 @@ Example: now := time.now() fmt.println(time.to_string_dd_mm_yy(now, buf[:])) */ +@(require_results) to_string_dd_mm_yy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YY_DATE_LEN) y, _m, d := date(t) @@ -664,6 +695,7 @@ Example: now := time.now() fmt.println(time.to_string_mm_dd_yyyy(now, buf[:])) */ +@(require_results) to_string_mm_dd_yyyy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YYYY_DATE_LEN) y, _m, d := date(t) @@ -698,6 +730,7 @@ Example: now := time.now() fmt.println(time.to_string_mm_dd_yy(now, buf[:])) */ +@(require_results) to_string_mm_dd_yy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check { assert(len(buf) >= MIN_YY_DATE_LEN) y, _m, d := date(t) @@ -718,6 +751,7 @@ to_string_mm_dd_yy :: proc(t: Time, buf: []u8) -> (res: string) #no_bounds_check /* Read the timestamp counter of the CPU. */ +@(require_results) read_cycle_counter :: proc "contextless" () -> u64 { return u64(intrinsics.read_cycle_counter()) } @@ -725,6 +759,7 @@ read_cycle_counter :: proc "contextless" () -> u64 { /* Obtain time from unix seconds and unix nanoseconds. */ +@(require_results) unix :: proc "contextless" (sec: i64, nsec: i64) -> Time { sec, nsec := sec, nsec if nsec < 0 || nsec >= 1e9 { @@ -742,6 +777,7 @@ unix :: proc "contextless" (sec: i64, nsec: i64) -> Time { /* Obtain time from unix nanoseconds. */ +@(require_results) from_nanoseconds :: #force_inline proc "contextless" (nsec: i64) -> Time { return Time{nsec} } @@ -754,6 +790,7 @@ to_unix_seconds :: time_to_unix /* Obtain the Unix timestamp in seconds from a Time. */ +@(require_results) time_to_unix :: proc "contextless" (t: Time) -> i64 { return t._nsec/1e9 } @@ -766,6 +803,7 @@ to_unix_nanoseconds :: time_to_unix_nano /* Obtain the Unix timestamp in nanoseconds from a Time. */ +@(require_results) time_to_unix_nano :: proc "contextless" (t: Time) -> i64 { return t._nsec } @@ -773,6 +811,7 @@ time_to_unix_nano :: proc "contextless" (t: Time) -> i64 { /* Add duration to a time. */ +@(require_results) time_add :: proc "contextless" (t: Time, d: Duration) -> Time { return Time{t._nsec + i64(d)} } @@ -839,18 +878,18 @@ UNIX_TO_ABSOLUTE :: UNIX_TO_INTERNAL + INTERNAL_TO_ABSOLUTE ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE -@(private) +@(private, require_results) _date :: proc "contextless" (t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) { year, month, day, yday = _abs_date(_time_abs(t), full) return } -@(private) +@(private, require_results) _time_abs :: proc "contextless" (t: Time) -> u64 { return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE) } -@(private) +@(private, require_results) _abs_date :: proc "contextless" (abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) { d := abs / SECONDS_PER_DAY @@ -916,6 +955,7 @@ This procedure calculates the time from datetime components supplied in the arguments to this procedure. If the datetime components don't represent a valid datetime, the function returns `false` in the second argument. */ +@(require_results) components_to_time :: proc "contextless" (#any_int year, #any_int month, #any_int day, #any_int hour, #any_int minute, #any_int second: i64, #any_int nsec := i64(0)) -> (t: Time, ok: bool) #optional_ok { this_date, err := dt.components_to_datetime(year, month, day, hour, minute, second, nsec) if err != .None { @@ -930,6 +970,7 @@ Convert datetime into time. If the datetime represents a time outside of a valid range, `false` is returned as the second return value. See `Time` for the representable range. */ +@(require_results) compound_to_time :: proc "contextless" (datetime: dt.DateTime) -> (t: Time, ok: bool) { unix_epoch := dt.DateTime{{1970, 1, 1}, {0, 0, 0, 0}, nil} delta, err := dt.sub(datetime, unix_epoch) @@ -958,6 +999,7 @@ datetime_to_time :: proc{components_to_time, compound_to_time} /* Convert time into datetime. */ +@(require_results) time_to_datetime :: proc "contextless" (t: Time) -> (dt.DateTime, bool) { unix_epoch := dt.DateTime{{1970, 1, 1}, {0, 0, 0, 0}, nil} @@ -976,6 +1018,7 @@ time_to_compound :: time_to_datetime /* Check if a year is a leap year. */ +@(require_results) is_leap_year :: proc "contextless" (year: int) -> (leap: bool) { return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) }