Skip to content

Commit

Permalink
Merge pull request #17 from Code-Hex/add/period-contains
Browse files Browse the repository at this point in the history
added period contains
  • Loading branch information
Code-Hex authored Oct 1, 2023
2 parents 5134e07 + ca9b094 commit 6e3a393
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 8 deletions.
13 changes: 13 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,3 +500,16 @@ func ExamplePeriod_periodicalSlice() {
// 2009-01-01 02:00:00 +0000 UTC
// 2009-01-01 03:00:00 +0000 UTC
}

func ExamplePeriod_Contains() {
p, _ := synchro.NewPeriod[tz.UTC](
"2008-12-28",
"2009-01-03",
)
t := synchro.New[tz.UTC](2009, 1, 3, 0, 0, 0, 0)

// p.Contains(t) >= 0 is the same as 2008-12-28 <= t && t <= 2009-01-03
fmt.Println("p.Contains(t) >= 0:", p.Contains(t) >= 0)
// Output:
// p.Contains(t) >= 0: true
}
36 changes: 29 additions & 7 deletions period.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ var stringType = reflect.TypeOf("")
// Period allows iteration over a set of dates and times,
// recurring at regular intervals, over a given period.
type Period[T TimeZone] struct {
start Time[T]
end Time[T]
from Time[T]
to Time[T]
}

var _ interface {
Expand All @@ -29,9 +29,15 @@ var _ interface {

// String implements the fmt.Stringer interface.
func (p Period[T]) String() string {
return fmt.Sprintf("from %s to %s", p.start, p.end)
return fmt.Sprintf("from %s to %s", p.from, p.to)
}

// From returns end of period.
func (p Period[T]) From() Time[T] { return p.from }

// To returns start of period.
func (p Period[T]) To() Time[T] { return p.to }

// NewPeriod creates a new Period struct between the 'from' and 'to' values you specified.
//
// If Time[T] or time.Time is specified, it guarantees no error returns.
Expand All @@ -47,11 +53,27 @@ func NewPeriod[T TimeZone, T1 timeish[T], T2 timeish[T]](from T1, to T2) (Period
return Period[T]{}, fmt.Errorf("failed to parse to: %w", err)
}
return Period[T]{
start: start,
end: end,
from: start,
to: end,
}, nil
}

// Contains checks whether the specified t is included within from and to.
//
// if p.from < t && t < p.to, it returns +1; if p.from == t || t == p.to, it returns 0.
// Otherwise returns -1;
func (p Period[T]) Contains(t Time[T]) int {
cmpFrom := p.from.Compare(t)
cmpTo := p.to.Compare(t)
if cmpFrom == -1 && cmpTo == 1 {
return 1
}
if cmpFrom == 0 || cmpTo == 0 {
return 0
}
return -1
}

type periodical[T TimeZone] <-chan Time[T]

// Slice returns the slice of Time[T].
Expand All @@ -74,13 +96,13 @@ func (p periodical[T]) Slice() (s []Time[T]) {
func (p Period[T]) Periodic(next func(Time[T]) Time[T]) periodical[T] {
compare := isNotAfter[T]
// p.start > p.end
if p.start.After(p.end) {
if p.from.After(p.to) {
compare = isNotBefore[T]
}
ch := make(chan Time[T], 1)
go func() {
defer close(ch)
for current := p.start; compare(current, p.end); current = next(current) {
for current := p.from; compare(current, p.to); current = next(current) {
ch <- current
}
}()
Expand Down
90 changes: 90 additions & 0 deletions period_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,3 +288,93 @@ func TestConvertTime_Panic(t *testing.T) {
}()
convertTime[tz.UTC](true)
}

func TestPeriod_Contains(t *testing.T) {
cases := []struct {
name string
t Time[tz.UTC]
from string
to string
want int
}{
{
name: "2018-08-16 is included between 2018-08-15 and 2018-08-17",
t: New[tz.UTC](2018, 8, 16, 0, 0, 0, 0),
from: "2018-08-15",
to: "2018-08-17",
want: 1,
},
{
name: "2018-12-30 is included between 2018-12-28 and 2019-01-01",
t: New[tz.UTC](2018, 12, 30, 0, 0, 0, 0),
from: "2018-12-28",
to: "2019-01-01",
want: 1,
},
{
name: "2018-08-15 is the same as from",
t: New[tz.UTC](2018, 8, 15, 0, 0, 0, 0),
from: "2018-08-15",
to: "2018-08-17",
want: 0,
},
{
name: "2018-08-17 is the same as from",
t: New[tz.UTC](2018, 8, 17, 0, 0, 0, 0),
from: "2018-08-15",
to: "2018-08-17",
want: 0,
},
{
name: "2018-08-18 is not included between 2018-08-15 and 2018-08-17",
t: New[tz.UTC](2018, 8, 18, 0, 0, 0, 0),
from: "2018-08-15",
to: "2018-08-17",
want: -1,
},
{
name: "2018-08-14 is not included between 2018-08-15 and 2018-08-17",
t: New[tz.UTC](2018, 8, 14, 0, 0, 0, 0),
from: "2018-08-15",
to: "2018-08-17",
want: -1,
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
period, err := NewPeriod[tz.UTC](tc.from, tc.to)
if err != nil {
t.Fatal(err)
}
got := period.Contains(tc.t)
if diff := cmp.Diff(tc.want, got); diff != "" {
t.Fatalf("(-want, +got)\n%s", diff)
}
})
}
}

func TestPeriod_From(t *testing.T) {
want := New[tz.UTC](2018, 8, 14, 0, 0, 0, 0)
period, err := NewPeriod[tz.UTC]("2018-08-14", "2018-08-16")
if err != nil {
t.Fatal(err)
}
got := period.From()
if diff := cmp.Diff(want, got); diff != "" {
t.Fatalf("(-want, +got)\n%s", diff)
}
}

func TestPeriod_To(t *testing.T) {
want := New[tz.UTC](2018, 8, 16, 0, 0, 0, 0)
period, err := NewPeriod[tz.UTC]("2018-08-14", "2018-08-16")
if err != nil {
t.Fatal(err)
}
got := period.To()
if diff := cmp.Diff(want, got); diff != "" {
t.Fatalf("(-want, +got)\n%s", diff)
}
}
3 changes: 2 additions & 1 deletion time.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ func (t Time[T]) IsLeapYear() bool {

// IsBetween returns true if from < t && t < to.
func (t Time[T]) IsBetween(from Time[T], to Time[T]) bool {
return from.Before(t) && to.After(t)
p, _ := NewPeriod[T](from, to)
return p.Contains(t) == 1
}

// DiffInCalendarDays calculates the difference in calendar days between t and u. (t-u)
Expand Down

0 comments on commit 6e3a393

Please sign in to comment.