Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add unshift #5

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
Duration [![Build](https://travis-ci.org/senseyeio/duration.svg?branch=master)](https://travis-ci.org/senseyeio/duration) [![Coverage](https://coveralls.io/repos/github/senseyeio/duration/badge.svg?branch=master)](https://coveralls.io/github/senseyeio/duration?branch=master) [![Go Report Card](https://goreportcard.com/badge/senseyeio/duration)](https://goreportcard.com/report/senseyeio/duration) [![GoDoc](https://godoc.org/github.com/senseyeio/duration?status.svg)](https://godoc.org/github.com/senseyeio/duration)
=======
Parse ISO8601 duration strings, and use to shift dates/times.
# Duration [![Build](https://travis-ci.org/senseyeio/duration.svg?branch=master)](https://travis-ci.org/senseyeio/duration) [![Coverage](https://coveralls.io/repos/github/senseyeio/duration/badge.svg?branch=master)](https://coveralls.io/github/senseyeio/duration?branch=master) [![Go Report Card](https://goreportcard.com/badge/senseyeio/duration)](https://goreportcard.com/report/senseyeio/duration) [![GoDoc](https://godoc.org/github.com/senseyeio/duration?status.svg)](https://godoc.org/github.com/senseyeio/duration)

Basic Example
-------------
This is a fork of the original `duration` package with added functionality to support shifting dates/times both forward and backward.

## Basic Example

```go
package main
Expand All @@ -19,8 +18,10 @@ func main() {
d, _ := iso8601.ParseISO8601("P1D")
today := time.Now()
tomorrow := d.Shift(today)
yesterday := d.Unshift(today)
fmt.Println(today.Format("Jan _2"))
fmt.Println(tomorrow.Format("Jan _2"))
fmt.Println(yesterday.Format("Jan _2"))
}
```

Expand Down Expand Up @@ -82,3 +83,31 @@ Nov 2, 2006
Dec 2, 2006
Jan 2, 2007
```


Additional Functionality
---------------------------
This fork includes an Unshift method that complements the Shift functionality. It returns a time.Time shifted back by the duration from the given start.

```go
// UnShift returns a time.Time, shifted back by the duration from the given start.
//
// NB: UnShift uses time.AddDate for years, months, weeks, and days, and so
// shares its limitations. In particular, shifting back by months is not recommended
// unless the start date is before the 28th of the month. Otherwise, dates will
// roll over, e.g. Oct 1 - P1M = Aug 31.
//
// Week and Day values will be combined as W*7 + D.
func (d Duration) Unshift(t time.Time) time.Time {
if d.Y != 0 || d.M != 0 || d.W != 0 || d.D != 0 {
days := d.W*7 + d.D
t = t.AddDate(-d.Y, -d.M, -days)
}
t = t.Add(-d.timeDuration())
return t
}

```

This method allows for shifting dates and times backward, which can be useful in certain scenarios.

17 changes: 17 additions & 0 deletions duration.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,23 @@ func (d Duration) Shift(t time.Time) time.Time {
return t
}

// UnShift returns a time.Time, shifted back by the duration from the given start.
//
// NB: UnShift uses time.AddDate for years, months, weeks, and days, and so
// shares its limitations. In particular, shifting back by months is not recommended
// unless the start date is before the 28th of the month. Otherwise, dates will
// roll over, e.g. Oct 1 - P1M = Aug 31.
//
// Week and Day values will be combined as W*7 + D.
func (d Duration) Unshift(t time.Time) time.Time {
if d.Y != 0 || d.M != 0 || d.W != 0 || d.D != 0 {
days := d.W*7 + d.D
t = t.AddDate(-d.Y, -d.M, -days)
}
t = t.Add(-d.timeDuration())
return t
}

func (d Duration) timeDuration() time.Duration {
var dur time.Duration
dur = dur + (time.Duration(d.TH) * time.Hour)
Expand Down
37 changes: 37 additions & 0 deletions duration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,40 @@ func TestCanRejectBadJSON(t *testing.T) {
t.Fatal("expected error, got none")
}
}

func TestCanUnshift(t *testing.T) {
cases := []struct {
to string
duration duration.Duration
want string
}{
{"Jan 1, 2019 at 00:00:00", duration.Duration{Y: 1}, "Jan 1, 2018 at 00:00:00"},
{"Feb 1, 2018 at 00:00:00", duration.Duration{M: 1}, "Jan 1, 2018 at 00:00:00"},
{"Mar 1, 2018 at 00:00:00", duration.Duration{M: 2}, "Jan 1, 2018 at 00:00:00"},
{"Jan 8, 2018 at 00:00:00", duration.Duration{W: 1}, "Jan 1, 2018 at 00:00:00"},
{"Jan 2, 2018 at 00:00:00", duration.Duration{D: 1}, "Jan 1, 2018 at 00:00:00"},
{"Jan 1, 2018 at 01:00:00", duration.Duration{TH: 1}, "Jan 1, 2018 at 00:00:00"},
{"Jan 1, 2018 at 00:01:00", duration.Duration{TM: 1}, "Jan 1, 2018 at 00:00:00"},
{"Jan 1, 2018 at 00:00:01", duration.Duration{TS: 1}, "Jan 1, 2018 at 00:00:00"},
{"Jun 9, 2028 at 05:10:06", duration.Duration{
Y: 10,
M: 5,
D: 8,
TH: 5,
TM: 10,
TS: 6,
},
"Jan 1, 2018 at 00:00:00",
},
}

for k, c := range cases {
to := makeTime(t, c.to)
want := makeTime(t, c.want)

got := c.duration.Unshift(to)
if !want.Equal(got) {
t.Fatalf("Case %d: want=%s, got=%s", k, want, got)
}
}
}