Skip to content

Commit

Permalink
Support day format in human-friendly time formats
Browse files Browse the repository at this point in the history
So one does not have to calculate days as multiples of 24 hours in head
when older logs are needed.
  • Loading branch information
mathewcohle committed Mar 10, 2019
1 parent a7eb9fa commit 36a92ad
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 18 deletions.
15 changes: 8 additions & 7 deletions README.md
Expand Up @@ -24,7 +24,7 @@ Author - [Luca Grulla](https://www.lucagrulla.com) - [https://www.lucagrulla.co
* **Flexible date and time parser**.
* You can work with either `Local` timezone or `UTC` (default).
* Flexible parsing.
* Human friendly formats, i.e. `1h20m` to indicate 1 hour and 20 minutes ago.
* Human friendly formats, i.e. `2d1h20m` to indicate 2 days, 1 hour and 20 minutes ago.
* a specific hour, i.e. `13:10` to indicate 13:10 of today.
* a full timestamp `2018-10-20T8:53`.
* **multi log groups tailing** tail multiple log groups in parallel: `cw tail tail my-auth-service my-web`
Expand Down Expand Up @@ -114,12 +114,12 @@ go get github.com/lucagrulla/cw
-s, --stream-name Print the log stream name this event belongs to.
-n, --group-name Print the log log group name this event belongs to.
-b, --start="2018-12-25T09:34:45"
The UTC start time. Passed as either date/time or human-friendly format. The human-friendly format accepts the number of hours and minutes prior to the present. Denote hours with
'h' and minutes with 'm' i.e. 80m, 4h30m. If just time is used (format: hh[:mm]) it is expanded to today at the given time. Full available date/time format:
2017-02-27[T09[:00[:00]].
-e, --end="" The UTC end time. Passed as either date/time or human-friendly format. The human-friendly format accepts the number of hours and minutes prior to the present. Denote hours with
'h' and minutes with 'm' i.e. 80m, 4h30m.If just time is used (format: hh[:mm]) it is expanded to today at the given time. Full available date/time format:
2017-02-27[T09[:00[:00]].
The UTC start time. Passed as either date/time or human-friendly format. The human-friendly format accepts the number of days, hours and minutes prior to the present. Denote days with
'd', hours with 'h' and minutes with 'm' i.e. 80m, 4h30m, 2d4h. If just time is used (format: hh[:mm]) it is expanded to today at the given time. Full available date/time format:
2017-02-27[T09[:00[:00]].
-e, --end="" The UTC end time. Passed as either date/time or human-friendly format. The human-friendly format accepts the number of days, hours and minutes prior to the present. Denote days with
'd', hours with 'h' and minutes with 'm' i.e. 80m, 4h30m, 2d4h. If just time is used (format: hh[:mm]) it is expanded to today at the given time. Full available date/time format:
2017-02-27[T09[:00[:00]].
-l, --local Treat date and time in Local timezone.
-g, --grep="" Pattern to filter logs by. See http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html for syntax.
-v, --grepv="" Equivalent of grep --invert-match. Invert match pattern to filter logs by.
Expand All @@ -141,6 +141,7 @@ go get github.com/lucagrulla/cw
* `cw tail -f my-log-group:my-log-stream-prefix`
* `cw tail -f my-log-group:my-log-stream-prefix my-log-group2`
* `cw tail -f my-log-group:my-log-stream-prefix -b2017-01-01T08:10:10 -e2017-01-01T08:05:00`
* `cw tail -f my-log-group:my-log-stream-prefix -b7d` to start from 7 days ago.
* `cw tail -f my-log-group:my-log-stream-prefix -b3h` to start from 3 hours ago.
* `cw tail -f my-log-group:my-log-stream-prefix -b100m` to start from 100 minutes ago.
* `cw tail -f my-log-group:my-log-stream-prefix -b2h30m` to start from 2 hours and 30 minutes ago.
Expand Down
20 changes: 12 additions & 8 deletions main.go
Expand Up @@ -50,14 +50,14 @@ var (
printStreamName = tailCommand.Flag("stream-name", "Print the log stream name this event belongs to.").Short('s').Default("false").Bool()
printGroupName = tailCommand.Flag("group-name", "Print the log group name this event belongs to.").Short('n').Default("false").Bool()
startTime = tailCommand.Flag("start", "The UTC start time. Passed as either date/time or human-friendly format."+
" The human-friendly format accepts the number of hours and minutes prior to the present. "+
"Denote hours with 'h' and minutes with 'm' i.e. 80m, 4h30m."+
" The human-friendly format accepts the number of days, hours and minutes prior to the present. "+
"Denote days with 'd', hours with 'h' and minutes with 'm' i.e. 80m, 4h30m, 2d4h."+
" If just time is used (format: hh[:mm]) it is expanded to today at the given time."+
" Full available date/time format: 2017-02-27[T09[:00[:00]].").
Short('b').Default(time.Now().UTC().Add(-30 * time.Second).Format(timeFormat)).String()
endTime = tailCommand.Flag("end", "The UTC end time. Passed as either date/time or human-friendly format. "+
"The human-friendly format accepts the number of hours and minutes prior to the present. "+
"Denote hours with 'h' and minutes with 'm' i.e. 80m, 4h30m."+
" The human-friendly format accepts the number of days, hours and minutes prior to the present. "+
"Denote days with 'd', hours with 'h' and minutes with 'm' i.e. 80m, 4h30m, 2d4h."+
"If just time is used (format: hh[:mm]) it is expanded to today at the given time. Full available date/time format: 2017-02-27[T09[:00[:00]].").
Short('e').Default("").String()
local = tailCommand.Flag("local", "Treat date and time in Local timezone.").Short('l').Default("false").Bool()
Expand Down Expand Up @@ -93,10 +93,14 @@ func timestampToTime(timeStamp *string) (time.Time, error) {
mm, _ := strconv.Atoi(res[2])

return time.Date(y, m, d, t, mm, 0, 0, zone), nil
} else if regexp.MustCompile(`^\d{1,}h$|^\d{1,}m$|^\d{1,}h\d{1,}m$`).MatchString(*timeStamp) {
d, _ := time.ParseDuration(*timeStamp)

t := time.Now().In(zone).Add(-d)
} else if res := regexp.MustCompile(
`^(?:(?P<Day>\d{1,})(?:d))?(?P<HourMinute>(?:\d{1,}h)?(?:\d{1,}m)?)?$`).FindStringSubmatch(
*timeStamp); res != nil {
// Unfortunately, ParseDuration does not support day time unit
days, _ := strconv.Atoi(res[1])
d, _ := time.ParseDuration(res[2])

t := time.Now().In(zone).AddDate(0, 0, -days).Add(-d)
y, m, dd := t.Date()
return time.Date(y, m, dd, t.Hour(), t.Minute(), 0, 0, zone), nil
}
Expand Down
25 changes: 22 additions & 3 deletions main_test.go
Expand Up @@ -54,13 +54,32 @@ func TestTimestampToTime(t *testing.T) {
func TestHumanReadableTimeToTime(t *testing.T) {
assert := assert.New(t)

s := "32h"
dd, _ := time.ParseDuration(s)
x := time.Now().UTC().Add(-dd)
s := "2d"
x := time.Now().UTC().AddDate(0, 0, -2)

y, m, d := x.Date()

parsedTime, _ := timestampToTime(&s)
assert.Equal(time.Date(y, m, d, x.Hour(), x.Minute(), 0, 0, time.UTC),
parsedTime, "wrong parsing for input %s", s)

s = "03d50m"
dd, _ := time.ParseDuration(`50m`)
x = time.Now().UTC().AddDate(0, 0, -3).Add(-dd)

y, m, d = x.Date()

parsedTime, _ = timestampToTime(&s)
assert.Equal(time.Date(y, m, d, x.Hour(), x.Minute(), 0, 0, time.UTC),
parsedTime, "wrong parsing for input %s", s)

s = "32h"
dd, _ = time.ParseDuration(s)
x = time.Now().UTC().Add(-dd)

y, m, d = x.Date()

parsedTime, _ = timestampToTime(&s)
assert.Equal(time.Date(y, m, d, x.Hour(), x.Minute(), 0, 0, time.UTC), parsedTime, "wrong parsing for input %s", s)

s = "50m"
Expand Down

0 comments on commit 36a92ad

Please sign in to comment.