From 24a1a8b96f133ff84ede87e13f4ffd7c7b316606 Mon Sep 17 00:00:00 2001 From: Kevin Chabowski Date: Wed, 28 Aug 2013 00:49:03 +0200 Subject: Chronos infos can now be stringified and parsed. --- chronos/chronos.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ chronos/chronos_test.go | 40 ++++++++++++++++++------------- 2 files changed, 88 insertions(+), 16 deletions(-) diff --git a/chronos/chronos.go b/chronos/chronos.go index e66fc76..1d2c943 100644 --- a/chronos/chronos.go +++ b/chronos/chronos.go @@ -1,12 +1,18 @@ package chronos import ( + "errors" + "fmt" "math" + "strconv" + "strings" "time" ) type TimeUnit int +const timefmt = "2006-01-02 15:04:05" + const ( Minute TimeUnit = iota Hour @@ -18,6 +24,15 @@ const ( var nilTime time.Time +var tuLookup = map[string]TimeUnit{ + "Minute": Minute, + "Hour": Hour, + "Day": Day, + "Week": Week, + "Month": Month, + "Year": Year, +} + func (tu TimeUnit) String() string { switch tu { case Minute: @@ -98,6 +113,10 @@ type Frequency struct { Count uint } +func (f Frequency) String() string { + return fmt.Sprintf("%d %s", f.Count, f.Unit) +} + func (f Frequency) addTo(t time.Time, mul uint) time.Time { sec := t.Second() min := t.Minute() @@ -163,3 +182,48 @@ func (c Chronos) NextAfter(t time.Time) time.Time { return nilTime // Should actually never happen... } + +func (c Chronos) String() string { + s := c.Start.UTC().Format(timefmt) + if c.Freq.Count > 0 { + s += " +" + c.Freq.String() + if !c.End.IsZero() { + s += " !" + c.End.UTC().Format(timefmt) + } + } + return s +} + +func ParseChronos(s string) (c Chronos, err error) { + elems := strings.Split(s, " ") + + switch len(elems) { + case 6: // Everything specified + _end := elems[4] + " " + elems[5] + if c.End, err = time.ParseInLocation(timefmt, _end[1:], time.UTC); err != nil { + return + } + fallthrough + case 4: // start time and frequency + var count uint64 + if count, err = strconv.ParseUint(elems[2][1:], 10, 32); err != nil { + return + } + c.Freq.Count = uint(count) + + var ok bool + if c.Freq.Unit, ok = tuLookup[elems[3]]; !ok { + err = fmt.Errorf("Unknown timeunit %s", elems[3]) + return + } + fallthrough + case 2: // Only start time + if c.Start, err = time.ParseInLocation(timefmt, elems[0]+" "+elems[1], time.UTC); err != nil { + return + } + default: + err = errors.New("Unknown chronos format") + } + + return +} diff --git a/chronos/chronos_test.go b/chronos/chronos_test.go index 692af14..1798b4c 100644 --- a/chronos/chronos_test.go +++ b/chronos/chronos_test.go @@ -6,32 +6,40 @@ import ( ) func mktime(y int, month time.Month, d, h, min int) time.Time { - return time.Date(y, month, d, h, min, 0, 0, time.Local) + return time.Date(y, month, d, h, min, 0, 0, time.UTC) } func TestChronos(t *testing.T) { tbl := []struct { - start time.Time - end time.Time - unit TimeUnit - count uint - now time.Time - want time.Time + chronos string + now time.Time + want time.Time }{ - {mktime(1991, 4, 30, 0, 0), nilTime, Year, 1, mktime(2013, 8, 26, 13, 37), mktime(2014, 4, 30, 0, 0)}, - {mktime(2013, 1, 1, 0, 0), nilTime, Year, 0, mktime(2013, 8, 26, 13, 37), nilTime}, - {mktime(2013, 1, 1, 0, 0), nilTime, Year, 0, mktime(2012, 1, 1, 0, 0), mktime(2013, 1, 1, 0, 0)}, - {mktime(1900, 12, 24, 12, 34), nilTime, Year, 5, mktime(2013, 8, 26, 13, 37), mktime(2015, 12, 24, 12, 34)}, - {mktime(1900, 12, 24, 12, 34), mktime(2010, 1, 1, 1, 1), Year, 5, mktime(2013, 8, 26, 13, 37), nilTime}, - {mktime(2013, 8, 1, 4, 2), nilTime, Week, 3, mktime(2013, 8, 26, 13, 37), mktime(2013, 9, 12, 4, 2)}, - {mktime(2013, 8, 26, 13, 37), nilTime, Year, 0, mktime(2013, 8, 26, 13, 37), mktime(2013, 8, 26, 13, 37)}, - {mktime(2013, 8, 25, 13, 37), nilTime, Day, 1, mktime(2013, 8, 26, 13, 37), mktime(2013, 8, 26, 13, 37)}, + {"1991-04-30 00:00:00 +1 Year", mktime(2013, 8, 26, 13, 37), mktime(2014, 4, 30, 0, 0)}, + {"2013-01-01 00:00:00", mktime(2013, 8, 26, 13, 37), nilTime}, + {"2013-01-01 00:00:00", mktime(2012, 1, 1, 0, 0), mktime(2013, 1, 1, 0, 0)}, + {"1900-12-24 12:34:00 +5 Year", mktime(2013, 8, 26, 13, 37), mktime(2015, 12, 24, 12, 34)}, + {"1900-12-24 12:34:00 +5 Year !2010-01-01 01:01:00", mktime(2013, 8, 26, 13, 37), nilTime}, + {"2013-08-01 04:02:00 +3 Week", mktime(2013, 8, 26, 13, 37), mktime(2013, 9, 12, 4, 2)}, + {"2013-08-26 13:37:00", mktime(2013, 8, 26, 13, 37), mktime(2013, 8, 26, 13, 37)}, + {"2013-08-25 13:37:00 +1 Day", mktime(2013, 8, 26, 13, 37), mktime(2013, 8, 26, 13, 37)}, + {"2012-12-31 23:59:00 +100 Minute", mktime(2013, 1, 1, 0, 0), mktime(2013, 1, 1, 1, 39)}, } for i, e := range tbl { - have := Chronos{e.start, e.end, Frequency{e.unit, e.count}}.NextAfter(e.now) + c, err := ParseChronos(e.chronos) + if err != nil { + t.Errorf("#%d: Failed parsing \"%s\": %s", i, e.chronos, err) + continue + } + have := c.NextAfter(e.now) if !have.Equal(e.want) { t.Errorf("#%d: Want: %s, Have: %s", i, e.want, have) } + + if s := c.String(); s != e.chronos { + t.Errorf("#%d: String() failed: \"%s\" != \"%s\"", i, e.chronos, s) + } + } } -- cgit v1.2.3-54-g00ecf