---
slug: 31-time-random
title: Time & random
description: Timestamps and formatting (now, format_time, parse_time) and randomness (random, random_int) — note that random is deny-by-default.
example_ids: [time-random]
---

# Time & random

```synsema
-- Doc example: time & random. `time` is auto-granted; `random` is NOT (deny-by-default).
intent: "doc example: time and random"
require random

print("epoch 0 = " + format_time(0) + ",  a die roll = " + text(random_int(1, 6)))

test "format_time / parse_time round-trip (UTC, ISO-8601)"
    assert_eq(format_time(0), "1970-01-01T00:00:00Z")
    assert_eq(parse_time("1970-01-01T00:00:00Z"), 0)
    assert(now() > 1000000000)

test "random needs `require random`; values land in range"
    let r be random()
    assert(r >= 0 and r < 1)
    let d be random_int(1, 6)
    assert(d >= 1 and d <= 6)
```

## Time

`time` is auto-granted under `run`/`test` (declare `require time` under `serve`).

```synsema
now()                               -- unix timestamp (number)
format_time(now())                  -- ISO-8601 UTC by default
format_time(t, "%Y-%m-%d %H:%M")    -- strftime pattern
parse_time("2026-06-30T12:00:00Z")  -- inverse of format_time
sleep(seconds)                      -- pause
```

## Random — **deny-by-default**

Unlike many languages, `random` needs `require random` even under `run` — because randomness is used for tokens and nonces, it's a capability, not a freebie.

```synsema
require random
random()            -- float in [0, 1)
random_int(1, 6)    -- integer in [min, max]
random_bytes(16)    -- n bytes from the OS CSPRNG (engine v0.5.5+)
token()             -- 32 CSPRNG bytes as base64url — session ids, CSRF tokens
```

`random()`/`random_int()` are **not** cryptographic — anything security-related (tokens, nonces, salts) goes through `random_bytes`/`token`, which read the OS CSPRNG. Same `require random` gate for all four. More in [Login & sessions](/en/0.6.x/40a-web-auth).
