Три типа покрывают модель времени Nova: Duration (знаковый интервал), Timestamp (момент от Unix-эпохи) и Monotonic (монотонные часы процесса). Все хранят наносекунды в одном поле i64. Методы-расширения для целых чисел и чисел с плавающей точкой позволяют писать 5.to_seconds(), 1.to_hours(), 500.to_millis() напрямую.
ro timeout = 30.to_seconds()
ro deadline = 1_700_000_000.to_unix_seconds() + timeout
ro d = 3661.to_seconds() // 1h 1min 1s
assert(d.parts().hours == 1)
Типы
Duration
стабильно с 0.1export type Duration { nanos i64 }
Знаковый временной интервал с наносекундной точностью. Диапазон: ±292 года (i64::MAX наносекунд). Поддерживает операторы арифметики, сравнения и форматирования.
Timestamp
стабильно с 0.1export type Timestamp { nanos i64 }
Момент времени, хранимый как число наносекунд от Unix-эпохи (1970-01-01 UTC). Знаковый, поэтому поддерживает даты до 1970 года. Timestamp - Timestamp даёт Duration. Методам, которым нужны текущие настенные часы, требуется эффект Time.
Monotonic
стабильно с 0.6export type Monotonic { nanos i64 }
Точка на монотонных часах процесса. Не подвержена коррекциям NTP / переходу на летнее время / ручной настройке часов. Используйте для дедлайнов таймеров, интервалов профилирования и бюджетов повторных попыток. Не может быть сериализована или сравнена между процессами.
Примеры
ro start = Monotonic.now()
// ... work ...
ro elapsed = Monotonic.now().elapsed_since(start)
Константы
const ZERO Duration = { nanos: 0 } // zero duration
const SECOND Duration = { nanos: 1_000_000_000 } // 1 second
const MINUTE Duration = { nanos: 60_000_000_000 } // 1 minute
const HOUR Duration = { nanos: 3_600_000_000_000 }
const EPOCH Timestamp = { nanos: 0 } // 1970-01-01 00:00:00 UTC
Duration — конструкторы
fn[T Ints] T @to_nanos() -> Duration // 1 ns
fn[T Ints] T @to_micros() -> Duration // 1 μs = 1_000 ns
fn[T Ints] T @to_millis() -> Duration // 1 ms = 1_000_000 ns
fn[T Ints] T @to_seconds() -> Duration // 1 s = 1_000_000_000 ns
fn[T Ints] T @to_minutes() -> Duration // 60 s
fn[T Ints] T @to_hours() -> Duration // 3600 s
fn[T Ints] T @to_days() -> Duration // 86400 s
fn[T Ints] T @to_weeks() -> Duration // 7 * 86400 s
fn f64 @to_seconds() -> Duration // e.g. 0.5 → 500ms
Duration — аксессоры
fn Duration @nanos() -> i64 // raw nanoseconds
fn Duration @micros() -> i64 // truncating
fn Duration @millis() -> i64
fn Duration @seconds() -> i64
fn Duration @minutes() -> i64
fn Duration @hours() -> i64
fn Duration @days() -> i64
fn Duration @seconds_f64() -> f64 // fractional seconds (preserves sub-second)
Примеры
assert(2.to_seconds().millis() == 2000)
assert(1500.to_millis().seconds_f64() == 1.5)
Duration — арифметика
fn Duration @plus(other Duration) -> Duration // d1 + d2
fn Duration @minus(other Duration) -> Duration // d1 - d2 (may be negative)
fn Duration @neg() -> Duration // unary -
fn Duration @abs() -> Duration // |d|
fn Duration @times(n i64) -> Duration // d * n
fn Duration @times(n f64) -> Duration
fn Duration @div(n i64) -> Duration // d / n (truncating)
fn Duration @div(n f64) -> Duration
fn Duration @ratio(other Duration) -> f64 // d1 / d2 dimensionless
Примеры
assert(1.to_hours() + 30.to_minutes() == 90.to_minutes())
assert(30.to_seconds().ratio(1.to_minutes()) == 0.5)
Duration — форматирование
fn Duration @to_str() -> str // auto-scale: "500ns" / "42ms" / "2.5s" / "5min" / "2h"
fn Duration @parts() -> DurationParts
Примеры
ro d = 3661.to_seconds() // 1h 1min 1s
ro p = d.parts()
assert(p.hours == 1 && p.minutes == 1 && p.seconds == 1)
assert(2.to_hours().to_str() == "2h")
assert(500.to_nanos().to_str() == "500ns")
Расширения целых чисел и чисел с плавающей точкой
Методы-расширения для int и f64 позволяют естественно записывать литералы длительности:
fn[T Ints] T @to_nanos() -> Duration
fn[T Ints] T @to_micros() -> Duration
fn[T Ints] T @to_millis() -> Duration
fn[T Ints] T @to_seconds() -> Duration
fn[T Ints] T @to_minutes() -> Duration
fn[T Ints] T @to_hours() -> Duration
fn[T Ints] T @to_days() -> Duration
fn[T Ints] T @to_weeks() -> Duration
fn f64 @to_seconds() -> Duration
Примеры
assert(30.to_seconds().seconds() == 30)
assert(500.to_nanos().nanos() == 500)
assert(0.5.to_seconds() == 500.to_millis())
Timestamp — конструкторы
fn[T Ints] T @to_unix_seconds() -> Timestamp
fn[T Ints] T @to_unix_millis() -> Timestamp
fn[T Ints] T @to_unix_nanos() -> Timestamp
Timestamp — арифметика
fn Timestamp @plus(d Duration) -> Timestamp // shift forward
fn Timestamp @minus(d Duration) -> Timestamp // shift back
fn Timestamp @minus(other Timestamp) -> Duration // elapsed (signed)
Примеры
ro start = 1000.to_unix_seconds()
ro deadline = start + 30.to_seconds()
assert(deadline.unix_seconds() == 1030)
assert((deadline - start) == 30.to_seconds())
Timestamp — запросы через эффект Time
Эти методы требуют эффект Time из окружающей области видимости. В тестах внедрите детерминированный обработчик:
fn Timestamp @is_past() Time -> bool
fn Timestamp @elapsed() Time -> Duration // positive if in the past
fn Timestamp @time_until() Time -> Duration // positive if in the future
fn deadline_in(d Duration) Time -> Timestamp // now() + d
Примеры
with Time = th.fixed_ms(10_000) {
ro deadline = 5.to_unix_seconds()
assert(deadline.is_past())
ro (result, elapsed) = measure(|| 42)
assert(result == 42)
assert(elapsed == Duration.ZERO) // fixed clock doesn't advance
}