Cerial
Field Types

Duration

Duration field type in Cerial — CerialDuration wrapper class with unit accessors, comparison, and time duration parsing.

A time duration stored as SurrealDB's native duration type. Durations represent spans of time like 2h30m, 1w3d, or 500ms. Output is a CerialDuration instance with unit accessors; input accepts string notation, CerialDuration, or the SDK Duration type.

Schema Syntax

model Task {
  id Record @id
  ttl Duration
  timeout Duration?
  cooldown Duration @nullable
  intervals Duration[]
}

Types

DirectionType
OutputCerialDuration
InputCerialDurationInputstring | CerialDuration | Duration (SDK)
SurrealDBduration

Duration String Format

Duration strings use one or more unit segments concatenated together:

UnitSuffixExample
Yearsy1y
Weeksw2w
Daysd3d
Hoursh12h
Minutesm30m
Secondss45s
Millisecondsms500ms
Microsecondsus / µs100us
Nanosecondsns250ns

Compound durations: 1h30m, 2d12h, 1w3d2h30m15s

SurrealDB normalizes durations — for example, 7d becomes 1w, and 24h becomes 1d.

CerialDuration API

import { CerialDuration } from 'cerial';

// Create from string
const dur = new CerialDuration('2h30m');

// Static constructors
CerialDuration.from(input);    // from any CerialDurationInput
CerialDuration.parse(input);   // alias for from()

// Accessors — return TOTAL in each unit
dur.years;                     // total years
dur.weeks;                     // total weeks
dur.days;                      // total days
dur.hours;                     // total hours (e.g., 2 for '2h30m')
dur.minutes;                   // total minutes (e.g., 150 for '2h30m')
dur.seconds;                   // total seconds
dur.milliseconds;              // total milliseconds
dur.microseconds;              // total microseconds
dur.nanoseconds;               // total nanoseconds

// Serialization
dur.toString();                // '2h30m'
dur.toJSON();                  // same as toString()
dur.valueOf();                 // total milliseconds as number

// Comparison
dur.equals(other);             // compare with any CerialDurationInput
dur.compareTo(other);          // negative/zero/positive number

// SDK interop
dur.toNative();                // SDK Duration instance
dur.clone();                   // new CerialDuration copy

// Type guard
CerialDuration.is(value);     // value is CerialDuration

Duration accessors return the total in that unit, not the component. For '2h30m':

  • .hours2 (total hours, truncated)
  • .minutes150 (total minutes, not "the 30 minute part")

There is no built-in way to extract just the minutes component. If you need components, parse .toString() yourself.

Create & Update

// Create with string
const task = await client.db.Task.create({
  data: { ttl: '2h30m', cooldown: null },
});

// Create with CerialDuration
const task2 = await client.db.Task.create({
  data: { ttl: CerialDuration.from('1h15m'), cooldown: '5m' },
});

// Output is CerialDuration
task.ttl;               // CerialDuration instance
task.ttl.toString();    // '2h30m'
task.ttl.hours;         // 2
task.ttl.minutes;       // 150

// Update
await client.db.Task.updateUnique({
  where: { id: task.id },
  data: { ttl: '4h' },
});

// Array push
await client.db.Task.updateUnique({
  where: { id: task.id },
  data: { intervals: { push: '5m' } },
});

Filtering

Duration fields support comparison, set, and range operators:

// Direct equality
const tasks = await client.db.Task.findMany({
  where: { ttl: '2h' },
});

// Comparison operators
const longTasks = await client.db.Task.findMany({
  where: { ttl: { gt: '1h', lte: '24h' } },
});

// Set operators
const specific = await client.db.Task.findMany({
  where: { ttl: { in: ['30m', '1h', '2h'] } },
});

// Range
const midRange = await client.db.Task.findMany({
  where: { ttl: { between: ['1h', '12h'] } },
});

Available Operators

OperatorDescription
eqEqual to
neqNot equal to
gtGreater than
gteGreater than or equal
ltLess than
lteLess than or equal
betweenWithin a range (inclusive)
inIn a set of values
notInNot in a set of values

Conditional Operators

OperatorAvailable whenDescription
not? or @nullableNegated comparison
isNone? (optional)true = field is absent
isNull@nullabletrue = field is null
isDefinedAlwaystrue = field exists

OrderBy

Duration fields support orderBy. Durations are compared by their total time value.

const sorted = await client.db.Task.findMany({
  orderBy: { ttl: 'asc' },
});

In Objects and Tuples

object RetryConfig {
  delay Duration
  maxWait Duration?
}

tuple TimeWindow {
  start Duration,
  end Duration
}

model Job {
  id Record @id
  retry RetryConfig
  window TimeWindow
}

Supported Decorators

DecoratorEffect
@default(value)Default duration on create (e.g., @default(1h))
@defaultAlways(value)Reset to value on every write
@nullableAllow explicit null
@readonlyWrite-once field
@indexDatabase index
@uniqueUnique constraint

Duration @default values are written unquoted in migrations: @default(1h30m) produces DEFAULT 1h30m in SurrealQL (not DEFAULT '1h30m').

On this page