This is an automated email from the ASF dual-hosted git repository. wusheng pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/skywalking-cli.git
commit b31dc3d60fcdd49394bb278d1dddd1a6582579ce Author: kezhenxu94 <kezhenx...@163.com> AuthorDate: Sat Nov 9 20:02:42 2019 +0800 Redesign start end time when absent and present --- commands/interceptor/duration.go | 97 +++++++++++++++++++++-------------- commands/interceptor/duration_test.go | 64 ++++++++++++++++++++--- 2 files changed, 116 insertions(+), 45 deletions(-) diff --git a/commands/interceptor/duration.go b/commands/interceptor/duration.go index 55c4b86..1be9974 100644 --- a/commands/interceptor/duration.go +++ b/commands/interceptor/duration.go @@ -26,32 +26,31 @@ import ( ) var stepFormats = map[schema.Step]string{ - schema.StepSecond: "2006-01-02 1504", + schema.StepSecond: "2006-01-02 150400", schema.StepMinute: "2006-01-02 1504", schema.StepHour: "2006-01-02 15", schema.StepDay: "2006-01-02", - schema.StepMonth: "2006-01-02", + schema.StepMonth: "2006-01", } -var supportedTimeLayouts = []string{ - "2006-01-02 150400", - "2006-01-02 1504", - "2006-01-02 15", - "2006-01-02", - "2006-01", +var stepDuration = map[schema.Step]time.Duration{ + schema.StepSecond: time.Second, + schema.StepMinute: time.Minute, + schema.StepHour: time.Hour, + schema.StepDay: time.Hour * 24, + schema.StepMonth: time.Hour * 24 * 30, } -func tryParseTime(unparsed string, parsed *time.Time) error { +func tryParseTime(unparsed string) (schema.Step, time.Time, error) { var possibleError error = nil - for _, layout := range supportedTimeLayouts { + for step, layout := range stepFormats { t, err := time.Parse(layout, unparsed) if err == nil { - *parsed = t - return nil + return step, t, nil } possibleError = err } - return possibleError + return schema.StepSecond, time.Time{}, possibleError } // DurationInterceptor sets the duration if absent, and formats it accordingly, @@ -80,42 +79,62 @@ func DurationInterceptor(ctx *cli.Context) error { // in the format, (e.g. 2019-11-09 1001), so they'll be considered as UTC-based, // and generate the missing `start`(`end`) based on the same timezone, UTC func ParseDuration(start string, end string) (time.Time, time.Time, schema.Step) { + logger.Log.Debugln("Start time:", start, "end time:", end) + now := time.Now().UTC() - startTime := now - endTime := now - logger.Log.Debugln("Start time:", start, "end time:", end) - if len(start) == 0 && len(end) == 0 { // both absent - startTime = now.Add(-30 * time.Minute) - endTime = now - } else if len(end) == 0 { // start is present - if err := tryParseTime(start, &startTime); err != nil { + // both are absent + if len(start) == 0 && len(end) == 0 { + return now.Add(-30 * time.Minute), now, schema.StepMinute + } + + var startTime, endTime time.Time + var step schema.Step + var err error + + // both are present + if len(start) > 0 && len(end) > 0 { + start, end = AlignPrecision(start, end) + + if step, startTime, err = tryParseTime(start); err != nil { logger.Log.Fatalln("Unsupported time format:", start, err) } - } else if len(start) == 0 { // end is present - if err := tryParseTime(end, &endTime); err != nil { + if step, endTime, err = tryParseTime(end); err != nil { logger.Log.Fatalln("Unsupported time format:", end, err) } - } else { // both are present - if err := tryParseTime(start, &startTime); err != nil { + + return startTime, endTime, step + } + + // end is absent + if len(end) == 0 { + if step, startTime, err = tryParseTime(start); err != nil { logger.Log.Fatalln("Unsupported time format:", start, err) } - if err := tryParseTime(end, &endTime); err != nil { + return startTime, startTime.Add(30 * stepDuration[step]), step + } + + // start is present + if len(start) == 0 { + if step, endTime, err = tryParseTime(end); err != nil { logger.Log.Fatalln("Unsupported time format:", end, err) } + return endTime.Add(-30 * stepDuration[step]), endTime, step } - duration := endTime.Sub(startTime) - step := schema.StepSecond - if duration.Hours() >= 24*30 { // time range > 1 month - step = schema.StepMonth - } else if duration.Hours() > 24 { // time range > 1 day - step = schema.StepDay - } else if duration.Minutes() > 60 { // time range > 1 hour - step = schema.StepHour - } else if duration.Seconds() > 60 { // time range > 1 minute - step = schema.StepMinute - } else if duration.Seconds() <= 0 { // illegal - logger.Log.Fatalln("end time must be later than start time, end time:", endTime, ", start time:", startTime) - } + + logger.Log.Fatalln("Should never happen") + return startTime, endTime, step } + +// AlignPrecision aligns the two time strings to same precision +// by truncating the more precise one +func AlignPrecision(start string, end string) (string, string) { + if len(start) < len(end) { + return start, end[0:len(start)] + } + if len(start) > len(end) { + return start[0:len(end)], end + } + return start, end +} diff --git a/commands/interceptor/duration_test.go b/commands/interceptor/duration_test.go index 7879cfd..c9b587d 100644 --- a/commands/interceptor/duration_test.go +++ b/commands/interceptor/duration_test.go @@ -44,20 +44,20 @@ func TestParseDuration(t *testing.T) { name: "Should set current time if start is absent", args: args{ start: "", - end: now.Add(10 * time.Minute).Format(timeFormat), + end: now.Format(timeFormat), }, - wantedStartTime: now, - wantedEndTime: now.Add(10 * time.Minute), + wantedStartTime: now.Add(-30 * time.Minute), + wantedEndTime: now, wantedStep: schema.StepMinute, }, { name: "Should set current time if end is absent", args: args{ - start: now.Add(-10 * time.Minute).Format(timeFormat), + start: now.Format(timeFormat), end: "", }, - wantedStartTime: now.Add(-10 * time.Minute), - wantedEndTime: now, + wantedStartTime: now, + wantedEndTime: now.Add(30 * time.Minute), wantedStep: schema.StepMinute, }, { @@ -96,3 +96,55 @@ func TestParseDuration(t *testing.T) { }) } } + +func TestAlignPrecision(t *testing.T) { + type args struct { + start string + end string + } + tests := []struct { + name string + args args + wantedStart string + wantedEnd string + }{ + { + name: "Should keep both when same precision", + args: args{ + start: "2019-01-01", + end: "2019-01-01", + }, + wantedStart: "2019-01-01", + wantedEnd: "2019-01-01", + }, + { + name: "Should truncate start when it's less precise", + args: args{ + start: "2019-01-01 1200", + end: "2019-01-01", + }, + wantedStart: "2019-01-01", + wantedEnd: "2019-01-01", + }, + { + name: "Should truncate end when it's less precise", + args: args{ + start: "2019-01-01", + end: "2019-01-01 1200", + }, + wantedStart: "2019-01-01", + wantedEnd: "2019-01-01", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotStart, gotEnd := AlignPrecision(tt.args.start, tt.args.end) + if gotStart != tt.wantedStart { + t.Errorf("AlignPrecision() gotStart = %v, wantedStart %v", gotStart, tt.wantedStart) + } + if gotEnd != tt.wantedEnd { + t.Errorf("AlignPrecision() gotEnd = %v, wantedStart %v", gotEnd, tt.wantedEnd) + } + }) + } +}