Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve ParseTime, handle mismatched format and value #124

Merged
merged 1 commit into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 43 additions & 38 deletions pkg/utils/parse_time.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package utils

import (
"errors"
"fmt"
"reflect"
"time"
Expand All @@ -26,33 +25,44 @@ const Rfc2822zLayout string = "%a, %d %b %Y %T %z"
// Parses a value into Time given a timeOutputFormat. The conversion
// only works with float64 as this is what we get when parsing a response.
func ParseTime(value any, timeOutputFormat string) (time.Time, error) {
switch timeOutputFormat {
case Iso8601, Rfc3339:
switch value.(type) {
case string:
value_string := value.(string)
timeValue, err := time.Parse(time.RFC3339, value_string)
if err != nil {
return time.Time{}, err
}
return timeValue, nil
switch timeOutputFormat {
case Iso8601, Rfc3339:
timeValue, err := time.Parse(time.RFC3339, value_string)
if err != nil {
return time.Time{}, err
}
return timeValue, nil

case Rfc2822:
// XXX: the time package's layout for RFC2822 is bogus, don't use that.
value_string := value.(string)
timeValue, err := timefmt.Parse(value_string, Rfc2822Layout)
if err != nil {
return time.Time{}, err
}
return timeValue, nil
case Rfc2822z:
// XXX: the time package's layout for RFC2822 is bogus, don't use that.
value_string := value.(string)
timeValue, err := timefmt.Parse(value_string, Rfc2822zLayout)
if err != nil {
return time.Time{}, err
}
return timeValue, nil
case Rfc2822:
// XXX: the time package's layout for RFC2822 is bogus, don't use that.
timeValue, err := timefmt.Parse(value_string, Rfc2822Layout)
if err != nil {
return time.Time{}, err
}
return timeValue, nil

case Rfc2822z:
// XXX: the time package's layout for RFC2822 is bogus, don't use that.
timeValue, err := timefmt.Parse(value_string, Rfc2822zLayout)
if err != nil {
return time.Time{}, err
}
return timeValue, nil

case TimestampSecs, TimestampMillis, TimestampMicros, TimestampNanos:
return time.Time{}, fmt.Errorf("ParseTime received incoherent inputs: timeOutputFormat: %s value: %s (%s)", timeOutputFormat, fmt.Sprint(value), reflect.TypeOf(value))

case TimestampSecs, TimestampMillis, TimestampMicros, TimestampNanos:
default:
timeValue, err := timefmt.Parse(value_string, timeOutputFormat)
if err != nil {
return time.Time{}, err
}
return timeValue, nil
}
default:
var value_i64 int64
switch value.(type) {
case int, int8, int16, int32, int64:
Expand All @@ -61,25 +71,20 @@ func ParseTime(value any, timeOutputFormat string) (time.Time, error) {
value_f64 := reflect.ValueOf(value).Float()
value_i64 = int64(value_f64)
default:
return time.Time{}, errors.New("parseTime only accepts float64 or int64 values with timestamp based formats")
return time.Time{}, fmt.Errorf("ParseTime does not support values of type (%s)", reflect.TypeOf(value))
}

if timeOutputFormat == TimestampSecs {
switch timeOutputFormat {
case TimestampSecs:
return time.Unix(value_i64, 0), nil
} else if timeOutputFormat == TimestampMillis {
case TimestampMillis:
return time.Unix(0, value_i64*1_000_000), nil
} else if timeOutputFormat == TimestampMicros {
case TimestampMicros:
return time.Unix(0, value_i64*1_000), nil
} else if timeOutputFormat == TimestampNanos {
case TimestampNanos:
return time.Unix(0, value_i64), nil
default:
return time.Time{}, fmt.Errorf("ParseTime received incoherent inputs: timeOutputFormat: %s value: %s (%s)", timeOutputFormat, fmt.Sprint(value), reflect.TypeOf(value))
}
default:
value_string := value.(string)
timeValue, err := timefmt.Parse(value_string, timeOutputFormat)
if err != nil {
return time.Time{}, err
}
return timeValue, nil
}
return time.Time{}, fmt.Errorf("timeOutputFormat not supported yet %s", timeOutputFormat)
}
8 changes: 8 additions & 0 deletions pkg/utils/parse_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,12 @@ func TestParseTime(t *testing.T) {
}
})
}

t.Run("Error on incoherent format and value", func(t *testing.T) {
value := 1711629296987654321
format := "%Y-%m-%d %H:%M:%S.%f"
_, err := ParseTime(value, format)

assert.ErrorContains(err, fmt.Sprintf("ParseTime received incoherent inputs: timeOutputFormat: %s value: %s (%s)", format, fmt.Sprint(value), "int"))
})
}
Loading