diff --git a/influxql/ast.go b/influxql/ast.go index 8bf3c16a79..b0f2efc721 100644 --- a/influxql/ast.go +++ b/influxql/ast.go @@ -810,7 +810,7 @@ type TimeLiteral struct { // String returns a string representation of the literal. func (l *TimeLiteral) String() string { - return `"` + l.Val.UTC().Format(TimeFormat) + `"` + return `"` + l.Val.UTC().Format(DateTimeFormat) + `"` } // DurationLiteral represents a duration literal. diff --git a/influxql/ast_test.go b/influxql/ast_test.go index 85bf902b7b..d12afce621 100644 --- a/influxql/ast_test.go +++ b/influxql/ast_test.go @@ -199,11 +199,11 @@ func TestTimeRange(t *testing.T) { min, max := influxql.TimeRange(expr) // Compare with expected min/max. - if min := min.Format(influxql.TimeFormat); tt.min != min { + if min := min.Format(influxql.DateTimeFormat); tt.min != min { t.Errorf("%d. %s: unexpected min:\n\nexp=%s\n\ngot=%s\n\n", i, tt.expr, tt.min, min) continue } - if max := max.Format(influxql.TimeFormat); tt.max != max { + if max := max.Format(influxql.DateTimeFormat); tt.max != max { t.Errorf("%d. %s: unexpected max:\n\nexp=%s\n\ngot=%s\n\n", i, tt.expr, tt.max, max) continue } diff --git a/influxql/engine.go b/influxql/engine.go index 94fde06485..fbebd713c8 100644 --- a/influxql/engine.go +++ b/influxql/engine.go @@ -60,7 +60,7 @@ func (p *Planner) Plan(stmt *SelectStatement) (*Executor, error) { max = now } if max.Before(min) { - return nil, fmt.Errorf("invalid time range: %s - %s", min.Format(TimeFormat), max.Format(TimeFormat)) + return nil, fmt.Errorf("invalid time range: %s - %s", min.Format(DateTimeFormat), max.Format(DateTimeFormat)) } e.min, e.max = min, max diff --git a/influxql/parser.go b/influxql/parser.go index 9f934a8d97..5b7a498075 100644 --- a/influxql/parser.go +++ b/influxql/parser.go @@ -10,8 +10,13 @@ import ( "time" ) -// TimeFormat represents the format for time literals. -const TimeFormat = "2006-01-02 15:04:05.999999" +const ( + // DateFormat represents the format for date literals. + DateFormat = "2006-01-02" + + // DateTimeFormat represents the format for date time literals. + DateTimeFormat = "2006-01-02 15:04:05.999999" +) // Parser represents an InfluxQL parser. type Parser struct { @@ -852,10 +857,16 @@ func (p *Parser) parseUnaryExpr() (Expr, error) { } case STRING: // If literal looks like a date time then parse it as a time literal. - if isTimeString(lit) { - t, err := time.Parse(TimeFormat, lit) + if isDateTimeString(lit) { + t, err := time.Parse(DateTimeFormat, lit) if err != nil { - return nil, &ParseError{Message: "unable to parse time", Pos: pos} + return nil, &ParseError{Message: "unable to parse datetime", Pos: pos} + } + return &TimeLiteral{Val: t}, nil + } else if isDateString(lit) { + t, err := time.Parse(DateFormat, lit) + if err != nil { + return nil, &ParseError{Message: "unable to parse date", Pos: pos} } return &TimeLiteral{Val: t}, nil } @@ -1034,10 +1045,14 @@ func split(s string) (a []rune) { return } -// isTimeString returns true if the string looks like a time literal. -func isTimeString(s string) bool { return timeStringRegexp.MatchString(s) } +// isDateString returns true if the string looks like a datetime literal. +func isDateString(s string) bool { return dateStringRegexp.MatchString(s) } -var timeStringRegexp = regexp.MustCompile(`^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)?$`) +// isDateTimeString returns true if the string looks like a datetime literal. +func isDateTimeString(s string) bool { return dateTimeStringRegexp.MatchString(s) } + +var dateStringRegexp = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`) +var dateTimeStringRegexp = regexp.MustCompile(`^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}(?:\.\d+)?$`) // ErrInvalidDuration is returned when parsing a malformatted duration. var ErrInvalidDuration = errors.New("invalid duration") diff --git a/influxql/parser_test.go b/influxql/parser_test.go index 97f5899a68..ad347c237b 100644 --- a/influxql/parser_test.go +++ b/influxql/parser_test.go @@ -349,7 +349,9 @@ func TestParser_ParseExpr(t *testing.T) { {s: `false`, expr: &influxql.BooleanLiteral{Val: false}}, {s: `my_ident`, expr: &influxql.VarRef{Val: "my_ident"}}, {s: `"2000-01-01 00:00:00"`, expr: &influxql.TimeLiteral{Val: mustParseTime("2000-01-01T00:00:00Z")}}, - {s: `"2000-01-32 00:00:00"`, err: `unable to parse time at line 1, char 1`}, + {s: `"2000-01-32 00:00:00"`, err: `unable to parse datetime at line 1, char 1`}, + {s: `"2000-01-01"`, expr: &influxql.TimeLiteral{Val: mustParseTime("2000-01-01T00:00:00Z")}}, + {s: `"2000-01-99"`, err: `unable to parse date at line 1, char 1`}, // Simple binary expression {