lib/promutils: hide the math.Round() logic inside ParseTimeMsec() function

This should prevent from bugs similar to https://github.com/VictoriaMetrics/VictoriaMetrics/issues/5801 in the future

This is a follow-up for ce3ec3ff2e
This commit is contained in:
Aliaksandr Valialkin 2024-02-23 00:54:20 +02:00
parent 5934002b57
commit df7d3c55ed
No known key found for this signature in database
GPG key ID: 52C003EE2BCDB9EB
4 changed files with 16 additions and 13 deletions

View file

@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"math"
"time" "time"
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils" "github.com/VictoriaMetrics/VictoriaMetrics/lib/promutils"
@ -15,11 +14,10 @@ const (
) )
func parseTime(s string) (time.Time, error) { func parseTime(s string) (time.Time, error) {
secs, err := promutils.ParseTime(s) msecs, err := promutils.ParseTimeMsec(s)
if err != nil { if err != nil {
return time.Time{}, fmt.Errorf("cannot parse %s: %w", s, err) return time.Time{}, fmt.Errorf("cannot parse %s: %w", s, err)
} }
msecs := int64(math.Round(secs * 1e3))
if msecs < minTimeMsecs { if msecs < minTimeMsecs {
msecs = 0 msecs = 0
} }

View file

@ -28,11 +28,10 @@ func GetTime(r *http.Request, argKey string, defaultMs int64) (int64, error) {
return maxTimeMsecs, nil return maxTimeMsecs, nil
} }
// Parse argValue // Parse argValue
secs, err := promutils.ParseTime(argValue) msecs, err := promutils.ParseTimeMsec(argValue)
if err != nil { if err != nil {
return 0, fmt.Errorf("cannot parse %s=%s: %w", argKey, argValue, err) return 0, fmt.Errorf("cannot parse %s=%s: %w", argKey, argValue, err)
} }
msecs := int64(math.Round(secs * 1e3))
if msecs < minTimeMsecs { if msecs < minTimeMsecs {
msecs = 0 msecs = 0
} }

View file

@ -2,19 +2,25 @@ package promutils
import ( import (
"fmt" "fmt"
"math"
"strconv" "strconv"
"strings" "strings"
"time" "time"
) )
// ParseTime parses time s in different formats. // ParseTimeMsec parses time s in different formats.
// //
// See https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#timestamp-formats // See https://docs.victoriametrics.com/Single-server-VictoriaMetrics.html#timestamp-formats
// //
// It returns unix timestamp in seconds. // It returns unix timestamp in milliseconds.
func ParseTime(s string) (float64, error) { func ParseTimeMsec(s string) (int64, error) {
currentTimestamp := float64(time.Now().UnixNano()) / 1e9 currentTimestamp := float64(time.Now().UnixNano()) / 1e9
return ParseTimeAt(s, currentTimestamp) secs, err := ParseTimeAt(s, currentTimestamp)
if err != nil {
return 0, err
}
msecs := int64(math.Round(secs * 1000))
return msecs, nil
} }
const ( const (

View file

@ -78,12 +78,12 @@ func TestParseTimeAtSuccess(t *testing.T) {
f("2023-05-20T04:57:43.123456789-02:30", now, 1.6845676631234567e+09) f("2023-05-20T04:57:43.123456789-02:30", now, 1.6845676631234567e+09)
} }
func TestParseTimeFailure(t *testing.T) { func TestParseTimeMsecFailure(t *testing.T) {
f := func(s string) { f := func(s string) {
t.Helper() t.Helper()
ts, err := ParseTime(s) msec, err := ParseTimeMsec(s)
if ts != 0 { if msec != 0 {
t.Fatalf("unexpected time parsed: %f; want 0", ts) t.Fatalf("unexpected time parsed: %d; want 0", msec)
} }
if err == nil { if err == nil {
t.Fatalf("expecting non-nil error") t.Fatalf("expecting non-nil error")