mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Core: Add go-datemath library (#22978)
This commit is contained in:
1
go.mod
1
go.mod
@@ -60,6 +60,7 @@ require (
|
|||||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf
|
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf
|
||||||
|
github.com/timberio/go-datemath v0.1.1-0.20200323150745-74ddef604fff
|
||||||
github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329
|
github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329
|
||||||
github.com/uber/jaeger-client-go v2.20.1+incompatible
|
github.com/uber/jaeger-client-go v2.20.1+incompatible
|
||||||
github.com/uber/jaeger-lib v2.2.0+incompatible // indirect
|
github.com/uber/jaeger-lib v2.2.0+incompatible // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -286,6 +286,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf h1:Z2X3Os7oRzpdJ75iPqWZc0HeJWFYNCvKsfpQwFpRNTA=
|
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf h1:Z2X3Os7oRzpdJ75iPqWZc0HeJWFYNCvKsfpQwFpRNTA=
|
||||||
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0=
|
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf/go.mod h1:M8agBzgqHIhgj7wEn9/0hJUZcrvt9VY+Ln+S1I5Mha0=
|
||||||
|
github.com/timberio/go-datemath v0.1.1-0.20200323150745-74ddef604fff h1:QCdUBuN+iKWAB9HqPTkBwyKPPUHDobJ2AuELSNZwd4o=
|
||||||
|
github.com/timberio/go-datemath v0.1.1-0.20200323150745-74ddef604fff/go.mod h1:m7kjsbCuO4QKP3KLfnxiUZWiOiFXmxj30HeexjL3lc0=
|
||||||
github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329 h1:VBsKFh4W1JEMz3eLCmM9zOJKZdDkP5W4b3Y4hc7SbZc=
|
github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329 h1:VBsKFh4W1JEMz3eLCmM9zOJKZdDkP5W4b3Y4hc7SbZc=
|
||||||
github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329/go.mod h1:OBcG9bn7sHtXgarhUEb3OfCnNsgtGnkVf41ilSZ3K3E=
|
github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329/go.mod h1:OBcG9bn7sHtXgarhUEb3OfCnNsgtGnkVf41ilSZ3K3E=
|
||||||
github.com/uber/jaeger-client-go v2.20.1+incompatible h1:HgqpYBng0n7tLJIlyT4kPCIv5XgCsF+kai1NnnrJzEU=
|
github.com/uber/jaeger-client-go v2.20.1+incompatible h1:HgqpYBng0n7tLJIlyT4kPCIv5XgCsF+kai1NnnrJzEU=
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
_ "github.com/robfig/cron"
|
_ "github.com/robfig/cron"
|
||||||
_ "github.com/robfig/cron/v3"
|
_ "github.com/robfig/cron/v3"
|
||||||
_ "github.com/stretchr/testify/require"
|
_ "github.com/stretchr/testify/require"
|
||||||
|
_ "github.com/timberio/go-datemath"
|
||||||
_ "gopkg.in/square/go-jose.v2"
|
_ "gopkg.in/square/go-jose.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
1
vendor/github.com/timberio/go-datemath/.gitignore
generated
vendored
Normal file
1
vendor/github.com/timberio/go-datemath/.gitignore
generated
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
y.output
|
||||||
16
vendor/github.com/timberio/go-datemath/CONTRIBUTING.md
generated
vendored
Normal file
16
vendor/github.com/timberio/go-datemath/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
Bug fixes and other contributions via pull request greatly welcomed!
|
||||||
|
|
||||||
|
This library relies on [goyacc](https://godoc.org/golang.org/x/tools/cmd/goyacc) and
|
||||||
|
[golex](https://godoc.org/modernc.org/golex) for parsing and evaluating datemath grammar.
|
||||||
|
|
||||||
|
To install, run:
|
||||||
|
|
||||||
|
* `go get golang.org/x/tools/cmd/goyacc modernc.org/golex`
|
||||||
|
|
||||||
|
After modifying either the `datemath.l` or `datemath.y` you can rerun `go generate`.
|
||||||
|
|
||||||
|
When in doubt on semantics of the library, [Elasticsearch's
|
||||||
|
implementation](https://www.elastic.co/guide/en/elasticsearch/reference/7.3/common-options.html#date-math) should be
|
||||||
|
considered the canonical specification.
|
||||||
13
vendor/github.com/timberio/go-datemath/LICENSE
generated
vendored
Normal file
13
vendor/github.com/timberio/go-datemath/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
Copyright (c) 2019, Timber Technologies, Inc.
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||||
|
with or without fee is hereby granted, provided that the above copyright notice
|
||||||
|
and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||||
|
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||||
|
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||||
|
THIS SOFTWARE.
|
||||||
29
vendor/github.com/timberio/go-datemath/README.md
generated
vendored
Normal file
29
vendor/github.com/timberio/go-datemath/README.md
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# go-datemath
|
||||||
|
|
||||||
|
[](http://godoc.org/github.com/timberio/go-datemath)
|
||||||
|
[](https://circleci.com/gh/timberio/go-datemath)
|
||||||
|
[](https://goreportcard.com/report/github.com/timberio/go-datemath)
|
||||||
|
[](http://gocover.io/github.com/timberio/go-datemath)
|
||||||
|
|
||||||
|
This library provides support for parsing datemath expressions compatibly with [Elasticsearch datemath
|
||||||
|
expressions](https://www.elastic.co/guide/en/elasticsearch/reference/7.3/common-options.html#date-math). These are
|
||||||
|
useful for allowing users to specify, and for encoding, relative dates. Examples:
|
||||||
|
|
||||||
|
* `now+15m`: 15 minutes from now
|
||||||
|
* `now-1w+1d`: one day after on week ago
|
||||||
|
* `2015-05-05T00:00:00||+1M`: one month after 2019-05-05
|
||||||
|
|
||||||
|
These expressions will seem familiar if you have used Grafana or Kibana.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
```go
|
||||||
|
expr, _ := datemath.Parse("now-15m")
|
||||||
|
fmt.Println(t.Time(datemath.WithNow(now)))
|
||||||
|
```
|
||||||
|
|
||||||
|
See [package documentation](http://godoc.org/github.com/timberio/go-datemath) for usage and more examples.
|
||||||
|
|
||||||
|
## Development / Contributing
|
||||||
|
|
||||||
|
See [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||||
352
vendor/github.com/timberio/go-datemath/datemath.go
generated
vendored
Normal file
352
vendor/github.com/timberio/go-datemath/datemath.go
generated
vendored
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
// Requires golang.org/x/tools/cmd/goyacc and modernc.org/golex
|
||||||
|
//
|
||||||
|
//go:generate goyacc -o datemath.y.go datemath.y
|
||||||
|
//go:generate golex -o datemath.l.go datemath.l
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package datemath provides an expression language for relative dates based on Elasticsearch's date math.
|
||||||
|
|
||||||
|
This package is useful for letting end-users describe dates in a simple format similar to Grafana and Kibana and for
|
||||||
|
persisting them as relative dates.
|
||||||
|
|
||||||
|
The expression starts with an anchor date, which can either be "now", or an ISO8601 date string ending with ||. This
|
||||||
|
anchor date can optionally be followed by one or more date math expressions, for example:
|
||||||
|
|
||||||
|
now+1h Add one hour
|
||||||
|
now-1d Subtract one day
|
||||||
|
now/d Round down to the nearest day
|
||||||
|
|
||||||
|
The supported time units are:
|
||||||
|
y Years
|
||||||
|
M Months
|
||||||
|
w Weeks
|
||||||
|
d Days
|
||||||
|
b Business Days (excludes Saturday and Sunday by default, use WithBusinessDayFunc to override)
|
||||||
|
h Hours
|
||||||
|
H Hours
|
||||||
|
m Minutes
|
||||||
|
s Seconds
|
||||||
|
|
||||||
|
Compatibility with Elasticsearch datemath
|
||||||
|
|
||||||
|
This package aims to be a superset of Elasticsearch's expressions. That is, any datemath expression that is valid for
|
||||||
|
Elasticsearch should evaluate in the same way here.
|
||||||
|
|
||||||
|
Currently the package does not support expressions outside of those also considered valid by Elasticsearch, but this may
|
||||||
|
change in the future to include additional functionality.
|
||||||
|
*/
|
||||||
|
package datemath
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// have goyacc parser return more verbose syntax error messages
|
||||||
|
yyErrorVerbose = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var missingTimeZone = time.FixedZone("MISSING", 0)
|
||||||
|
|
||||||
|
type timeUnit rune
|
||||||
|
|
||||||
|
const (
|
||||||
|
timeUnitYear = timeUnit('y')
|
||||||
|
timeUnitMonth = timeUnit('M')
|
||||||
|
timeUnitWeek = timeUnit('w')
|
||||||
|
timeUnitDay = timeUnit('d')
|
||||||
|
timeUnitBusinessDay = timeUnit('b')
|
||||||
|
timeUnitHour = timeUnit('h')
|
||||||
|
timeUnitMinute = timeUnit('m')
|
||||||
|
timeUnitSecond = timeUnit('s')
|
||||||
|
)
|
||||||
|
|
||||||
|
func (u timeUnit) String() string {
|
||||||
|
return string(u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expression represents a parsed datemath expression
|
||||||
|
type Expression struct {
|
||||||
|
input string
|
||||||
|
|
||||||
|
mathExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
type mathExpression struct {
|
||||||
|
anchorDateExpression anchorDateExpression
|
||||||
|
adjustments []timeAdjuster
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMathExpression(anchorDateExpression anchorDateExpression, adjustments []timeAdjuster) mathExpression {
|
||||||
|
return mathExpression{
|
||||||
|
anchorDateExpression: anchorDateExpression,
|
||||||
|
adjustments: adjustments,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface
|
||||||
|
//
|
||||||
|
// It serializes as the string expression the Expression was created with
|
||||||
|
func (e Expression) MarshalJSON() ([]byte, error) {
|
||||||
|
return []byte(strconv.Quote(e.String())), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface
|
||||||
|
//
|
||||||
|
// Parses the datemath expression from a JSON string
|
||||||
|
func (e *Expression) UnmarshalJSON(data []byte) error {
|
||||||
|
s, err := strconv.Unquote(string(data))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
expression, err := Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
*e = expression
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a the string used to create the expression
|
||||||
|
func (e Expression) String() string {
|
||||||
|
return e.input
|
||||||
|
}
|
||||||
|
|
||||||
|
// Options represesent configurable behavior for interpreting the datemath expression
|
||||||
|
type Options struct {
|
||||||
|
// Use this this time as "now"
|
||||||
|
// Default is `time.Now()`
|
||||||
|
Now time.Time
|
||||||
|
|
||||||
|
// Use this location if there is no timezone in the expression
|
||||||
|
// Defaults to time.UTC
|
||||||
|
Location *time.Location
|
||||||
|
|
||||||
|
// Use this weekday as the start of the week
|
||||||
|
// Defaults to time.Monday
|
||||||
|
StartOfWeek time.Weekday
|
||||||
|
|
||||||
|
// Rounding to period should be done to the end of the period
|
||||||
|
// Defaults to false
|
||||||
|
RoundUp bool
|
||||||
|
|
||||||
|
BusinessDayFunc func(time.Time) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNow use the given time as "now"
|
||||||
|
func WithNow(now time.Time) func(*Options) {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.Now = now
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithStartOfWeek uses the given weekday as the start of the week
|
||||||
|
func WithStartOfWeek(day time.Weekday) func(*Options) {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.StartOfWeek = day
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithLocation uses the given location as the timezone of the date if unspecified
|
||||||
|
func WithLocation(l *time.Location) func(*Options) {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.Location = l
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithRoundUp sets the rounding of time to the end of the period instead of the beginning
|
||||||
|
func WithRoundUp(b bool) func(*Options) {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.RoundUp = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBusinessDayFunc use the given fn to check if a day is a business day
|
||||||
|
func WithBusinessDayFunc(fn func(time.Time) bool) func(*Options) {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.BusinessDayFunc = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNotWeekend(t time.Time) bool {
|
||||||
|
return t.Weekday() != time.Saturday && t.Weekday() != time.Sunday
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time evaluate the expression with the given options to get the time it represents
|
||||||
|
func (e Expression) Time(opts ...func(*Options)) time.Time {
|
||||||
|
options := Options{
|
||||||
|
Now: time.Now(),
|
||||||
|
Location: time.UTC,
|
||||||
|
StartOfWeek: time.Monday,
|
||||||
|
}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&options)
|
||||||
|
}
|
||||||
|
|
||||||
|
t := e.anchorDateExpression(options)
|
||||||
|
for _, adjustment := range e.adjustments {
|
||||||
|
t = adjustment(t, options)
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse parses the datemath expression which can later be evaluated
|
||||||
|
func Parse(s string) (Expression, error) {
|
||||||
|
lex := newLexer([]byte(s))
|
||||||
|
lexWrapper := newLexerWrapper(lex)
|
||||||
|
|
||||||
|
yyParse(lexWrapper)
|
||||||
|
|
||||||
|
if len(lex.errors) > 0 {
|
||||||
|
return Expression{}, fmt.Errorf(strings.Join(lex.errors, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return Expression{input: s, mathExpression: lexWrapper.expression}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustParse is the same as Parse() but panic's on error
|
||||||
|
func MustParse(s string) Expression {
|
||||||
|
e, err := Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseAndEvaluate is a convience wrapper to parse and return the time that the expression represents
|
||||||
|
func ParseAndEvaluate(s string, opts ...func(*Options)) (time.Time, error) {
|
||||||
|
expression, err := Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
return time.Time{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return expression.Time(opts...), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type anchorDateExpression func(opts Options) time.Time
|
||||||
|
|
||||||
|
func anchorDateNow(opts Options) time.Time {
|
||||||
|
return opts.Now.In(opts.Location)
|
||||||
|
}
|
||||||
|
|
||||||
|
func anchorDate(t time.Time) func(opts Options) time.Time {
|
||||||
|
return func(opts Options) time.Time {
|
||||||
|
location := t.Location()
|
||||||
|
if location == missingTimeZone {
|
||||||
|
location = opts.Location
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type timeAdjuster func(time.Time, Options) time.Time
|
||||||
|
|
||||||
|
func addUnits(factor int, u timeUnit) func(time.Time, Options) time.Time {
|
||||||
|
return func(t time.Time, options Options) time.Time {
|
||||||
|
switch u {
|
||||||
|
case timeUnitYear:
|
||||||
|
return t.AddDate(factor, 0, 0)
|
||||||
|
case timeUnitMonth:
|
||||||
|
return t.AddDate(0, factor, 0)
|
||||||
|
case timeUnitWeek:
|
||||||
|
return t.AddDate(0, 0, 7*factor)
|
||||||
|
case timeUnitDay:
|
||||||
|
return t.AddDate(0, 0, factor)
|
||||||
|
case timeUnitBusinessDay:
|
||||||
|
|
||||||
|
fn := options.BusinessDayFunc
|
||||||
|
if fn == nil {
|
||||||
|
fn = isNotWeekend
|
||||||
|
}
|
||||||
|
|
||||||
|
increment := 1
|
||||||
|
if factor < 0 {
|
||||||
|
increment = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := factor; i != 0; i -= increment {
|
||||||
|
t = t.AddDate(0, 0, increment)
|
||||||
|
for !fn(t) {
|
||||||
|
t = t.AddDate(0, 0, increment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return t
|
||||||
|
|
||||||
|
case timeUnitHour:
|
||||||
|
return t.Add(time.Duration(factor) * time.Hour)
|
||||||
|
case timeUnitMinute:
|
||||||
|
return t.Add(time.Duration(factor) * time.Minute)
|
||||||
|
case timeUnitSecond:
|
||||||
|
return t.Add(time.Duration(factor) * time.Second)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown time unit: %s", u))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func truncateUnits(u timeUnit) func(time.Time, Options) time.Time {
|
||||||
|
var roundDown = func(t time.Time, options Options) time.Time {
|
||||||
|
switch u {
|
||||||
|
case timeUnitYear:
|
||||||
|
return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location())
|
||||||
|
case timeUnitMonth:
|
||||||
|
return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location())
|
||||||
|
case timeUnitWeek:
|
||||||
|
diff := int(t.Weekday() - options.StartOfWeek)
|
||||||
|
if diff < 0 {
|
||||||
|
return time.Date(t.Year(), t.Month(), t.Day()+diff-1, 0, 0, 0, 0, t.Location())
|
||||||
|
}
|
||||||
|
return time.Date(t.Year(), t.Month(), t.Day()-diff, 0, 0, 0, 0, t.Location())
|
||||||
|
case timeUnitDay:
|
||||||
|
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
|
||||||
|
case timeUnitHour:
|
||||||
|
return t.Truncate(time.Hour)
|
||||||
|
case timeUnitMinute:
|
||||||
|
return t.Truncate(time.Minute)
|
||||||
|
case timeUnitSecond:
|
||||||
|
return t.Truncate(time.Second)
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown time unit: %s", u))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(t time.Time, options Options) time.Time {
|
||||||
|
if options.RoundUp {
|
||||||
|
return addUnits(1, u)(roundDown(t, options), options).Add(-time.Millisecond)
|
||||||
|
}
|
||||||
|
return roundDown(t, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func daysIn(m time.Month, year int) int {
|
||||||
|
return time.Date(year, m+1, 0, 0, 0, 0, 0, time.UTC).Day()
|
||||||
|
}
|
||||||
|
|
||||||
|
// lexerWrapper wraps the golex generated wrapper to store the parsed expression for later and provide needed data to
|
||||||
|
// the parser
|
||||||
|
type lexerWrapper struct {
|
||||||
|
lex yyLexer
|
||||||
|
|
||||||
|
expression mathExpression
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLexerWrapper(lex yyLexer) *lexerWrapper {
|
||||||
|
return &lexerWrapper{
|
||||||
|
lex: lex,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lexerWrapper) Lex(lval *yySymType) int {
|
||||||
|
return l.lex.Lex(lval)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lexerWrapper) Error(s string) {
|
||||||
|
l.lex.Error(s)
|
||||||
|
}
|
||||||
144
vendor/github.com/timberio/go-datemath/datemath.l
generated
vendored
Normal file
144
vendor/github.com/timberio/go-datemath/datemath.l
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
This file is used with golex to generate a lexer that has a signature compatible with goyacc.
|
||||||
|
|
||||||
|
Many constants referred to below are defined by goyacc when creating template.y.go
|
||||||
|
|
||||||
|
See https://godoc.org/modernc.org/golex for more about golex
|
||||||
|
*/
|
||||||
|
|
||||||
|
%{
|
||||||
|
|
||||||
|
package datemath
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 0 is expected by the goyacc generated parser to indicate EOF
|
||||||
|
eofCode = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// lexer holds the state of the lexer
|
||||||
|
type lexer struct {
|
||||||
|
src *bytes.Reader
|
||||||
|
|
||||||
|
buf []byte
|
||||||
|
current byte
|
||||||
|
|
||||||
|
pos int
|
||||||
|
|
||||||
|
errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLexer(b []byte) *lexer {
|
||||||
|
l := &lexer{
|
||||||
|
src: bytes.NewReader(b),
|
||||||
|
}
|
||||||
|
// queue up a byte
|
||||||
|
l.next()
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lexer) Error(s string) {
|
||||||
|
l.errors = append(l.errors, fmt.Sprintf("%s at character %d starting with %q", s, l.pos, string(l.buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lexer) next() {
|
||||||
|
if l.current != 0 {
|
||||||
|
l.buf = append(l.buf, l.current)
|
||||||
|
}
|
||||||
|
l.current = 0
|
||||||
|
if b, err := l.src.ReadByte(); err == nil {
|
||||||
|
l.current = b
|
||||||
|
}
|
||||||
|
l.pos++
|
||||||
|
}
|
||||||
|
func (l *lexer) Lex(lval *yySymType) int {
|
||||||
|
%}
|
||||||
|
|
||||||
|
/* give some regular expressions more semantic names for use below */
|
||||||
|
eof \0
|
||||||
|
|
||||||
|
/* tell golex how to determine the current start condition */
|
||||||
|
%yyt l.startCondition
|
||||||
|
/* tell golex how to determine the current byte */
|
||||||
|
%yyc l.current
|
||||||
|
/* tell golex how to advance to the next byte */
|
||||||
|
%yyn l.next()
|
||||||
|
|
||||||
|
%%
|
||||||
|
// runs before each token is parsed
|
||||||
|
l.buf = l.buf[:0]
|
||||||
|
|
||||||
|
[0-9]
|
||||||
|
i, err := strconv.ParseInt(string(l.buf), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("could not parse digit as number: %s", err))
|
||||||
|
}
|
||||||
|
lval.i = int(i)
|
||||||
|
return tDIGIT
|
||||||
|
|
||||||
|
"now"
|
||||||
|
return tNOW
|
||||||
|
|
||||||
|
"+"
|
||||||
|
return tPLUS
|
||||||
|
|
||||||
|
"-"
|
||||||
|
return tMINUS
|
||||||
|
|
||||||
|
":"
|
||||||
|
return tCOLON
|
||||||
|
|
||||||
|
"||"
|
||||||
|
return tPIPES
|
||||||
|
|
||||||
|
"/"
|
||||||
|
return tBACKSLASH
|
||||||
|
|
||||||
|
[yMwdbhHms]
|
||||||
|
switch l.buf[0] {
|
||||||
|
case 'y':
|
||||||
|
lval.unit = timeUnitYear
|
||||||
|
case 'M':
|
||||||
|
lval.unit = timeUnitMonth
|
||||||
|
case 'w':
|
||||||
|
lval.unit = timeUnitWeek
|
||||||
|
case 'b':
|
||||||
|
lval.unit = timeUnitBusinessDay
|
||||||
|
case 'd':
|
||||||
|
lval.unit = timeUnitDay
|
||||||
|
case 'h', 'H':
|
||||||
|
lval.unit = timeUnitHour
|
||||||
|
case 'm':
|
||||||
|
lval.unit = timeUnitMinute
|
||||||
|
case 's':
|
||||||
|
lval.unit = timeUnitSecond
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown time unit: %q", l.buf[0]))
|
||||||
|
}
|
||||||
|
return tUNIT
|
||||||
|
|
||||||
|
\.
|
||||||
|
return tDOT
|
||||||
|
|
||||||
|
"T"
|
||||||
|
return tTIME_DELIMITER
|
||||||
|
|
||||||
|
"Z"
|
||||||
|
return tUTC
|
||||||
|
|
||||||
|
{eof}
|
||||||
|
return eofCode
|
||||||
|
|
||||||
|
.
|
||||||
|
return tINVALID_TOKEN
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
// should never get here
|
||||||
|
panic("scanner internal error")
|
||||||
|
}
|
||||||
296
vendor/github.com/timberio/go-datemath/datemath.l.go
generated
vendored
Normal file
296
vendor/github.com/timberio/go-datemath/datemath.l.go
generated
vendored
Normal file
@@ -0,0 +1,296 @@
|
|||||||
|
// Code generated by golex. DO NOT EDIT.
|
||||||
|
|
||||||
|
/*
|
||||||
|
This file is used with golex to generate a lexer that has a signature compatible with goyacc.
|
||||||
|
|
||||||
|
Many constants referred to below are defined by goyacc when creating template.y.go
|
||||||
|
|
||||||
|
See https://godoc.org/modernc.org/golex for more about golex
|
||||||
|
*/
|
||||||
|
|
||||||
|
package datemath
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 0 is expected by the goyacc generated parser to indicate EOF
|
||||||
|
eofCode = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// lexer holds the state of the lexer
|
||||||
|
type lexer struct {
|
||||||
|
src *bytes.Reader
|
||||||
|
|
||||||
|
buf []byte
|
||||||
|
current byte
|
||||||
|
|
||||||
|
pos int
|
||||||
|
|
||||||
|
errors []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLexer(b []byte) *lexer {
|
||||||
|
l := &lexer{
|
||||||
|
src: bytes.NewReader(b),
|
||||||
|
}
|
||||||
|
// queue up a byte
|
||||||
|
l.next()
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lexer) Error(s string) {
|
||||||
|
l.errors = append(l.errors, fmt.Sprintf("%s at character %d starting with %q", s, l.pos, string(l.buf)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *lexer) next() {
|
||||||
|
if l.current != 0 {
|
||||||
|
l.buf = append(l.buf, l.current)
|
||||||
|
}
|
||||||
|
l.current = 0
|
||||||
|
if b, err := l.src.ReadByte(); err == nil {
|
||||||
|
l.current = b
|
||||||
|
}
|
||||||
|
l.pos++
|
||||||
|
}
|
||||||
|
func (l *lexer) Lex(lval *yySymType) int {
|
||||||
|
|
||||||
|
/* give some regular expressions more semantic names for use below */
|
||||||
|
/* tell golex how to determine the current start condition */
|
||||||
|
/* tell golex how to determine the current byte */
|
||||||
|
/* tell golex how to advance to the next byte */
|
||||||
|
|
||||||
|
yystate0:
|
||||||
|
|
||||||
|
// runs before each token is parsed
|
||||||
|
l.buf = l.buf[:0]
|
||||||
|
|
||||||
|
goto yystart1
|
||||||
|
|
||||||
|
yystate1:
|
||||||
|
l.next()
|
||||||
|
yystart1:
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
goto yyabort
|
||||||
|
case l.current == '+':
|
||||||
|
goto yystate4
|
||||||
|
case l.current == '-':
|
||||||
|
goto yystate5
|
||||||
|
case l.current == '.':
|
||||||
|
goto yystate6
|
||||||
|
case l.current == '/':
|
||||||
|
goto yystate7
|
||||||
|
case l.current == ':':
|
||||||
|
goto yystate9
|
||||||
|
case l.current == 'H' || l.current == 'M' || l.current == 'b' || l.current == 'd' || l.current == 'h' || l.current == 'm' || l.current == 's' || l.current == 'w' || l.current == 'y':
|
||||||
|
goto yystate10
|
||||||
|
case l.current == 'T':
|
||||||
|
goto yystate11
|
||||||
|
case l.current == 'Z':
|
||||||
|
goto yystate12
|
||||||
|
case l.current == '\x00':
|
||||||
|
goto yystate2
|
||||||
|
case l.current == 'n':
|
||||||
|
goto yystate13
|
||||||
|
case l.current == '|':
|
||||||
|
goto yystate16
|
||||||
|
case l.current >= '0' && l.current <= '9':
|
||||||
|
goto yystate8
|
||||||
|
case l.current >= '\x01' && l.current <= '\t' || l.current >= '\v' && l.current <= '*' || l.current == ',' || l.current >= ';' && l.current <= 'G' || l.current >= 'I' && l.current <= 'L' || l.current >= 'N' && l.current <= 'S' || l.current >= 'U' && l.current <= 'Y' || l.current >= '[' && l.current <= 'a' || l.current == 'c' || l.current >= 'e' && l.current <= 'g' || l.current >= 'i' && l.current <= 'l' || l.current >= 'o' && l.current <= 'r' || l.current >= 't' && l.current <= 'v' || l.current == 'x' || l.current == 'z' || l.current == '{' || l.current >= '}' && l.current <= 'ÿ':
|
||||||
|
goto yystate3
|
||||||
|
}
|
||||||
|
|
||||||
|
yystate2:
|
||||||
|
l.next()
|
||||||
|
goto yyrule12
|
||||||
|
|
||||||
|
yystate3:
|
||||||
|
l.next()
|
||||||
|
goto yyrule13
|
||||||
|
|
||||||
|
yystate4:
|
||||||
|
l.next()
|
||||||
|
goto yyrule3
|
||||||
|
|
||||||
|
yystate5:
|
||||||
|
l.next()
|
||||||
|
goto yyrule4
|
||||||
|
|
||||||
|
yystate6:
|
||||||
|
l.next()
|
||||||
|
goto yyrule9
|
||||||
|
|
||||||
|
yystate7:
|
||||||
|
l.next()
|
||||||
|
goto yyrule7
|
||||||
|
|
||||||
|
yystate8:
|
||||||
|
l.next()
|
||||||
|
goto yyrule1
|
||||||
|
|
||||||
|
yystate9:
|
||||||
|
l.next()
|
||||||
|
goto yyrule5
|
||||||
|
|
||||||
|
yystate10:
|
||||||
|
l.next()
|
||||||
|
goto yyrule8
|
||||||
|
|
||||||
|
yystate11:
|
||||||
|
l.next()
|
||||||
|
goto yyrule10
|
||||||
|
|
||||||
|
yystate12:
|
||||||
|
l.next()
|
||||||
|
goto yyrule11
|
||||||
|
|
||||||
|
yystate13:
|
||||||
|
l.next()
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
goto yyrule13
|
||||||
|
case l.current == 'o':
|
||||||
|
goto yystate14
|
||||||
|
}
|
||||||
|
|
||||||
|
yystate14:
|
||||||
|
l.next()
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
goto yyabort
|
||||||
|
case l.current == 'w':
|
||||||
|
goto yystate15
|
||||||
|
}
|
||||||
|
|
||||||
|
yystate15:
|
||||||
|
l.next()
|
||||||
|
goto yyrule2
|
||||||
|
|
||||||
|
yystate16:
|
||||||
|
l.next()
|
||||||
|
switch {
|
||||||
|
default:
|
||||||
|
goto yyrule13
|
||||||
|
case l.current == '|':
|
||||||
|
goto yystate17
|
||||||
|
}
|
||||||
|
|
||||||
|
yystate17:
|
||||||
|
l.next()
|
||||||
|
goto yyrule6
|
||||||
|
|
||||||
|
yyrule1: // [0-9]
|
||||||
|
{
|
||||||
|
|
||||||
|
i, err := strconv.ParseInt(string(l.buf), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("could not parse digit as number: %s", err))
|
||||||
|
}
|
||||||
|
lval.i = int(i)
|
||||||
|
return tDIGIT
|
||||||
|
}
|
||||||
|
yyrule2: // "now"
|
||||||
|
{
|
||||||
|
|
||||||
|
return tNOW
|
||||||
|
}
|
||||||
|
yyrule3: // "+"
|
||||||
|
{
|
||||||
|
|
||||||
|
return tPLUS
|
||||||
|
}
|
||||||
|
yyrule4: // "-"
|
||||||
|
{
|
||||||
|
|
||||||
|
return tMINUS
|
||||||
|
}
|
||||||
|
yyrule5: // ":"
|
||||||
|
{
|
||||||
|
|
||||||
|
return tCOLON
|
||||||
|
}
|
||||||
|
yyrule6: // "||"
|
||||||
|
{
|
||||||
|
|
||||||
|
return tPIPES
|
||||||
|
}
|
||||||
|
yyrule7: // "/"
|
||||||
|
{
|
||||||
|
|
||||||
|
return tBACKSLASH
|
||||||
|
}
|
||||||
|
yyrule8: // [yMwdbhHms]
|
||||||
|
{
|
||||||
|
|
||||||
|
switch l.buf[0] {
|
||||||
|
case 'y':
|
||||||
|
lval.unit = timeUnitYear
|
||||||
|
case 'M':
|
||||||
|
lval.unit = timeUnitMonth
|
||||||
|
case 'w':
|
||||||
|
lval.unit = timeUnitWeek
|
||||||
|
case 'b':
|
||||||
|
lval.unit = timeUnitBusinessDay
|
||||||
|
case 'd':
|
||||||
|
lval.unit = timeUnitDay
|
||||||
|
case 'h', 'H':
|
||||||
|
lval.unit = timeUnitHour
|
||||||
|
case 'm':
|
||||||
|
lval.unit = timeUnitMinute
|
||||||
|
case 's':
|
||||||
|
lval.unit = timeUnitSecond
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown time unit: %q", l.buf[0]))
|
||||||
|
}
|
||||||
|
return tUNIT
|
||||||
|
}
|
||||||
|
yyrule9: // \.
|
||||||
|
{
|
||||||
|
|
||||||
|
return tDOT
|
||||||
|
}
|
||||||
|
yyrule10: // "T"
|
||||||
|
{
|
||||||
|
|
||||||
|
return tTIME_DELIMITER
|
||||||
|
}
|
||||||
|
yyrule11: // "Z"
|
||||||
|
{
|
||||||
|
|
||||||
|
return tUTC
|
||||||
|
}
|
||||||
|
yyrule12: // {eof}
|
||||||
|
{
|
||||||
|
|
||||||
|
return eofCode
|
||||||
|
}
|
||||||
|
yyrule13: // .
|
||||||
|
if true { // avoid go vet determining the below panic will not be reached
|
||||||
|
|
||||||
|
return tINVALID_TOKEN
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
|
||||||
|
yyabort: // no lexem recognized
|
||||||
|
//
|
||||||
|
// silence unused label errors for build and satisfy go vet reachability analysis
|
||||||
|
//
|
||||||
|
{
|
||||||
|
if false {
|
||||||
|
goto yyabort
|
||||||
|
}
|
||||||
|
if false {
|
||||||
|
goto yystate0
|
||||||
|
}
|
||||||
|
if false {
|
||||||
|
goto yystate1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// should never get here
|
||||||
|
panic("scanner internal error")
|
||||||
|
}
|
||||||
300
vendor/github.com/timberio/go-datemath/datemath.y
generated
vendored
Normal file
300
vendor/github.com/timberio/go-datemath/datemath.y
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
|||||||
|
/*
|
||||||
|
This file is used with goyacc to generate a parser.
|
||||||
|
|
||||||
|
See https://godoc.org/golang.org/x/tools/cmd/goyacc for more about goyacc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
%{
|
||||||
|
package datemath
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var epoch = time.Unix(0, 0).In(time.UTC)
|
||||||
|
|
||||||
|
// convert a list of significant digits to an integer
|
||||||
|
// assumes most to least significant
|
||||||
|
// e.g. 5,2,3 -> 523
|
||||||
|
func digitsToInt(digits ...int) int {
|
||||||
|
n := 0
|
||||||
|
for i := range digits {
|
||||||
|
n += digits[i] * int(math.Pow10(len(digits)-i-1))
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
/* set of valid tokens; generated constants used by lexer */
|
||||||
|
%token tNOW tPLUS tMINUS tPIPES tBACKSLASH tTIME_DELIMITER tCOLON tDOT tUNIT tUTC tDIGIT tINVALID_TOKEN
|
||||||
|
|
||||||
|
/* Go variables to hold the corresponding token values */
|
||||||
|
%union {
|
||||||
|
i64 int64
|
||||||
|
i int
|
||||||
|
unit timeUnit
|
||||||
|
month time.Month
|
||||||
|
|
||||||
|
expression mathExpression
|
||||||
|
anchorDateExpression anchorDateExpression
|
||||||
|
timeAdjuster timeAdjuster
|
||||||
|
timeAdjusters []timeAdjuster
|
||||||
|
|
||||||
|
location *time.Location
|
||||||
|
time time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
/* associate tokens with Go types */
|
||||||
|
%type <unit> tUNIT
|
||||||
|
%type <i> sign factor number year day hour minute second nanoseconds tDIGIT
|
||||||
|
%type <month> month
|
||||||
|
%type <expression> expression
|
||||||
|
%type <time> date time absolute_date_expression
|
||||||
|
%type <i64> millitimestamp
|
||||||
|
%type <timeAdjusters> date_math_expressions
|
||||||
|
%type <timeAdjuster> date_math_expression
|
||||||
|
%type <location> timezone
|
||||||
|
|
||||||
|
%error start tINVALID_TOKEN :
|
||||||
|
"invalid token"
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
start : expression { // last rule; assign the evaluated time so we can use use it later
|
||||||
|
yylex.(*lexerWrapper).expression = $1
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* an expression can be either a:
|
||||||
|
* * A ISO8601 timestamp (can be truncated)
|
||||||
|
* * the string "now"
|
||||||
|
*
|
||||||
|
* followed by list of date math expressions
|
||||||
|
*/
|
||||||
|
expression :
|
||||||
|
absolute_date_expression {
|
||||||
|
$$ = newMathExpression(anchorDate($1), nil)
|
||||||
|
}
|
||||||
|
| absolute_date_expression tPIPES {
|
||||||
|
$$ = newMathExpression(anchorDate($1), nil)
|
||||||
|
}
|
||||||
|
| absolute_date_expression tPIPES date_math_expressions {
|
||||||
|
$$ = newMathExpression(anchorDate($1), $3)
|
||||||
|
}
|
||||||
|
| tNOW {
|
||||||
|
$$ = newMathExpression(anchorDateNow, nil)
|
||||||
|
}
|
||||||
|
| tNOW date_math_expressions {
|
||||||
|
$$ = newMathExpression(anchorDateNow, $2)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An absolute date expression can be:
|
||||||
|
* * a unix timestamp in milliseconds
|
||||||
|
* * a date
|
||||||
|
* * a time
|
||||||
|
* * a datetime
|
||||||
|
* Dates and times can be truncated by leaving off smaller units. For example, 2006 would map to 2006-01-01T00:00:00
|
||||||
|
*/
|
||||||
|
absolute_date_expression :
|
||||||
|
date {
|
||||||
|
$$ = $1
|
||||||
|
}
|
||||||
|
|
|
||||||
|
time {
|
||||||
|
$$ = $1
|
||||||
|
}
|
||||||
|
|
|
||||||
|
date tTIME_DELIMITER time timezone {
|
||||||
|
$$ = time.Date($1.Year(), $1.Month(), $1.Day(), $3.Hour(), $3.Minute(), $3.Second(), $3.Nanosecond(), $4)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
millitimestamp {
|
||||||
|
$$ = time.Unix($1 / 1000, $1%1000 * 1000000)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
timezone :
|
||||||
|
/* empty */ {
|
||||||
|
$$ = missingTimeZone
|
||||||
|
}
|
||||||
|
|
|
||||||
|
sign tDIGIT tDIGIT tCOLON tDIGIT tDIGIT { /* support +/-09:00 style timezone specifiers */
|
||||||
|
$$ = time.FixedZone("$1$2$3:$5$6", $1 * ((($2 * 10 + $3) * 60 * 60) + (($5 * 10 + $6) * 60)))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
tUTC { /* Z */
|
||||||
|
$$ = time.UTC
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
date :
|
||||||
|
year {
|
||||||
|
$$ = time.Date($1, 1, 1, 0, 0, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
year tMINUS month {
|
||||||
|
$$ = time.Date($1, $3, 1, 0, 0, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
year tMINUS month tMINUS day {
|
||||||
|
if $5 > daysIn($3, $1) {
|
||||||
|
yylex.Error(fmt.Sprintf("day %d out of bounds for month %d", $5, $3))
|
||||||
|
}
|
||||||
|
$$ = time.Date($1, $3, $5, 0, 0, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/* store in a time.Time struct using the epoch for the year/month/day */
|
||||||
|
time :
|
||||||
|
hour {
|
||||||
|
$$ = time.Date(epoch.Year(), epoch.Month(), epoch.Day(), $1, 0, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
hour tCOLON minute {
|
||||||
|
$$ = time.Date(epoch.Year(), epoch.Month(), epoch.Day(), $1, $3, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
hour tCOLON minute tCOLON second {
|
||||||
|
$$ = time.Date(epoch.Year(), epoch.Month(), epoch.Day(), $1, $3, $5, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
hour tCOLON minute tCOLON second tDOT nanoseconds {
|
||||||
|
$$ = time.Date(epoch.Year(), epoch.Month(), epoch.Day(), $1, $3, $5, $7, missingTimeZone)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
year :
|
||||||
|
tDIGIT tDIGIT tDIGIT tDIGIT {
|
||||||
|
$$ = digitsToInt($1, $2, $3, $4)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
month:
|
||||||
|
tDIGIT tDIGIT {
|
||||||
|
$$ = time.Month(digitsToInt($1, $2))
|
||||||
|
if $$ > 12 {
|
||||||
|
yylex.Error(fmt.Sprintf("month out of bounds %d", $$))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
day:
|
||||||
|
tDIGIT tDIGIT {
|
||||||
|
// range validated in `date`
|
||||||
|
$$ = digitsToInt($1, $2)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
hour:
|
||||||
|
tDIGIT tDIGIT {
|
||||||
|
$$ = digitsToInt($1, $2)
|
||||||
|
if $$ > 23 {
|
||||||
|
yylex.Error(fmt.Sprintf("hours out of bounds %d", $$))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
minute:
|
||||||
|
tDIGIT tDIGIT {
|
||||||
|
$$ = digitsToInt($1, $2)
|
||||||
|
if $$ > 59 {
|
||||||
|
yylex.Error(fmt.Sprintf("minutes out of bounds %d", $$))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
second:
|
||||||
|
tDIGIT tDIGIT {
|
||||||
|
$$ = digitsToInt($1, $2)
|
||||||
|
if $$ > 59 {
|
||||||
|
yylex.Error(fmt.Sprintf("seconds out of bounds %d", $$))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/* only supports 3 digits for fractional seconds for now */
|
||||||
|
nanoseconds:
|
||||||
|
tDIGIT {
|
||||||
|
$$ = $1 * 100000000
|
||||||
|
}
|
||||||
|
|
|
||||||
|
tDIGIT tDIGIT {
|
||||||
|
$$ = digitsToInt($1, $2) * 10000000
|
||||||
|
}
|
||||||
|
|
|
||||||
|
tDIGIT tDIGIT tDIGIT {
|
||||||
|
$$ = digitsToInt($1, $2, $3) * 1000000
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/* allow for list of time adjustments; evaluated from left to right */
|
||||||
|
date_math_expressions :
|
||||||
|
date_math_expression date_math_expressions {
|
||||||
|
$$ = append([]timeAdjuster{$1}, $2...)
|
||||||
|
/*f, g := $1, $2 // bind to local scope*/
|
||||||
|
/*$$ = func(t time.Time) time.Time {*/
|
||||||
|
/*return g(f(t))*/
|
||||||
|
/*}*/
|
||||||
|
}
|
||||||
|
|
|
||||||
|
date_math_expression {
|
||||||
|
$$ = []timeAdjuster{$1}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
date_math_expression :
|
||||||
|
sign factor tUNIT { /* add units; e.g. +15m */
|
||||||
|
$$ = addUnits($1 * $2, $3)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
tBACKSLASH tUNIT { /* truncate to specified unit: e.g. /d */
|
||||||
|
$$ = truncateUnits($2)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
sign :
|
||||||
|
tMINUS {
|
||||||
|
$$ = -1
|
||||||
|
}
|
||||||
|
|
|
||||||
|
tPLUS {
|
||||||
|
$$ = 1
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
factor :
|
||||||
|
/* empty */ { /* default to 1 if no integer specified */
|
||||||
|
$$ = 1
|
||||||
|
}
|
||||||
|
|
|
||||||
|
number {
|
||||||
|
$$ = $1
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
number :
|
||||||
|
tDIGIT {
|
||||||
|
$$ = $1
|
||||||
|
}
|
||||||
|
|
|
||||||
|
number tDIGIT {
|
||||||
|
$$ = $1 * 10 + $2
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
/* 5 digits or longer is considered a timestamp */
|
||||||
|
millitimestamp:
|
||||||
|
tDIGIT tDIGIT tDIGIT tDIGIT tDIGIT {
|
||||||
|
$$ = int64(digitsToInt($1, $2, $3, $4, $5))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
millitimestamp tDIGIT {
|
||||||
|
$$ = $1 * 10 + int64($2)
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
776
vendor/github.com/timberio/go-datemath/datemath.y.go
generated
vendored
Normal file
776
vendor/github.com/timberio/go-datemath/datemath.y.go
generated
vendored
Normal file
@@ -0,0 +1,776 @@
|
|||||||
|
// Code generated by goyacc -o datemath.y.go datemath.y. DO NOT EDIT.
|
||||||
|
|
||||||
|
//line datemath.y:8
|
||||||
|
package datemath
|
||||||
|
|
||||||
|
import __yyfmt__ "fmt"
|
||||||
|
|
||||||
|
//line datemath.y:8
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var epoch = time.Unix(0, 0).In(time.UTC)
|
||||||
|
|
||||||
|
// convert a list of significant digits to an integer
|
||||||
|
// assumes most to least significant
|
||||||
|
// e.g. 5,2,3 -> 523
|
||||||
|
func digitsToInt(digits ...int) int {
|
||||||
|
n := 0
|
||||||
|
for i := range digits {
|
||||||
|
n += digits[i] * int(math.Pow10(len(digits)-i-1))
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
//line datemath.y:34
|
||||||
|
type yySymType struct {
|
||||||
|
yys int
|
||||||
|
i64 int64
|
||||||
|
i int
|
||||||
|
unit timeUnit
|
||||||
|
month time.Month
|
||||||
|
|
||||||
|
expression mathExpression
|
||||||
|
anchorDateExpression anchorDateExpression
|
||||||
|
timeAdjuster timeAdjuster
|
||||||
|
timeAdjusters []timeAdjuster
|
||||||
|
|
||||||
|
location *time.Location
|
||||||
|
time time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
const tNOW = 57346
|
||||||
|
const tPLUS = 57347
|
||||||
|
const tMINUS = 57348
|
||||||
|
const tPIPES = 57349
|
||||||
|
const tBACKSLASH = 57350
|
||||||
|
const tTIME_DELIMITER = 57351
|
||||||
|
const tCOLON = 57352
|
||||||
|
const tDOT = 57353
|
||||||
|
const tUNIT = 57354
|
||||||
|
const tUTC = 57355
|
||||||
|
const tDIGIT = 57356
|
||||||
|
const tINVALID_TOKEN = 57357
|
||||||
|
|
||||||
|
var yyToknames = [...]string{
|
||||||
|
"$end",
|
||||||
|
"error",
|
||||||
|
"$unk",
|
||||||
|
"tNOW",
|
||||||
|
"tPLUS",
|
||||||
|
"tMINUS",
|
||||||
|
"tPIPES",
|
||||||
|
"tBACKSLASH",
|
||||||
|
"tTIME_DELIMITER",
|
||||||
|
"tCOLON",
|
||||||
|
"tDOT",
|
||||||
|
"tUNIT",
|
||||||
|
"tUTC",
|
||||||
|
"tDIGIT",
|
||||||
|
"tINVALID_TOKEN",
|
||||||
|
}
|
||||||
|
var yyStatenames = [...]string{}
|
||||||
|
|
||||||
|
const yyEofCode = 1
|
||||||
|
const yyErrCode = 2
|
||||||
|
const yyInitialStackSize = 16
|
||||||
|
|
||||||
|
//line datemath.y:300
|
||||||
|
|
||||||
|
//line yacctab:1
|
||||||
|
var yyExca = [...]int{
|
||||||
|
-1, 1,
|
||||||
|
1, -1,
|
||||||
|
-2, 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
const yyPrivate = 57344
|
||||||
|
|
||||||
|
const yyLast = 65
|
||||||
|
|
||||||
|
var yyAct = [...]int{
|
||||||
|
|
||||||
|
14, 6, 17, 16, 4, 12, 63, 62, 61, 60,
|
||||||
|
40, 42, 59, 56, 10, 54, 53, 23, 52, 24,
|
||||||
|
29, 51, 49, 47, 46, 45, 43, 41, 37, 35,
|
||||||
|
39, 34, 32, 30, 27, 22, 19, 36, 28, 55,
|
||||||
|
57, 44, 17, 16, 21, 15, 11, 18, 20, 1,
|
||||||
|
38, 13, 7, 3, 5, 2, 31, 58, 50, 33,
|
||||||
|
9, 48, 8, 26, 25,
|
||||||
|
}
|
||||||
|
var yyPact = [...]int{
|
||||||
|
|
||||||
|
0, -1000, -1000, 39, 37, 38, -1000, 22, 42, 34,
|
||||||
|
21, 37, -1000, 37, 20, 26, -1000, -1000, 19, -1000,
|
||||||
|
18, 17, 15, -1000, -1000, 25, 14, -1000, -1000, -3,
|
||||||
|
13, 5, 12, 31, 11, 10, -1000, -1000, -1000, 9,
|
||||||
|
-1000, -1000, 8, -1000, 7, -1000, 4, 2, -1000, 1,
|
||||||
|
28, -1, -1000, 30, -1000, -2, -1000, -5, -1000, -6,
|
||||||
|
-7, -8, -1000, -1000,
|
||||||
|
}
|
||||||
|
var yyPgo = [...]int{
|
||||||
|
|
||||||
|
0, 0, 64, 63, 62, 61, 60, 59, 58, 57,
|
||||||
|
56, 55, 54, 1, 53, 52, 5, 51, 50, 49,
|
||||||
|
}
|
||||||
|
var yyR1 = [...]int{
|
||||||
|
|
||||||
|
0, 19, 11, 11, 11, 11, 11, 14, 14, 14,
|
||||||
|
14, 18, 18, 18, 12, 12, 12, 13, 13, 13,
|
||||||
|
13, 4, 10, 5, 6, 7, 8, 9, 9, 9,
|
||||||
|
16, 16, 17, 17, 1, 1, 2, 2, 3, 3,
|
||||||
|
15, 15,
|
||||||
|
}
|
||||||
|
var yyR2 = [...]int{
|
||||||
|
|
||||||
|
0, 1, 1, 2, 3, 1, 2, 1, 1, 4,
|
||||||
|
1, 0, 6, 1, 1, 3, 5, 1, 3, 5,
|
||||||
|
7, 4, 2, 2, 2, 2, 2, 1, 2, 3,
|
||||||
|
2, 1, 3, 2, 1, 1, 0, 1, 1, 2,
|
||||||
|
5, 2,
|
||||||
|
}
|
||||||
|
var yyChk = [...]int{
|
||||||
|
|
||||||
|
-1000, -19, -11, -14, 4, -12, -13, -15, -4, -6,
|
||||||
|
14, 7, -16, -17, -1, 8, 6, 5, 9, 14,
|
||||||
|
6, 10, 14, -16, -16, -2, -3, 14, 12, -13,
|
||||||
|
14, -10, 14, -7, 14, 14, 12, 14, -18, -1,
|
||||||
|
13, 14, 6, 14, 10, 14, 14, 14, -5, 14,
|
||||||
|
-8, 14, 14, 14, 14, 11, 14, 10, -9, 14,
|
||||||
|
14, 14, 14, 14,
|
||||||
|
}
|
||||||
|
var yyDef = [...]int{
|
||||||
|
|
||||||
|
0, -2, 1, 2, 5, 7, 8, 10, 14, 17,
|
||||||
|
0, 3, 6, 31, 36, 0, 34, 35, 0, 41,
|
||||||
|
0, 0, 24, 4, 30, 0, 37, 38, 33, 11,
|
||||||
|
0, 15, 0, 18, 0, 0, 32, 39, 9, 0,
|
||||||
|
13, 24, 0, 22, 0, 25, 21, 0, 16, 0,
|
||||||
|
19, 0, 40, 0, 23, 0, 26, 0, 20, 27,
|
||||||
|
0, 28, 12, 29,
|
||||||
|
}
|
||||||
|
var yyTok1 = [...]int{
|
||||||
|
|
||||||
|
1,
|
||||||
|
}
|
||||||
|
var yyTok2 = [...]int{
|
||||||
|
|
||||||
|
2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
|
||||||
|
12, 13, 14, 15,
|
||||||
|
}
|
||||||
|
var yyTok3 = [...]int{
|
||||||
|
0,
|
||||||
|
}
|
||||||
|
|
||||||
|
var yyErrorMessages = [...]struct {
|
||||||
|
state int
|
||||||
|
token int
|
||||||
|
msg string
|
||||||
|
}{
|
||||||
|
{1, 15, "invalid token"},
|
||||||
|
}
|
||||||
|
|
||||||
|
//line yaccpar:1
|
||||||
|
|
||||||
|
/* parser for yacc output */
|
||||||
|
|
||||||
|
var (
|
||||||
|
yyDebug = 0
|
||||||
|
yyErrorVerbose = false
|
||||||
|
)
|
||||||
|
|
||||||
|
type yyLexer interface {
|
||||||
|
Lex(lval *yySymType) int
|
||||||
|
Error(s string)
|
||||||
|
}
|
||||||
|
|
||||||
|
type yyParser interface {
|
||||||
|
Parse(yyLexer) int
|
||||||
|
Lookahead() int
|
||||||
|
}
|
||||||
|
|
||||||
|
type yyParserImpl struct {
|
||||||
|
lval yySymType
|
||||||
|
stack [yyInitialStackSize]yySymType
|
||||||
|
char int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *yyParserImpl) Lookahead() int {
|
||||||
|
return p.char
|
||||||
|
}
|
||||||
|
|
||||||
|
func yyNewParser() yyParser {
|
||||||
|
return &yyParserImpl{}
|
||||||
|
}
|
||||||
|
|
||||||
|
const yyFlag = -1000
|
||||||
|
|
||||||
|
func yyTokname(c int) string {
|
||||||
|
if c >= 1 && c-1 < len(yyToknames) {
|
||||||
|
if yyToknames[c-1] != "" {
|
||||||
|
return yyToknames[c-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return __yyfmt__.Sprintf("tok-%v", c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func yyStatname(s int) string {
|
||||||
|
if s >= 0 && s < len(yyStatenames) {
|
||||||
|
if yyStatenames[s] != "" {
|
||||||
|
return yyStatenames[s]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return __yyfmt__.Sprintf("state-%v", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func yyErrorMessage(state, lookAhead int) string {
|
||||||
|
const TOKSTART = 4
|
||||||
|
|
||||||
|
if !yyErrorVerbose {
|
||||||
|
return "syntax error"
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range yyErrorMessages {
|
||||||
|
if e.state == state && e.token == lookAhead {
|
||||||
|
return "syntax error: " + e.msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res := "syntax error: unexpected " + yyTokname(lookAhead)
|
||||||
|
|
||||||
|
// To match Bison, suggest at most four expected tokens.
|
||||||
|
expected := make([]int, 0, 4)
|
||||||
|
|
||||||
|
// Look for shiftable tokens.
|
||||||
|
base := yyPact[state]
|
||||||
|
for tok := TOKSTART; tok-1 < len(yyToknames); tok++ {
|
||||||
|
if n := base + tok; n >= 0 && n < yyLast && yyChk[yyAct[n]] == tok {
|
||||||
|
if len(expected) == cap(expected) {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
expected = append(expected, tok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if yyDef[state] == -2 {
|
||||||
|
i := 0
|
||||||
|
for yyExca[i] != -1 || yyExca[i+1] != state {
|
||||||
|
i += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for tokens that we accept or reduce.
|
||||||
|
for i += 2; yyExca[i] >= 0; i += 2 {
|
||||||
|
tok := yyExca[i]
|
||||||
|
if tok < TOKSTART || yyExca[i+1] == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(expected) == cap(expected) {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
expected = append(expected, tok)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the default action is to accept or reduce, give up.
|
||||||
|
if yyExca[i+1] != 0 {
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tok := range expected {
|
||||||
|
if i == 0 {
|
||||||
|
res += ", expecting "
|
||||||
|
} else {
|
||||||
|
res += " or "
|
||||||
|
}
|
||||||
|
res += yyTokname(tok)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func yylex1(lex yyLexer, lval *yySymType) (char, token int) {
|
||||||
|
token = 0
|
||||||
|
char = lex.Lex(lval)
|
||||||
|
if char <= 0 {
|
||||||
|
token = yyTok1[0]
|
||||||
|
goto out
|
||||||
|
}
|
||||||
|
if char < len(yyTok1) {
|
||||||
|
token = yyTok1[char]
|
||||||
|
goto out
|
||||||
|
}
|
||||||
|
if char >= yyPrivate {
|
||||||
|
if char < yyPrivate+len(yyTok2) {
|
||||||
|
token = yyTok2[char-yyPrivate]
|
||||||
|
goto out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 0; i < len(yyTok3); i += 2 {
|
||||||
|
token = yyTok3[i+0]
|
||||||
|
if token == char {
|
||||||
|
token = yyTok3[i+1]
|
||||||
|
goto out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if token == 0 {
|
||||||
|
token = yyTok2[1] /* unknown char */
|
||||||
|
}
|
||||||
|
if yyDebug >= 3 {
|
||||||
|
__yyfmt__.Printf("lex %s(%d)\n", yyTokname(token), uint(char))
|
||||||
|
}
|
||||||
|
return char, token
|
||||||
|
}
|
||||||
|
|
||||||
|
func yyParse(yylex yyLexer) int {
|
||||||
|
return yyNewParser().Parse(yylex)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int {
|
||||||
|
var yyn int
|
||||||
|
var yyVAL yySymType
|
||||||
|
var yyDollar []yySymType
|
||||||
|
_ = yyDollar // silence set and not used
|
||||||
|
yyS := yyrcvr.stack[:]
|
||||||
|
|
||||||
|
Nerrs := 0 /* number of errors */
|
||||||
|
Errflag := 0 /* error recovery flag */
|
||||||
|
yystate := 0
|
||||||
|
yyrcvr.char = -1
|
||||||
|
yytoken := -1 // yyrcvr.char translated into internal numbering
|
||||||
|
defer func() {
|
||||||
|
// Make sure we report no lookahead when not parsing.
|
||||||
|
yystate = -1
|
||||||
|
yyrcvr.char = -1
|
||||||
|
yytoken = -1
|
||||||
|
}()
|
||||||
|
yyp := -1
|
||||||
|
goto yystack
|
||||||
|
|
||||||
|
ret0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
ret1:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
yystack:
|
||||||
|
/* put a state and value onto the stack */
|
||||||
|
if yyDebug >= 4 {
|
||||||
|
__yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate))
|
||||||
|
}
|
||||||
|
|
||||||
|
yyp++
|
||||||
|
if yyp >= len(yyS) {
|
||||||
|
nyys := make([]yySymType, len(yyS)*2)
|
||||||
|
copy(nyys, yyS)
|
||||||
|
yyS = nyys
|
||||||
|
}
|
||||||
|
yyS[yyp] = yyVAL
|
||||||
|
yyS[yyp].yys = yystate
|
||||||
|
|
||||||
|
yynewstate:
|
||||||
|
yyn = yyPact[yystate]
|
||||||
|
if yyn <= yyFlag {
|
||||||
|
goto yydefault /* simple state */
|
||||||
|
}
|
||||||
|
if yyrcvr.char < 0 {
|
||||||
|
yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval)
|
||||||
|
}
|
||||||
|
yyn += yytoken
|
||||||
|
if yyn < 0 || yyn >= yyLast {
|
||||||
|
goto yydefault
|
||||||
|
}
|
||||||
|
yyn = yyAct[yyn]
|
||||||
|
if yyChk[yyn] == yytoken { /* valid shift */
|
||||||
|
yyrcvr.char = -1
|
||||||
|
yytoken = -1
|
||||||
|
yyVAL = yyrcvr.lval
|
||||||
|
yystate = yyn
|
||||||
|
if Errflag > 0 {
|
||||||
|
Errflag--
|
||||||
|
}
|
||||||
|
goto yystack
|
||||||
|
}
|
||||||
|
|
||||||
|
yydefault:
|
||||||
|
/* default state action */
|
||||||
|
yyn = yyDef[yystate]
|
||||||
|
if yyn == -2 {
|
||||||
|
if yyrcvr.char < 0 {
|
||||||
|
yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* look through exception table */
|
||||||
|
xi := 0
|
||||||
|
for {
|
||||||
|
if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
xi += 2
|
||||||
|
}
|
||||||
|
for xi += 2; ; xi += 2 {
|
||||||
|
yyn = yyExca[xi+0]
|
||||||
|
if yyn < 0 || yyn == yytoken {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
yyn = yyExca[xi+1]
|
||||||
|
if yyn < 0 {
|
||||||
|
goto ret0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if yyn == 0 {
|
||||||
|
/* error ... attempt to resume parsing */
|
||||||
|
switch Errflag {
|
||||||
|
case 0: /* brand new error */
|
||||||
|
yylex.Error(yyErrorMessage(yystate, yytoken))
|
||||||
|
Nerrs++
|
||||||
|
if yyDebug >= 1 {
|
||||||
|
__yyfmt__.Printf("%s", yyStatname(yystate))
|
||||||
|
__yyfmt__.Printf(" saw %s\n", yyTokname(yytoken))
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
|
||||||
|
case 1, 2: /* incompletely recovered error ... try again */
|
||||||
|
Errflag = 3
|
||||||
|
|
||||||
|
/* find a state where "error" is a legal shift action */
|
||||||
|
for yyp >= 0 {
|
||||||
|
yyn = yyPact[yyS[yyp].yys] + yyErrCode
|
||||||
|
if yyn >= 0 && yyn < yyLast {
|
||||||
|
yystate = yyAct[yyn] /* simulate a shift of "error" */
|
||||||
|
if yyChk[yystate] == yyErrCode {
|
||||||
|
goto yystack
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the current p has no shift on "error", pop stack */
|
||||||
|
if yyDebug >= 2 {
|
||||||
|
__yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys)
|
||||||
|
}
|
||||||
|
yyp--
|
||||||
|
}
|
||||||
|
/* there is no state on the stack with an error shift ... abort */
|
||||||
|
goto ret1
|
||||||
|
|
||||||
|
case 3: /* no shift yet; clobber input char */
|
||||||
|
if yyDebug >= 2 {
|
||||||
|
__yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken))
|
||||||
|
}
|
||||||
|
if yytoken == yyEofCode {
|
||||||
|
goto ret1
|
||||||
|
}
|
||||||
|
yyrcvr.char = -1
|
||||||
|
yytoken = -1
|
||||||
|
goto yynewstate /* try again in the same state */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reduction by production yyn */
|
||||||
|
if yyDebug >= 2 {
|
||||||
|
__yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate))
|
||||||
|
}
|
||||||
|
|
||||||
|
yynt := yyn
|
||||||
|
yypt := yyp
|
||||||
|
_ = yypt // guard against "declared and not used"
|
||||||
|
|
||||||
|
yyp -= yyR2[yyn]
|
||||||
|
// yyp is now the index of $0. Perform the default action. Iff the
|
||||||
|
// reduced production is ε, $1 is possibly out of range.
|
||||||
|
if yyp+1 >= len(yyS) {
|
||||||
|
nyys := make([]yySymType, len(yyS)*2)
|
||||||
|
copy(nyys, yyS)
|
||||||
|
yyS = nyys
|
||||||
|
}
|
||||||
|
yyVAL = yyS[yyp+1]
|
||||||
|
|
||||||
|
/* consult goto table to find next state */
|
||||||
|
yyn = yyR1[yyn]
|
||||||
|
yyg := yyPgo[yyn]
|
||||||
|
yyj := yyg + yyS[yyp].yys + 1
|
||||||
|
|
||||||
|
if yyj >= yyLast {
|
||||||
|
yystate = yyAct[yyg]
|
||||||
|
} else {
|
||||||
|
yystate = yyAct[yyj]
|
||||||
|
if yyChk[yystate] != -yyn {
|
||||||
|
yystate = yyAct[yyg]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// dummy call; replaced with literal code
|
||||||
|
switch yynt {
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:65
|
||||||
|
{ // last rule; assign the evaluated time so we can use use it later
|
||||||
|
yylex.(*lexerWrapper).expression = yyDollar[1].expression
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:77
|
||||||
|
{
|
||||||
|
yyVAL.expression = newMathExpression(anchorDate(yyDollar[1].time), nil)
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:80
|
||||||
|
{
|
||||||
|
yyVAL.expression = newMathExpression(anchorDate(yyDollar[1].time), nil)
|
||||||
|
}
|
||||||
|
case 4:
|
||||||
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
|
//line datemath.y:83
|
||||||
|
{
|
||||||
|
yyVAL.expression = newMathExpression(anchorDate(yyDollar[1].time), yyDollar[3].timeAdjusters)
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:86
|
||||||
|
{
|
||||||
|
yyVAL.expression = newMathExpression(anchorDateNow, nil)
|
||||||
|
}
|
||||||
|
case 6:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:89
|
||||||
|
{
|
||||||
|
yyVAL.expression = newMathExpression(anchorDateNow, yyDollar[2].timeAdjusters)
|
||||||
|
}
|
||||||
|
case 7:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:103
|
||||||
|
{
|
||||||
|
yyVAL.time = yyDollar[1].time
|
||||||
|
}
|
||||||
|
case 8:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:107
|
||||||
|
{
|
||||||
|
yyVAL.time = yyDollar[1].time
|
||||||
|
}
|
||||||
|
case 9:
|
||||||
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
|
//line datemath.y:111
|
||||||
|
{
|
||||||
|
yyVAL.time = time.Date(yyDollar[1].time.Year(), yyDollar[1].time.Month(), yyDollar[1].time.Day(), yyDollar[3].time.Hour(), yyDollar[3].time.Minute(), yyDollar[3].time.Second(), yyDollar[3].time.Nanosecond(), yyDollar[4].location)
|
||||||
|
}
|
||||||
|
case 10:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:115
|
||||||
|
{
|
||||||
|
yyVAL.time = time.Unix(yyDollar[1].i64/1000, yyDollar[1].i64%1000*1000000)
|
||||||
|
}
|
||||||
|
case 11:
|
||||||
|
yyDollar = yyS[yypt-0 : yypt+1]
|
||||||
|
//line datemath.y:121
|
||||||
|
{
|
||||||
|
yyVAL.location = missingTimeZone
|
||||||
|
}
|
||||||
|
case 12:
|
||||||
|
yyDollar = yyS[yypt-6 : yypt+1]
|
||||||
|
//line datemath.y:125
|
||||||
|
{ /* support +/-09:00 style timezone specifiers */
|
||||||
|
yyVAL.location = time.FixedZone("$1$2$3:$5$6", yyDollar[1].i*(((yyDollar[2].i*10+yyDollar[3].i)*60*60)+((yyDollar[5].i*10+yyDollar[6].i)*60)))
|
||||||
|
}
|
||||||
|
case 13:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:129
|
||||||
|
{ /* Z */
|
||||||
|
yyVAL.location = time.UTC
|
||||||
|
}
|
||||||
|
case 14:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:135
|
||||||
|
{
|
||||||
|
yyVAL.time = time.Date(yyDollar[1].i, 1, 1, 0, 0, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
case 15:
|
||||||
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
|
//line datemath.y:139
|
||||||
|
{
|
||||||
|
yyVAL.time = time.Date(yyDollar[1].i, yyDollar[3].month, 1, 0, 0, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
case 16:
|
||||||
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
|
//line datemath.y:143
|
||||||
|
{
|
||||||
|
if yyDollar[5].i > daysIn(yyDollar[3].month, yyDollar[1].i) {
|
||||||
|
yylex.Error(fmt.Sprintf("day %d out of bounds for month %d", yyDollar[5].i, yyDollar[3].month))
|
||||||
|
}
|
||||||
|
yyVAL.time = time.Date(yyDollar[1].i, yyDollar[3].month, yyDollar[5].i, 0, 0, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
case 17:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:153
|
||||||
|
{
|
||||||
|
yyVAL.time = time.Date(epoch.Year(), epoch.Month(), epoch.Day(), yyDollar[1].i, 0, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
case 18:
|
||||||
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
|
//line datemath.y:157
|
||||||
|
{
|
||||||
|
yyVAL.time = time.Date(epoch.Year(), epoch.Month(), epoch.Day(), yyDollar[1].i, yyDollar[3].i, 0, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
case 19:
|
||||||
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
|
//line datemath.y:161
|
||||||
|
{
|
||||||
|
yyVAL.time = time.Date(epoch.Year(), epoch.Month(), epoch.Day(), yyDollar[1].i, yyDollar[3].i, yyDollar[5].i, 0, missingTimeZone)
|
||||||
|
}
|
||||||
|
case 20:
|
||||||
|
yyDollar = yyS[yypt-7 : yypt+1]
|
||||||
|
//line datemath.y:165
|
||||||
|
{
|
||||||
|
yyVAL.time = time.Date(epoch.Year(), epoch.Month(), epoch.Day(), yyDollar[1].i, yyDollar[3].i, yyDollar[5].i, yyDollar[7].i, missingTimeZone)
|
||||||
|
}
|
||||||
|
case 21:
|
||||||
|
yyDollar = yyS[yypt-4 : yypt+1]
|
||||||
|
//line datemath.y:171
|
||||||
|
{
|
||||||
|
yyVAL.i = digitsToInt(yyDollar[1].i, yyDollar[2].i, yyDollar[3].i, yyDollar[4].i)
|
||||||
|
}
|
||||||
|
case 22:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:177
|
||||||
|
{
|
||||||
|
yyVAL.month = time.Month(digitsToInt(yyDollar[1].i, yyDollar[2].i))
|
||||||
|
if yyVAL.month > 12 {
|
||||||
|
yylex.Error(fmt.Sprintf("month out of bounds %d", yyVAL.month))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 23:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:186
|
||||||
|
{
|
||||||
|
// range validated in `date`
|
||||||
|
yyVAL.i = digitsToInt(yyDollar[1].i, yyDollar[2].i)
|
||||||
|
}
|
||||||
|
case 24:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:193
|
||||||
|
{
|
||||||
|
yyVAL.i = digitsToInt(yyDollar[1].i, yyDollar[2].i)
|
||||||
|
if yyVAL.i > 23 {
|
||||||
|
yylex.Error(fmt.Sprintf("hours out of bounds %d", yyVAL.i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 25:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:202
|
||||||
|
{
|
||||||
|
yyVAL.i = digitsToInt(yyDollar[1].i, yyDollar[2].i)
|
||||||
|
if yyVAL.i > 59 {
|
||||||
|
yylex.Error(fmt.Sprintf("minutes out of bounds %d", yyVAL.i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 26:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:211
|
||||||
|
{
|
||||||
|
yyVAL.i = digitsToInt(yyDollar[1].i, yyDollar[2].i)
|
||||||
|
if yyVAL.i > 59 {
|
||||||
|
yylex.Error(fmt.Sprintf("seconds out of bounds %d", yyVAL.i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 27:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:221
|
||||||
|
{
|
||||||
|
yyVAL.i = yyDollar[1].i * 100000000
|
||||||
|
}
|
||||||
|
case 28:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:225
|
||||||
|
{
|
||||||
|
yyVAL.i = digitsToInt(yyDollar[1].i, yyDollar[2].i) * 10000000
|
||||||
|
}
|
||||||
|
case 29:
|
||||||
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
|
//line datemath.y:229
|
||||||
|
{
|
||||||
|
yyVAL.i = digitsToInt(yyDollar[1].i, yyDollar[2].i, yyDollar[3].i) * 1000000
|
||||||
|
}
|
||||||
|
case 30:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:236
|
||||||
|
{
|
||||||
|
yyVAL.timeAdjusters = append([]timeAdjuster{yyDollar[1].timeAdjuster}, yyDollar[2].timeAdjusters...)
|
||||||
|
/*f, g := $1, $2 // bind to local scope*/
|
||||||
|
/*$$ = func(t time.Time) time.Time {*/
|
||||||
|
/*return g(f(t))*/
|
||||||
|
/*}*/
|
||||||
|
}
|
||||||
|
case 31:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:244
|
||||||
|
{
|
||||||
|
yyVAL.timeAdjusters = []timeAdjuster{yyDollar[1].timeAdjuster}
|
||||||
|
}
|
||||||
|
case 32:
|
||||||
|
yyDollar = yyS[yypt-3 : yypt+1]
|
||||||
|
//line datemath.y:250
|
||||||
|
{ /* add units; e.g. +15m */
|
||||||
|
yyVAL.timeAdjuster = addUnits(yyDollar[1].i*yyDollar[2].i, yyDollar[3].unit)
|
||||||
|
}
|
||||||
|
case 33:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:254
|
||||||
|
{ /* truncate to specified unit: e.g. /d */
|
||||||
|
yyVAL.timeAdjuster = truncateUnits(yyDollar[2].unit)
|
||||||
|
}
|
||||||
|
case 34:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:260
|
||||||
|
{
|
||||||
|
yyVAL.i = -1
|
||||||
|
}
|
||||||
|
case 35:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:264
|
||||||
|
{
|
||||||
|
yyVAL.i = 1
|
||||||
|
}
|
||||||
|
case 36:
|
||||||
|
yyDollar = yyS[yypt-0 : yypt+1]
|
||||||
|
//line datemath.y:270
|
||||||
|
{ /* default to 1 if no integer specified */
|
||||||
|
yyVAL.i = 1
|
||||||
|
}
|
||||||
|
case 37:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:274
|
||||||
|
{
|
||||||
|
yyVAL.i = yyDollar[1].i
|
||||||
|
}
|
||||||
|
case 38:
|
||||||
|
yyDollar = yyS[yypt-1 : yypt+1]
|
||||||
|
//line datemath.y:280
|
||||||
|
{
|
||||||
|
yyVAL.i = yyDollar[1].i
|
||||||
|
}
|
||||||
|
case 39:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:284
|
||||||
|
{
|
||||||
|
yyVAL.i = yyDollar[1].i*10 + yyDollar[2].i
|
||||||
|
}
|
||||||
|
case 40:
|
||||||
|
yyDollar = yyS[yypt-5 : yypt+1]
|
||||||
|
//line datemath.y:291
|
||||||
|
{
|
||||||
|
yyVAL.i64 = int64(digitsToInt(yyDollar[1].i, yyDollar[2].i, yyDollar[3].i, yyDollar[4].i, yyDollar[5].i))
|
||||||
|
}
|
||||||
|
case 41:
|
||||||
|
yyDollar = yyS[yypt-2 : yypt+1]
|
||||||
|
//line datemath.y:295
|
||||||
|
{
|
||||||
|
yyVAL.i64 = yyDollar[1].i64*10 + int64(yyDollar[2].i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto yystack /* stack new state and value */
|
||||||
|
}
|
||||||
3
vendor/github.com/timberio/go-datemath/go.mod
generated
vendored
Normal file
3
vendor/github.com/timberio/go-datemath/go.mod
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module github.com/timberio/go-datemath
|
||||||
|
|
||||||
|
go 1.13
|
||||||
0
vendor/github.com/timberio/go-datemath/go.sum
generated
vendored
Normal file
0
vendor/github.com/timberio/go-datemath/go.sum
generated
vendored
Normal file
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -262,6 +262,8 @@ github.com/stretchr/testify/assert
|
|||||||
github.com/stretchr/testify/require
|
github.com/stretchr/testify/require
|
||||||
# github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf
|
# github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf
|
||||||
github.com/teris-io/shortid
|
github.com/teris-io/shortid
|
||||||
|
# github.com/timberio/go-datemath v0.1.1-0.20200323150745-74ddef604fff
|
||||||
|
github.com/timberio/go-datemath
|
||||||
# github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329
|
# github.com/ua-parser/uap-go v0.0.0-20190826212731-daf92ba38329
|
||||||
github.com/ua-parser/uap-go/uaparser
|
github.com/ua-parser/uap-go/uaparser
|
||||||
# github.com/uber/jaeger-client-go v2.20.1+incompatible
|
# github.com/uber/jaeger-client-go v2.20.1+incompatible
|
||||||
|
|||||||
Reference in New Issue
Block a user