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>
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():
- Scans the layout string for known reference time components
- Extracts corresponding values from the input string
- Handles timezone parsing, AM/PM, fractional seconds
- Returns a Chrono
DateTimeorNaiveDateTime
format(time, layout) → Formatted string
Implements Go's time.Format():
- Scans the layout string for reference time components
- Substitutes actual time values
- 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 directlyclippy::unseparated_literal_suffix— literal style from Go portclippy::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()andchecked_sub_months()for year/month bounds- Leap year adjustments
- Returns
Undefinedon 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:
- Go layout parsing must match Go's behavior exactly
- Nanosecond overflow must return
Undefined, not error - Timezone names must be recognized consistently
- Duration parsing must handle Go's format (not ISO 8601)
- Date arithmetic edge cases (Feb 29, month overflow)
Dependencies
chrono— date/time handling (feature-gated behindtime)chrono-tz— timezone database (feature-gated behindtime)
Both are optional dependencies. Time builtins are not available in no_std
or opa-no-std configurations.