From b68ef475ee551c8efae41d4b901fd9648f9b8570 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Tue, 7 May 2024 14:40:28 +0300 Subject: feat(tools/when): support more timestamps with better merging logic Adds a FieldSet type which defines which parts of a timestamp to merge into another in a new `mergeTime` function. With this two timestamps can be merged granularly, enabling more queries like `Sep 03 18:00` to return useful results (e.g., in this case, in the current year and location). Change-Id: I8db161608c5f68c8f9c61de8c6fa46067eced39b Reviewed-on: https://cl.tvl.fyi/c/depot/+/11601 Autosubmit: tazjin Reviewed-by: tazjin Tested-by: BuildkiteCI --- tools/when/when.go | 87 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 15 deletions(-) (limited to 'tools/when/when.go') diff --git a/tools/when/when.go b/tools/when/when.go index 316f021913ab..a2ac494e8c64 100644 --- a/tools/when/when.go +++ b/tools/when/when.go @@ -20,6 +20,8 @@ Some valid queries: tomorrow 5PM -22h -7h10m + Mar 15 + Sep 3 18:00 For now a single timestamp and a single duration (which is added either to the current time, or the given time) is supported.` @@ -30,17 +32,53 @@ func printTime(t time.Time) { fmt.Println("UNIX: ", t.Unix()) } -func setTime(this time.Time, that time.Time) time.Time { - return time.Date( - this.Year(), - this.Month(), - this.Day(), - that.Hour(), - that.Minute(), - that.Second(), - 0, - this.Location(), - ) +type FieldSet uint8 + +const ( + SetYear FieldSet = 1 << iota + SetDay + SetMonth + SetHour + SetMinute + SetSecond + SetLocation +) + +const ( + SetDate = SetYear | SetDay | SetMonth + SetClock = SetHour | SetMinute | SetSecond +) + +// mergeTimes returns a new time.Time with all fields in this overridden with the +// specified fields from that. +func mergeTimes(this time.Time, that time.Time, set FieldSet) time.Time { + year, month, day := this.Date() + hour, min, sec := this.Clock() + loc := this.Location() + + if set&SetYear == SetYear { + year = that.Year() + } + if set&SetMonth == SetMonth { + month = that.Month() + } + if set&SetDay == SetDay { + day = that.Day() + } + if set&SetHour == SetHour { + hour = that.Hour() + } + if set&SetMinute == SetMinute { + min = that.Minute() + } + if set&SetSecond == SetSecond { + sec = that.Second() + } + if set&SetLocation == SetLocation { + loc = that.Location() + } + + return time.Date(year, month, day, hour, min, sec, 0, loc) } func parseTime(input string) (time.Time, error) { @@ -61,22 +99,41 @@ func parseTime(input string) (time.Time, error) { if t, err := time.Parse(time.Kitchen, input); err == nil { now := time.Now() - return setTime(now, t), nil + return mergeTimes(now, t, SetClock), nil } if t, err := time.Parse(time.TimeOnly, input); err == nil { now := time.Now() - return setTime(now, t), nil + return mergeTimes(now, t, SetClock), nil } if t, err := time.Parse("15:04", input); err == nil { now := time.Now() - return setTime(now, t), nil + return mergeTimes(now, t, SetClock), nil } if t, err := time.Parse("3PM", input); err == nil { now := time.Now() - return setTime(now, t), nil + return mergeTimes(now, t, SetClock), nil + } + + if t, err := time.Parse(time.DateTime, input); err == nil { + return t, nil + } + + if t, err := time.Parse(time.Stamp, input); err == nil { + now := time.Now() + return mergeTimes(t, now, SetYear|SetLocation), nil + } + + if t, err := time.Parse("Jan _2 15:04", input); err == nil { + now := time.Now() + return mergeTimes(t, now, SetYear|SetLocation), nil + } + + if t, err := time.Parse("Jan _2", input); err == nil { + now := time.Now() + return mergeTimes(t, now, SetYear|SetLocation), nil } return time.Time{}, fmt.Errorf("could not parse time: %q", input) -- cgit 1.4.1