Skip to content

Commit

Permalink
Add time.weekday builtin
Browse files Browse the repository at this point in the history
Fixes open-policy-agent#789.

Signed-off-by: Stephan Renatus <[email protected]>
  • Loading branch information
srenatus authored and tsandall committed Jun 25, 2018
1 parent 32c45d7 commit 6e8da23
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 0 deletions.
10 changes: 10 additions & 0 deletions ast/builtins.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ var DefaultBuiltins = [...]*Builtin{
ParseDurationNanos,
Date,
Clock,
Weekday,

// Crypto
CryptoX509ParseCertificates,
Expand Down Expand Up @@ -860,6 +861,15 @@ var Clock = &Builtin{
),
}

// Weekday returns the day of the week (Monday, Tuesday, ...) for the nanoseconds since epoch.
var Weekday = &Builtin{
Name: "time.weekday",
Decl: types.NewFunction(
types.Args(types.N),
types.S,
),
}

/**
* Crypto.
*/
Expand Down
1 change: 1 addition & 0 deletions docs/book/language-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ The input `string` is a JSON Web Token encoded with JWS Compact Serialization. J
| <span class="opa-keep-it-together">``time.parse_duration_ns(duration, output)``</span> | 1 | ``output`` is ``number`` representing the duration ``duration`` in nanoseconds. See the [Go `time` package documentation](https://golang.org/pkg/time/#ParseDuration) for more details on ``duration``. |
| <span class="opa-keep-it-together">``time.date(ns, [year, month, day])``</span> | 1 | outputs the ``year``, ``month`` (0-12), and ``day`` (0-31) as ``number``s representing the date from the nanoseconds since epoch (``ns``). |
| <span class="opa-keep-it-together">``time.clock(ns, [hour, minute, second])``</span> | 1 | outputs the ``hour``, ``minute`` (0-59), and ``second`` (0-59) as ``number``s representing the time of day for the nanoseconds since epoch (``ns``). |
| <span class="opa-keep-it-together">``time.weekday(ns, day)``</span> | 1 | outputs the ``day`` as ``string`` representing the day of the week for the nanoseconds since epoch (``ns``). |

> Multiple calls to the `time.now_ns` built-in function within a single policy
evaluation query will always return the same value.
Expand Down
19 changes: 19 additions & 0 deletions topdown/time.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@ func builtinClock(a ast.Value) (ast.Value, error) {
return result, nil
}

func builtinWeekday(a ast.Value) (ast.Value, error) {

value, err := builtins.NumberOperand(a, 1)
if err != nil {
return nil, err
}

f := builtins.NumberToFloat(value)
i64, acc := f.Int64()
if acc != big.Exact {
return nil, fmt.Errorf("timestamp too big")
}

t := time.Unix(0, i64).UTC()
weekday := t.Weekday().String()
return ast.String(weekday), nil
}

func int64ToJSONNumber(i int64) json.Number {
return json.Number(strconv.FormatInt(i, 10))
}
Expand All @@ -131,4 +149,5 @@ func init() {
RegisterFunctionalBuiltin1(ast.ParseDurationNanos.Name, builtinParseDurationNanos)
RegisterFunctionalBuiltin1(ast.Date.Name, builtinDate)
RegisterFunctionalBuiltin1(ast.Clock.Name, builtinClock)
RegisterFunctionalBuiltin1(ast.Weekday.Name, builtinWeekday)
}
9 changes: 9 additions & 0 deletions topdown/topdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1716,6 +1716,15 @@ func TestTopDownTime(t *testing.T) {

runTopDownTestCase(t, data, "clock too big", []string{`
p = [hour, minute, second] { [hour, minute, second] := time.clock(1582977600*1000*1000*1000*1000) }`}, fmt.Errorf("timestamp too big"))

for i, day := range []string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"} {
ts := 1517832000*1000*1000*1000 + i*24*int(time.Hour)
runTopDownTestCase(t, data, "weekday", []string{fmt.Sprintf(`p = weekday { weekday := time.weekday(%d)}`, ts)},
fmt.Sprintf("%q", day))
}

runTopDownTestCase(t, data, "weekday too big", []string{`
p = weekday { weekday := time.weekday(1582977600*1000*1000*1000*1000) }`}, fmt.Errorf("timestamp too big"))
}

func TestTopDownWalkBuiltin(t *testing.T) {
Expand Down

0 comments on commit 6e8da23

Please sign in to comment.