Time
Function | Description | Meta |
---|---|---|
time. |
Returns the nanoseconds since epoch after adding years, months and days to nanoseconds. Month & day values outside their usual ranges after the operation and will be normalized - for example, October 32 would become November 1. Arguments: Returns:ns (number)nanoseconds since the epoch years (number)number of years to add months (number)number of months to add days (number)number of days to add output (number)nanoseconds since the epoch representing the input time, with years, months and days added | v0.19.0 SDK-dependent |
time. |
Returns the Arguments: Returns:x (any<number, array<number, string>>)a number representing the nanoseconds since the epoch (UTC); or a two-element array of the nanoseconds, and a timezone string output (array<number, number, number>)the | SDK-dependent |
time. |
Returns the Arguments: Returns:x (any<number, array<number, string>>)a number representing the nanoseconds since the epoch (UTC); or a two-element array of the nanoseconds, and a timezone string date (array<number, number, number>)an array of | SDK-dependent |
time. |
Returns the difference between two unix timestamps in nanoseconds (with optional timezone strings). Arguments: Returns:ns1 (any<number, array<number, string>>)nanoseconds since the epoch; or a two-element array of the nanoseconds, and a timezone string ns2 (any<number, array<number, string>>)nanoseconds since the epoch; or a two-element array of the nanoseconds, and a timezone string output (array<number, number, number, number, number, number>)difference between | v0.28.0 SDK-dependent |
time. |
Returns the formatted timestamp for the nanoseconds since epoch. Arguments: Returns:x (any<number, array<number, string>, array<number, string, string>>)a number representing the nanoseconds since the epoch (UTC); or a two-element array of the nanoseconds, and a timezone string; or a three-element array of ns, timezone string and a layout string or golang defined formatting constant (see golang supported time formats) formatted timestamp (string)the formatted timestamp represented for the nanoseconds since the epoch in the supplied timezone (or UTC) | v0.48.0 SDK-dependent |
time. |
Returns the current time since epoch in nanoseconds. Returns:now (number)nanoseconds since epoch | SDK-dependent |
time. |
Returns the duration in nanoseconds represented by a string. Arguments: Returns:duration (string)a duration like "3m"; see the Go ns (number)the | SDK-dependent |
time. |
Returns the time in nanoseconds parsed from the string in the given format. Arguments: Returns:layout (string)format used for parsing, see the Go value (string)input to parse according to ns (number)
| SDK-dependent |
time. |
Returns the time in nanoseconds parsed from the string in RFC3339 format. Arguments: Returns:value (string)input string to parse in RFC3339 format ns (number)
| SDK-dependent |
time. |
Returns the day of the week (Monday, Tuesday, ...) for the nanoseconds since epoch. Arguments: Returns:x (any<number, array<number, string>>)a number representing the nanoseconds since the epoch (UTC); or a two-element array of the nanoseconds, and a timezone string day (string)the weekday represented by | SDK-dependent |
Multiple calls to the time.now_ns
built-in function within a single policy
evaluation query will always return the same value.
Timezones can be specified as
- an IANA Time Zone string e.g. "America/New_York"
- "UTC" or "", which are equivalent to not passing a timezone (i.e. will return as UTC)
- "Local", which will use the local timezone.
Note that OPA will use the time/tzdata
data if none is present on the runtime filesystem (see the
Go time.LoadLocation()
documentation for more information).
Timestamp Parsing
OPA can parse timestamps of nearly arbitrary formats, and currently accepts the same inputs as Go's time.Parse()
utility.
As a result, either you will pass a supported constant, or you must describe the format of your timestamps using the Reference Timestamp that Go's time
module expects:
2006-01-02T15:04:05Z07:00
In other date formats, that same value is rendered as:
- January 2, 15:04:05, 2006, in time zone seven hours west of GMT
- Unix time:
1136239445
- Unix
date
command output:Mon Jan 2 15:04:05 MST 2006
- RFC3339 timestamp:
2006-01-02T15:04:05Z07:00
Examples of valid values for each timestamp field:
- Year:
"2006"
"06"
- Month:
"Jan"
"January"
"01"
"1"
- Day of the week:
"Mon"
"Monday"
- Day of the month:
"2"
"_2"
"02"
- Day of the year:
"__2"
"002"
- Hour:
"15"
"3"
"03"
(PM or AM) - Minute:
"4"
"04"
- Second:
"5"
"05"
- AM/PM mark:
"PM"
For supported constants, formatting of nanoseconds, time zones, and other fields, see the Go time/format
module documentation.
Examples
clock
time.clock
is Rego's built-in function that returns the 'clock time'
(hours, minutes, seconds) for a given time in nanoseconds and timezone.
This is most useful for creating policy that's relative to a user's local time, or showing time-based information in a human-readable format in error messages that are shown to the user.
Grant access during local business hours
A common attribute-based access control (ABAC) requirement is to grant access based on time. This is typically done by determining the user's local time and ensuring it falls within a given period.
In this example we show how to allow requests when made by a user in their local business hours.
package play
import rego.v1
request_time := time.parse_ns("RFC822Z", input.request_time)
local_hours := data.business_hours[input.tz]
default allow := false
allow if {
[hour, _, _] := time.clock([request_time, input.tz])
hour > local_hours.start
hour < local_hours.end
}
{
"user": "y.hanako@example.com",
"tz": "Asia/Tokyo",
"request_time": "03 Jul 24 14:04 +0000"
}
{
"business_hours": {
"Asia/Tokyo": {
"start": 9,
"end": 18
}
}
}
format
time.format
is Rego's built-in function that takes a time in
nanoseconds since the Unix epoch and formats it as a string.
This is useful for displaying timestamps in a human-readable format
and presenting times in a given timezone.
The function accepts arguments in three formats, making it slightly more complicated to use. These are either:
-
A single value representing the nanoseconds since the Unix epoch
time.format(1720021249361794300)
time.format(1712345679361794300) -
A two-element array consisting of:
- The number of nanoseconds since the Unix epoch
- A timezone (TZ identifier)
# Using a named timezone identifier
time.format([1720021249361794300, "Europe/Paris"])
# Using a timezone code
time.format([1720021249361794300, "PDT"]) -
A three-element array consisting of:
- The number of nanoseconds since the Unix epoch
- A timezone (TZ identifier)
- Golang time layout string or formatting constant, see time package documentation.
# Using time format constant
time.format([1720021249361794300, "Europe/Paris", "RFC822Z"])
# Using a custom time layout string
time.format([1720021249361794300, "Europe/Paris", "2006_01_02_15_04_05"])
Show the local time in a response
time.format
can be used to provide information to the
user in a human-readable format in error messages. Error codes
and local times can be useful when debugging or troubleshooting
and so in many cases returning them from policy decisions can
be helpful.
In this example we see a user is not an admin and is denied access, the policy response is a message that includes the current time and an error code to help them debug.
package play
import rego.v1
request_time := time.parse_ns(
"RFC822Z",
input.request_utc_time,
)
local_time := time.format([
request_time,
input.tz,
"15:04:05",
])
default allow := false
allow if count(reasons) == 0
reasons contains message if {
input.role != "admin"
message := sprintf("E123 %s", [local_time])
}
{
"user": "yamada-hanako@example.com",
"tz": "Asia/Tokyo",
"role": "developer",
"request_utc_time": "03 Jul 24 14:04 +0000"
}
{}
parse_ns
time.parse_ns
is Rego's built-in function that parses a string into
a timestamp in nanoseconds since the Unix epoch.
This is useful converting input data to a format that can be compared with
other timestamps or used in time calculations.
Check if a time is within a period
In order to check if a time is in a period of time, we need to know the start and the end of the period first. This policy defines two dates in time to mark the start and the end of the period, before testing if the supplied time is in the period.
package play
import rego.v1
# 2006-01-02 is the time format string for yyyy-mm-dd
start_date := time.parse_ns("2006-01-02", "1999-01-01")
end_date := time.parse_ns("2006-01-02", "2000-01-01")
parsed_time := time.parse_rfc3339_ns(input.time)
default allow := false
allow if {
parsed_time > start_date
parsed_time < end_date
}
{
"time": "1999-07-02T13:14:46.878235008Z"
}
{}
Timestamp Parsing
In OPA, we can parse a simple YYYY-MM-DD timestamp as follows:
{}
{}
package time_format
ts := "1985-10-27"
result := time.parse_ns("2006-01-02", ts)
now_ns
time.now_ns
is Rego's built-in function that returns the current time
in nanoseconds since the Unix epoch. This is useful for comparing
timestamps or calculating time differences.
Check if a time is in the past
In this example, we see compare an RFC3339 timestamp with the current time to determine if the timestamp is in the past.
If you have a time in a different format, you might want to use
time.parse_ns
function to convert it to nanoseconds before comparing it with the current time.
Observe that in Rego, comparing time can be done using the <
and >
operators
just like comparing numbers and times in many other languages.
package play
import rego.v1
parsed_time := time.parse_rfc3339_ns(input.time)
in_past if parsed_time < time.now_ns()
{
"time": "2024-07-02T13:14:46.878235008Z"
}
{}