Files
regorus/docs/knowledge/time-builtins-compat.md
copilot-swe-agent[bot] 524aab5528 Add knowledge docs, agent definitions, and skill files
Add comprehensive documentation and GitHub Copilot configuration:

- docs/knowledge/: 17 deep-dive knowledge files covering value semantics,
  RVM architecture, builtins, FFI boundary, feature composition, error
  handling migration, policy evaluation security, Rego semantics,
  interpreter/compiler architecture, Azure Policy/RBAC, engine API,
  time builtins, language extension guide, tooling architecture,
  causality/partial eval, Rego compiler, Azure Policy aliases, and
  telemetry/diagnostics

- .github/agents/: 16 role-specific AI agent definitions (red-teamer,
  semantics-expert, architect, performance-engineer, test-engineer,
  verification-engineer, security-auditor, reliability-engineer,
  support-engineer, ci-engineer, refactorer, api-steward, program-manager,
  demo-engineer, dx-engineer, tech-lead)

- .github/skills/: 6 workflow skill definitions (thorough-review,
  design-alternatives, add-builtin, opa-conformance, security-review,
  verification)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: anakrish <35780660+anakrish@users.noreply.github.com>
2026-04-25 21:20:10 +00:00

5.1 KiB

Knowledge: Time Builtins Compatibility

Deep knowledge about the time builtin functions, especially the Go time.Parse compatibility layer. Read this before modifying src/builtins/time/ or any time-related builtins.

Architecture

src/builtins/
  time.rs              Main time builtins (303 lines)
  time/
    compat.rs          Go time.Parse compatibility layer (1,359 lines)
    diff.rs            Time difference calculation (83 lines)

compat.rs is the single most complex builtin module in the codebase.

Why Go Compatibility Matters

OPA is written in Go and uses Go's time.Parse() function. Go's time parsing is fundamentally different from standard approaches:

Standard (C, Rust, Python): format strings with %Y, %m, %d etc.

Go: uses a reference time as the layout. The reference time is:

Mon Jan 2 15:04:05 MST 2006

This specific date/time was chosen because each component is unique:

  • Month: January (1)
  • Day: 2
  • Hour: 15 (3 PM)
  • Minute: 04
  • Second: 05
  • Year: 2006
  • Timezone: MST

OPA test cases use Go layouts, so regorus must parse and format times using this same convention to pass conformance tests.

The compat.rs Module

This is essentially a Rust port of Go's time parsing logic. Key functions:

parse(layout, value) → Parsed time

Implements Go's time.Parse():

  1. Scans the layout string for known reference time components
  2. Extracts corresponding values from the input string
  3. Handles timezone parsing, AM/PM, fractional seconds
  4. Returns a Chrono DateTime or NaiveDateTime

format(time, layout) → Formatted string

Implements Go's time.Format():

  1. Scans the layout string for reference time components
  2. Substitutes actual time values
  3. Handles timezone abbreviation, offset formatting

parse_duration(s) → Duration

Parses Go-style duration strings: "10h12m45s", "1.5h", "300ms". Go's duration format is different from ISO 8601.

Tricky Aspects

Missing Components

Go's time.Parse allows missing year or time components. Chrono is stricter. The compatibility layer fills in defaults:

  • Missing year → 0 (or current year depending on context)
  • Missing time → 00:00:00
  • Missing timezone → UTC

Timezone Parsing

Go has a custom timezone parsing approach that differs from standard timezone databases. The compatibility layer handles:

  • Named timezones (MST, EST, PST)
  • Numeric offsets (+0700, -05:00)
  • Legacy formats
  • parse_legacy_timezone() for OPA-specific timezone handling

Fractional Seconds

Go layouts use .000 for milliseconds, .000000 for microseconds, .000000000 for nanoseconds. The number of zeros determines precision. The parser must count zeros to know the precision.

Lint Suppressions

compat.rs suppresses several lints:

  • clippy::arithmetic_side_effects — ported Go code uses arithmetic directly
  • clippy::unseparated_literal_suffix — literal style from Go port
  • clippy::pattern_type_mismatch

This is intentional — the module is a faithful port and the arithmetic has been verified in the original Go implementation.

Main Time Builtins (time.rs)

Function Purpose Complexity
time.now_ns() Current time in nanoseconds Low
time.parse_rfc3339_ns() Parse RFC 3339 timestamp Low
time.parse_ns() Parse with Go layout → nanoseconds High (uses compat.rs)
time.parse_duration_ns() Parse Go duration string Medium
time.format() Format with Go layout High (uses compat.rs)
time.date() Extract year/month/day Medium
time.clock() Extract hour/minute/second Medium
time.weekday() Day of week string Low
time.add_date() Date arithmetic Medium
time.diff() Time difference Medium

Date Arithmetic

time.add_date() uses checked arithmetic:

  • checked_add() and checked_sub_months() for year/month bounds
  • Leap year adjustments
  • Returns Undefined on overflow (OPA compatibility)

Nanosecond Precision

All time functions work with nanosecond timestamps internally. safe_timestamp_nanos() prevents overflow when converting from seconds to nanoseconds.

Predefined Format Layouts

layout_with_predefined_formats() maps OPA layout names to Chrono formats:

  • RFC 3339, RFC 822, RFC 850
  • ANSIC, Unix, Kitchen, Stamp formats
  • These must match OPA's predefined layouts exactly

OPA Conformance

Time builtins are a rich source of conformance edge cases:

  1. Go layout parsing must match Go's behavior exactly
  2. Nanosecond overflow must return Undefined, not error
  3. Timezone names must be recognized consistently
  4. Duration parsing must handle Go's format (not ISO 8601)
  5. Date arithmetic edge cases (Feb 29, month overflow)

Dependencies

  • chrono — date/time handling (feature-gated behind time)
  • chrono-tz — timezone database (feature-gated behind time)

Both are optional dependencies. Time builtins are not available in no_std or opa-no-std configurations.