-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
195 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
// Package dateutil provides interval handling and a custom flag. | ||
package dateutil | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/araddon/dateparse" | ||
"github.com/jinzhu/now" | ||
) | ||
|
||
var ( | ||
// EveryMinute will chop up a timespan into 60s intervals; | ||
// https://english.stackexchange.com/questions/3091/weekly-daily-hourly-minutely. | ||
EveryMinute = makeIntervalFunc(padLMinute, padRMinute) | ||
Hourly = makeIntervalFunc(padLHour, padRHour) | ||
Daily = makeIntervalFunc(padLDay, padRDay) | ||
Weekly = makeIntervalFunc(padLWeek, padRWeek) | ||
Monthly = makeIntervalFunc(padLMonth, padRMonth) | ||
|
||
padLMinute = func(t time.Time) time.Time { return now.With(t).BeginningOfMinute() } | ||
padRMinute = func(t time.Time) time.Time { return now.With(t).EndOfMinute() } | ||
padLHour = func(t time.Time) time.Time { return now.With(t).BeginningOfHour() } | ||
padRHour = func(t time.Time) time.Time { return now.With(t).EndOfHour() } | ||
padLDay = func(t time.Time) time.Time { return now.With(t).BeginningOfDay() } | ||
padRDay = func(t time.Time) time.Time { return now.With(t).EndOfDay() } | ||
padLWeek = func(t time.Time) time.Time { return now.With(t).BeginningOfWeek() } | ||
padRWeek = func(t time.Time) time.Time { return now.With(t).EndOfWeek() } | ||
padLMonth = func(t time.Time) time.Time { return now.With(t).BeginningOfMonth() } | ||
padRMonth = func(t time.Time) time.Time { return now.With(t).EndOfMonth() } | ||
) | ||
|
||
// Interval groups start and end. | ||
type Interval struct { | ||
Start time.Time | ||
End time.Time | ||
} | ||
|
||
type ( | ||
// padFunc allows to move a given time back and forth. | ||
padFunc func(t time.Time) time.Time | ||
// intervalFunc takes a start and endtime and returns a number of | ||
// intervals. How intervals are generated is flexible. | ||
intervalFunc func(s, e time.Time) []Interval | ||
) | ||
|
||
// makeIntervalFunc is a helper to create daily, weekly and other intervals. | ||
// Given two shiftFuncs (to mark the beginning of an interval and the end), we | ||
// return a function, that will allow us to generate intervals. | ||
// TODO: We only need right pad, no? | ||
func makeIntervalFunc(padLeft, padRight padFunc) intervalFunc { | ||
return func(s, e time.Time) (result []Interval) { | ||
if e.Before(s) || e.Equal(s) { | ||
return | ||
} | ||
e = e.Add(-1 * time.Second) | ||
var ( | ||
l time.Time = s | ||
r time.Time | ||
) | ||
for { | ||
r = padRight(l) | ||
result = append(result, Interval{l, r}) | ||
l = padLeft(r.Add(1 * time.Second)) | ||
if l.After(e) { | ||
break | ||
} | ||
} | ||
return result | ||
} | ||
} | ||
|
||
// MustParse will panic on an unparsable date string. | ||
func MustParse(value string) time.Time { | ||
t, err := dateparse.ParseStrict(value) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return t | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package dateutil | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestMakeIntervalFunc(t *testing.T) { | ||
var cases = []struct { | ||
padLeft padFunc | ||
padRight padFunc | ||
start time.Time | ||
end time.Time | ||
numIntervals int | ||
}{ | ||
{ | ||
padLeft: padLDay, | ||
padRight: padRDay, | ||
start: MustParse("2000-01-01"), | ||
end: MustParse("2000-01-01"), | ||
numIntervals: 0, | ||
}, | ||
{ | ||
padLeft: padLDay, | ||
padRight: padRDay, | ||
start: MustParse("2000-01-01"), | ||
end: MustParse("1999-01-01"), | ||
numIntervals: 0, | ||
}, | ||
{ | ||
padLeft: padLDay, | ||
padRight: padRDay, | ||
start: MustParse("2000-01-01"), | ||
end: MustParse("2001-01-01"), | ||
numIntervals: 366, | ||
}, | ||
{ | ||
padLeft: padLHour, | ||
padRight: padRHour, | ||
start: MustParse("2000-01-01 10:00"), | ||
end: MustParse("2000-01-01 12:00"), | ||
numIntervals: 2, | ||
}, | ||
{ | ||
padLeft: padLHour, | ||
padRight: padRHour, | ||
start: MustParse("2000-01-01 10:30"), | ||
end: MustParse("2000-01-01 12:00"), | ||
numIntervals: 2, | ||
}, | ||
{ | ||
padLeft: padLMonth, | ||
padRight: padRMonth, | ||
start: MustParse("2000-01-01 10:30"), | ||
end: MustParse("2000-01-01 12:00"), | ||
numIntervals: 1, | ||
}, | ||
} | ||
for i, c := range cases { | ||
f := makeIntervalFunc(c.padLeft, c.padRight) | ||
ivs := f(c.start, c.end) | ||
t.Logf("[%d] start: %v, end: %v", i, c.start, c.end) | ||
switch len(ivs) { | ||
case 0: | ||
case 1: | ||
t.Logf("[%d] [%v]", i, ivs[0]) | ||
case 2: | ||
t.Logf("[%d] [%v, %v]", i, ivs[0], ivs[1]) | ||
default: | ||
t.Logf("[%d] [%v, ..., %v]", i, ivs[0], ivs[len(ivs)-1]) | ||
} | ||
if len(ivs) != c.numIntervals { | ||
t.Fatalf("[%d] got %d, want %d", i, len(ivs), c.numIntervals) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package xflag | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/araddon/dateparse" | ||
) | ||
|
||
// Date can be used to parse command line args into dates. | ||
type Date struct { | ||
time.Time | ||
} | ||
|
||
// String returns a formatted date. | ||
func (d *Date) String() string { | ||
return d.Format("2006-01-02") | ||
} | ||
|
||
// Set parses a value into a date, relatively flexible due to | ||
// araddon/dateparse, 2014-04-26 will work, but oct. 7, 1970, too. | ||
func (d *Date) Set(value string) error { | ||
t, err := dateparse.ParseStrict(value) | ||
if err != nil { | ||
return err | ||
} | ||
*d = Date{t} | ||
return nil | ||
} |