Add @(require_results) to core:time

This commit is contained in:
gingerBill
2025-11-27 10:14:21 +00:00
parent 0b4884ada4
commit bf43dbaf5a
4 changed files with 60 additions and 3 deletions

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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)
}