Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 60 additions & 28 deletions docs/usage/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -447,44 +447,47 @@ See: [json](json.md) for more information.

### Time

Syntax:
`{time str "[format:cache]" "[tz:utc]"}`
`{timeformat unixtime "[format:RFC3339]" "[tz:utc]"}`
`{timeattr unixtime attr [tz:utc]"}`
`{duration dur}`
`{durationformat secs}`
`{buckettime str bucket "[format]" "[tz:utc]"}`
#### Time Parsing

These three time functions provide you a way to parse and manipulate time.
Syntax: `{time str "[format:cache]" "[tz:utc]"}`

* `time`: Parse a given time-string into a unix second time (default: auto-detection)
* `timeformat`: Takes a unix time, and formats it (default: RFC3339)
* `timeattr`: Extracts an attribute about a given datetime (weekday, week, yearweek, quarter)
* `duration`: Use a duration expressed in s,m,h and convert it to seconds eg `{duration 24h}`
* `durationformat`: Formats a duration (in seconds) to a human-readable time, (eg. 4h0m0s)
* `buckettime`: Truncate the time to a given bucket (*n*ano, *s*econd, *m*inute, *h*our, *d*ay, *mo*nth, *y*ear)
Parse a given time-string into a unix second time (default format: `cache`)

##### Format Auto-Detection

**Timezones:**
If the format argument is ommitted or set to "auto", it will attempt to resolve the format of the time.

If the format is unable to be resolved, it must be specified manually with a format below, or a custom format.

If ommitted or "cache": The first seen date will determine the format for all dates going forward (faster)

If "auto": The date format will be auto-detected with each parse. This can be used if the date could be in different formats (slower)

##### Timezones

The following values are accepted for a `tz` (timezone): `utc`, `local`, or a valid *IANA Time Zone*

By default, all datetimes are processed as UTC, unless explicit in the datetime itself, or overridden via a parameter.

**Format Auto-Detection:**

If the format argument is ommitted or set to "auto", it will attempt to resolve the format of the time.
#### Time Values

If the format is unable to be resolved, it must be specified manually with a format below, or a custom format.
Syntax: `{time now}`

If ommitted or "cache": The first seen date will determine the format for all dates going forward (faster)
These are special values to output:

* `now` - return the current unix timestamp cached at the start of *rare*
* `live` - return the current unix timestamp the moment it's executed
* `delta` - return the number of seconds that *rare* has executed

If "auto": The date format will always be auto-detected each time. This can be used if the date could be in different formats (slower)

**Special Values:**
The time `now` will return the current unix timestamp `{time now}`
#### Time Format

#### Time Formats
Syntax: `{timeformat unixtime "[format:RFC3339]" "[tz:utc]"}`

Takes a unix time, and formats it (default: `RFC3339`)

To reformat a time, you need to parse it first, eg: `{timeformat {time {0}} RFC3339}`

**Supported Formats:**
ANSIC, UNIX, RUBY, RFC822, RFC822Z, RFC1123, RFC1123Z, RFC3339, RFC3339, RFC3339N, NGINX
Expand All @@ -493,13 +496,42 @@ ANSIC, UNIX, RUBY, RFC822, RFC822Z, RFC1123, RFC1123Z, RFC3339, RFC3339, RFC3339
MONTH, MONTHNAME, MNTH, DAY, WEEKDAY, WDAY, YEAR, HOUR, MINUTE, SECOND, TIMEZONE, NTIMEZONE

**Custom formats:**
You can provide a custom format using go's well-known date. Here's an exercept from their docs:
You can provide a custom format using go's well-known date. Here's an exercept from the docs:

To define your own format, write down what the reference time would look like formatted your way; see the values of constants
like ANSIC, StampMicro or Kitchen for examples. The model is to demonstrate what the reference time looks like so that the Format
and Parse methods can apply the same transformation to a general time value.

The reference time used in the layouts is the specific time: `Mon Jan 2 15:04:05 MST 2006`

#### Time Attribute

Syntax: `{timeattr unixtime attr [tz:utc]"}`

Extracts an attribute about a given datetime

*Supports*: `weekday`, `week`, `yearweek`, `quarter`

#### Durations

Syntax: `{duration dur}`

Use a duration expressed in s,m,h and convert it to seconds eg `{duration 24h}`

From there, you can do arithmatic on time, for instance: `{sumi {time now} {duration 1h}}`

##### Format Duration

Syntax: `{durationformat secs}`

Formats a duration (in seconds) to a human-readable time, (eg. 4h0m0s)

#### Time Bucket

Syntax: `{buckettime str bucket "[format]" "[tz:utc]"}`

**From go docs:**
To define your own format, write down what the reference time would look like formatted your way; see the values of constants like ANSIC, StampMicro or Kitchen for examples. The model is to demonstrate what the reference time looks like so that the Format and Parse methods can apply the same transformation to a general time value.
Truncate the time to a given bucket (*n*ano, *s*econd, *m*inute, *h*our, *d*ay, *mo*nth, *y*ear)

The reference time used in the layouts is the specific time:
Mon Jan 2 15:04:05 MST 2006

## Errors

Expand Down
11 changes: 11 additions & 0 deletions pkg/expressions/stdlib/funcsTime.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,17 @@ func kfTimeParse(args []KeyBuilderStage) (KeyBuilderStage, error) {
return func(context KeyBuilderContext) string {
return now
}, nil
case "live":
return func(context KeyBuilderContext) string {
context.GetMatch(-1) // HACK: Touch the context so it doesn't get optimized out
return strconv.FormatInt(time.Now().Unix(), 10)
}, nil
case "delta":
start := time.Now().Unix()
return func(context KeyBuilderContext) string {
context.GetMatch(-1) // HACK: Touch the context so it doesn't get optimized out
return strconv.FormatInt(time.Now().Unix()-start, 10)
}, nil
}
}

Expand Down
35 changes: 35 additions & 0 deletions pkg/expressions/stdlib/funcsTime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,42 @@ func TestTimeNow(t *testing.T) {
ival, perr := strconv.ParseInt(val, 10, 64)
assert.NoError(t, perr)
assert.NotZero(t, ival)
}

func TestTimeLive(t *testing.T) {
t.Parallel()

kb, err := NewStdKeyBuilder().Compile("{time live}")
assert.Nil(t, err)

val := kb.BuildKey(mockContext())
assert.NotEmpty(t, val)

time.Sleep(1 * time.Second)

val2 := kb.BuildKey(mockContext())
assert.NotEmpty(t, val)
assert.NotEqual(t, val, val2)
}

func TestTimeDelta(t *testing.T) {
t.Parallel()

kb, err := NewStdKeyBuilder().Compile("{time delta}")
assert.Nil(t, err)

val := kb.BuildKey(mockContext())
assert.NotEmpty(t, val)

iVal, errVal := strconv.Atoi(val)
assert.NoError(t, errVal)
assert.Less(t, iVal, 300) // Delta should always be relatively lower (at least lower than running the test)

time.Sleep(1 * time.Second)

val2 := kb.BuildKey(mockContext())
assert.NotEmpty(t, val)
assert.NotEqual(t, val, val2)
}

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