Skip to content

API Reference

/

Values

Duration

A Duration holds a length of time as a whole number of nanoseconds, and maps to the SurrealDB duration type in both directions. This page documents how to make a Duration, how to read it in other units, and how to convert a datetime.timedelta, which the SDK does not send.

Import
from surrealdb import Duration

Source: duration.py

Syntax
Duration(elapsed=0)

Parameter

Type

Description

elapsedint

The length of time in nanoseconds. Defaults to

0

.

length = Duration(5_000_000_000)
print(length.seconds, length)
Output
5 5s

SurrealDB has no negative durations, so sending a Duration with a negative elapsed raises ValueError.

Duration is a dataclass with one field.

FieldTypeDescription
elapsedintThe length of time in nanoseconds.

Duration.parse() builds a Duration from SurrealQL duration text, or from a whole number of seconds.

Syntax
Duration.parse(value, nanoseconds=0)

Parameter

Type

Description

valuestr | int

Text made of one or more parts, each a whole number and a unit, such as

"1h30m"

. An

int

is a number of seconds.

nanosecondsint

Nanoseconds to add to the result. Defaults to

0

.

Returns: Duration

The units are the ones SurrealQL uses, in lower case:

UnitMeaning
nsNanoseconds
us or µsMicroseconds
msMilliseconds
sSeconds
mMinutes
hHours
dDays
wWeeks
yYears of 365 days

parse() accepts the same text as the server. Spaces around the text are ignored, but text with a fraction ("1.5s"), a sign ("-1s"), an exponent ("1e3s") or an upper-case unit ("1H") raises InvalidDurationError, and so does a negative int.

print(Duration.parse("1h30m").minutes)
print(Duration.parse("500ms").milliseconds)
print(Duration.parse("2d12h").hours)
print(Duration.parse(90))
print(Duration.parse(90, nanoseconds=500).nanoseconds)
Output
90
500
60
1m30s
90000000500
Duration.parse("1.5s")
Error output
surrealdb.errors.InvalidDurationError: Invalid duration format: 1.5s

Each unit property gives the number of whole units in the duration as an int, rounded down. Duration.parse("1h30m").hours is 1, not 1.5.

PropertyTypeDescription
nanosecondsintThe whole duration in nanoseconds, the same value as elapsed.
microsecondsintWhole microseconds.
millisecondsintWhole milliseconds.
secondsintWhole seconds.
minutesintWhole minutes.
hoursintWhole hours.
daysintWhole days.
weeksintWhole weeks.
yearsintWhole years of 365 days.

For a fraction of a unit, divide nanoseconds by the length of the unit in nanoseconds.

length = Duration.parse("2h30m")
print(length.hours, length.minutes, length.seconds)
print(length.nanoseconds / 3_600_000_000_000)
Output
2 150 9000
2.5

to_string() returns the duration as SurrealQL duration text, with the largest units first. str(duration) gives the same text, and a zero duration gives 0ns.

Syntax
duration.to_string()

Returns: str

print(Duration.parse("90m").to_string())
print(Duration(1_500_000_000).to_string())
print(Duration().to_string())
Output
1h30m
1s500ms
0ns

to_compact() returns a list that holds the number of whole seconds. The part of a second is not included.

Syntax
duration.to_compact()

Returns: list[int]

print(Duration(1_500_000_000).to_compact())
Output
[1]

get_seconds_and_nano() returns the whole seconds and the nanoseconds left over, which are the two parts that SurrealDB stores.

Syntax
duration.get_seconds_and_nano()

Returns: tuple[int, int]

print(Duration(1_500_000_000).get_seconds_and_nano())
Output
(1, 500000000)

Two Duration values are equal when they hold the same number of nanoseconds, however they were written. A Duration is hashable, so it can be a dict key or a member of a set. repr() shows the nanoseconds.

print(Duration.parse("90m") == Duration.parse("1h30m"))
print(repr(Duration.parse("90m")))
Output
True
Duration(elapsed=5400000000000)

The SDK does not send a datetime.timedelta, and raises TypeError for one. Convert it to a Duration first. Integer division by one microsecond keeps the value exact:

import datetime as dt
from surrealdb import Duration

timeout = dt.timedelta(minutes=1, seconds=30)
length = Duration((timeout // dt.timedelta(microseconds=1)) * 1000)
print(length)
Output
1m30s

To go the other way, use dt.timedelta(microseconds=length.nanoseconds // 1000). A timedelta holds microseconds, so the nanoseconds below one microsecond are dropped.

A Duration can be a field value or a query variable, and a duration that the server returns reads back as a Duration.

from surrealdb import Duration, RecordID, Surreal

with Surreal("ws://localhost:8000") as db:
    db.signin({"username": "root", "password": "secret"})
    db.use("surrealdb", "docs")

    db.create(RecordID("account", "tobie"), {
        "session_timeout": Duration.parse("30m"),
    })

    account = db.select(RecordID("account", "tobie")).execute()
    print(repr(account["session_timeout"]))

    sql = "RETURN d'2025-01-01T00:00:00Z' + $after"
    print(db.query(sql, {"after": Duration.parse("6h")}).first())
Output
Duration(elapsed=1800000000000)
2025-01-01 06:00:00+00:00

Was this page helpful?