TimeMathType: {
    absValue: ((abs) => TimestampValue);
    addAbsRel: (<T>(abs, rel) => T extends TimestampRecord
        ? TimestampRecord
        : TimestampValue);
    addRelRel: (<T>(rel1, rel2) => T extends RelativeTimeRecord
        ? RelativeTimeRecord
        : RelativeTimeValue);
    clampedSubtractAbsAbs: ((abs1, abs2) => RelativeTime);
    coerceRelativeTimeRecord: ((rel, brand) => RelativeTimeRecord);
    coerceTimestampRecord: ((abs, brand) => TimestampRecord);
    compareAbs: ((abs1, abs2) => RankComparison);
    compareRel: ((rel1, rel2) => RankComparison);
    divideRelNat: ((rel, nat) => RelativeTime);
    divideRelRel: ((rel1, rel2) => bigint);
    isRelZero: ((rel) => boolean);
    modAbsRel: ((abs, step) => RelativeTime);
    modRelRel: ((rel, step) => RelativeTime);
    multiplyRelNat: ((rel, nat) => RelativeTime);
    relValue: ((rel) => RelativeTimeValue);
    subtractAbsAbs: ((abs1, abs2) => RelativeTime);
    subtractAbsRel: ((abs, rel) => Timestamp);
    subtractRelRel: ((rel1, rel2) => RelativeTime);
}

TimeMath supports simple arithmetic on typed Time values, enforcing that values are combined in type-compatible ways. You can add 3 minutes to 3pm, or 5 minutes to a half hour, but it makes no sense to add 3pm and 5pm. Subtracting two Timestamps does produce a useful difference.

The brands prevent you from accidentally combining time values from different TimerServices. Some chains track time in blocks, others follow wall clock time, some do both. Every local computer has its own unique notion of wall clock time. Even when these clocks are talking about the same thing (UTC), they can all drift in different ways. Using the correct brands lets you be precise about which particular source of time you mean, preventing confusion or attacks when the clocks diverge. Thus it is an error to e.g. use a time you got from chain A to schedule an event on chain B.

The basic types are RelativeTimeRecord (durations) and TimestampRecord. The numeric values can be extracted from the typed values, but it's usually better to maintain values as their canonical typed form so these operations can be applied.

Type declaration