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:
parent
85dc4e565e
commit
f63877f247
1
go.mod
1
go.mod
@ -60,6 +60,7 @@ require (
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
||||
github.com/stretchr/testify v1.4.0
|
||||
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/uber/jaeger-client-go v2.20.1+incompatible
|
||||
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/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/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/go.mod h1:OBcG9bn7sHtXgarhUEb3OfCnNsgtGnkVf41ilSZ3K3E=
|
||||
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/v3"
|
||||
_ "github.com/stretchr/testify/require"
|
||||
_ "github.com/timberio/go-datemath"
|
||||
_ "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/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf
|
||||
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/uaparser
|
||||
# github.com/uber/jaeger-client-go v2.20.1+incompatible
|
||||
|
Loading…
Reference in New Issue
Block a user