diff --git a/docs/operator-manual/notifications/functions.md b/docs/operator-manual/notifications/functions.md
index c50d122024b76..ebde62a62afb0 100644
--- a/docs/operator-manual/notifications/functions.md
+++ b/docs/operator-manual/notifications/functions.md
@@ -12,6 +12,44 @@ Golang [Time](https://golang.org/pkg/time/#Time).
Parses specified string using RFC3339 layout. Returns an instance of Golang [Time](https://golang.org/pkg/time/#Time).
+
+Time related constants.
+
+**Durations**
+
+```
+ time.Nanosecond = 1
+ time.Microsecond = 1000 * Nanosecond
+ time.Millisecond = 1000 * Microsecond
+ time.Second = 1000 * Millisecond
+ time.Minute = 60 * Second
+ time.Hour = 60 * Minute
+```
+
+**Timestamps**
+
+Used when formatting time instances as strings (e.g. `time.Now().Format(time.RFC3339)`).
+
+```
+ time.Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
+ time.ANSIC = "Mon Jan _2 15:04:05 2006"
+ time.UnixDate = "Mon Jan _2 15:04:05 MST 2006"
+ time.RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
+ time.RFC822 = "02 Jan 06 15:04 MST"
+ time.RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
+ time.RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
+ time.RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
+ time.RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
+ time.RFC3339 = "2006-01-02T15:04:05Z07:00"
+ time.RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
+ time.Kitchen = "3:04PM"
+ // Handy time stamps.
+ time.Stamp = "Jan _2 15:04:05"
+ time.StampMilli = "Jan _2 15:04:05.000"
+ time.StampMicro = "Jan _2 15:04:05.000000"
+ time.StampNano = "Jan _2 15:04:05.000000000"
+```
+
### **strings**
String related functions.
diff --git a/go.mod b/go.mod
index 2440ee7c32ec6..2be32c1ffa798 100644
--- a/go.mod
+++ b/go.mod
@@ -9,6 +9,7 @@ require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/TomOnTime/utfutil v0.0.0-20180511104225-09c41003ee1d
github.com/alicebob/miniredis/v2 v2.33.0
+ github.com/antonmedv/expr v1.15.1
github.com/argoproj/gitops-engine v0.7.1-0.20240823213048-95e00254f82a
github.com/argoproj/notifications-engine v0.4.1-0.20240606074338-0802cd427621
github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1
@@ -117,7 +118,6 @@ require (
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v0.5.2 // indirect
- github.com/antonmedv/expr v1.15.1 // indirect
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
github.com/aws/aws-sdk-go-v2/config v1.25.12 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
diff --git a/util/notification/expression/time/time.go b/util/notification/expression/time/time.go
index 6457b75d8c093..63aa31c3d3d13 100644
--- a/util/notification/expression/time/time.go
+++ b/util/notification/expression/time/time.go
@@ -4,10 +4,37 @@ import (
"time"
)
+var now = time.Now
+
func NewExprs() map[string]interface{} {
return map[string]interface{}{
+ // Functions
"Parse": parse,
"Now": now,
+ // Durations
+ "Nanosecond": time.Nanosecond,
+ "Microsecond": time.Microsecond,
+ "Millisecond": time.Millisecond,
+ "Second": time.Second,
+ "Minute": time.Minute,
+ "Hour": time.Hour,
+ // Timestamps
+ "Layout": time.Layout,
+ "ANSIC": time.ANSIC,
+ "UnixDate": time.UnixDate,
+ "RubyDate": time.RubyDate,
+ "RFC822": time.RFC822,
+ "RFC822Z": time.RFC822Z,
+ "RFC850": time.RFC850,
+ "RFC1123": time.RFC1123,
+ "RFC1123Z": time.RFC1123Z,
+ "RFC3339": time.RFC3339,
+ "RFC3339Nano": time.RFC3339Nano,
+ "Kitchen": time.Kitchen,
+ "Stamp": time.Stamp,
+ "StampMilli": time.StampMilli,
+ "StampMicro": time.StampMicro,
+ "StampNano": time.StampNano,
}
}
@@ -18,7 +45,3 @@ func parse(timestamp string) time.Time {
}
return res
}
-
-func now() time.Time {
- return time.Now()
-}
diff --git a/util/notification/expression/time/time_test.go b/util/notification/expression/time/time_test.go
index 3003521344eb4..a450260bea399 100644
--- a/util/notification/expression/time/time_test.go
+++ b/util/notification/expression/time/time_test.go
@@ -2,19 +2,60 @@ package time
import (
"testing"
+ "time"
+ "github.com/antonmedv/expr"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestNewTimeExprs(t *testing.T) {
funcs := []string{
"Parse",
"Now",
+ "Nanosecond",
+ "Microsecond",
+ "Millisecond",
+ "Second",
+ "Minute",
+ "Hour",
+ "Layout",
+ "ANSIC",
+ "UnixDate",
+ "RubyDate",
+ "RFC822",
+ "RFC822Z",
+ "RFC850",
+ "RFC1123",
+ "RFC1123Z",
+ "RFC3339",
+ "RFC3339Nano",
+ "Kitchen",
+ "Stamp",
+ "StampMilli",
+ "StampMicro",
+ "StampNano",
}
for _, fn := range funcs {
timeExprs := NewExprs()
- _, hasFunc := timeExprs[fn]
- assert.True(t, hasFunc)
+ _, exists := timeExprs[fn]
+ assert.True(t, exists)
}
}
+
+func Test_NewExprs_Now(t *testing.T) {
+ defer func() { now = time.Now }()
+ fixedTime := time.Date(2022, 9, 26, 11, 30, 25, 0, time.UTC)
+ now = func() time.Time {
+ return fixedTime
+ }
+
+ vm, err := expr.Compile("time.Now().Truncate(time.Hour).Format(time.RFC3339)")
+ require.NoError(t, err)
+
+ val, err := expr.Run(vm, map[string]interface{}{"time": NewExprs()})
+ require.NoError(t, err)
+
+ assert.Equal(t, "2022-09-26T11:00:00Z", val)
+}