intervalset

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 17, 2023 License: MIT Imports: 4 Imported by: 0

README

IntervalSet Go Reference

intervalset is a Go package that provides operations on set of intervals. It supports two types of intervals:

  • Range: a range is an interval of numbers, either floats or integers;
  • Period: a period is an interval of Time.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Interval

type Interval[T any] interface {
	// Min returns the minimum value of the interval.
	Min() T

	// Max returns the maximum value of the interval.
	Max() T

	// Equal reports whether two intervals are equal.
	Equal(Interval[T]) bool

	// Before reports whether the interval is before the given interval.
	Before(Interval[T]) bool

	// After reports whether the interval is after the given interval.
	After(Interval[T]) bool

	// Contains reports whether the interval contains the given interval.
	Contains(Interval[T]) bool

	// Overlaps reports whether the interval overlaps the given interval.
	Overlaps(Interval[T]) bool

	// Intersect returns a new interval representing the intersection of both intervals.
	Intersect(Interval[T]) Interval[T]

	// Encompass returns a new interval encompassing two overlapping intervals.
	Encompass(Interval[T]) Interval[T]

	// Punch cuts the given interval out of the interval and returns the remaining intervals.
	Punch(Interval[T]) (Interval[T], Interval[T])

	// IsZero reports whether both limits are zero values
	IsZero() bool
}

Interval is an interface that represents an interval within the set.

type IntervalSet

type IntervalSet[T any] struct {
	// contains filtered or unexported fields
}

IntervalSet is an ordered set of intervals.

func EmptySet

func EmptySet[T any]() *IntervalSet[T]

EmptySet returns an empty set.

func Intersection

func Intersection[T any](sets ...*IntervalSet[T]) *IntervalSet[T]

Intersection returns a new set that is the intersection of the sets.

Example (Period)
a := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 4, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 7, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 8, 0, 0, 0, 0, time.UTC),
		),
	)

b := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 6, 0, 0, 0, 0, time.UTC),
		),
	)

// ab = a ∩ b
ab := Intersection(a, b)

for _, p := range ab.AsSlice() {
	fmt.Printf("%s - %s\n", p.Min(), p.Max())
}
Output:

2023-12-01 00:00:00 +0000 UTC - 2023-12-02 00:00:00 +0000 UTC
2023-12-04 00:00:00 +0000 UTC - 2023-12-05 00:00:00 +0000 UTC
Example (Range)
a := EmptySet[int]().
	Add(
		NewRange[int](1, 2),
		NewRange[int](4, 5),
		NewRange[int](7, 8),
	)

b := EmptySet[int]().
	Add(
		NewRange[int](1, 6),
	)

// ab = a ∩ b
ab := Intersection(a, b)

for _, p := range ab.AsSlice() {
	fmt.Printf("%d - %d\n", p.Min(), p.Max())
}
Output:

1 - 2
4 - 5

func Union

func Union[T any](sets ...*IntervalSet[T]) *IntervalSet[T]

Union returns a new set that is the union of the sets.

Example (Period)
a := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 4, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
		),
	)

b := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 3, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 6, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 7, 0, 0, 0, 0, time.UTC),
		),
	)

// ab = a ∪ b
ab := Union(a, b)

for _, p := range ab.AsSlice() {
	fmt.Printf("%s - %s\n", p.Min(), p.Max())
}
Output:

2023-12-01 00:00:00 +0000 UTC - 2023-12-03 00:00:00 +0000 UTC
2023-12-04 00:00:00 +0000 UTC - 2023-12-05 00:00:00 +0000 UTC
2023-12-06 00:00:00 +0000 UTC - 2023-12-07 00:00:00 +0000 UTC
Example (Range)
a := EmptySet[int]().
	Add(
		NewRange[int](1, 2),
		NewRange[int](4, 5),
	)

b := EmptySet[int]().
	Add(
		NewRange[int](2, 3),
		NewRange[int](6, 7),
	)

// ab = a ∪ b
ab := Union(a, b)

for _, p := range ab.AsSlice() {
	fmt.Printf("%d - %d\n", p.Min(), p.Max())
}
Output:

1 - 3
4 - 5
6 - 7

func (*IntervalSet[T]) Add

func (p *IntervalSet[T]) Add(intervals ...Interval[T]) *IntervalSet[T]

Add adds the given interval to the set. Intervals will be merged with the intervals present in the set.

Example (Period)
s := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 6, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 9, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 10, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 3, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 6, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 7, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 8, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 9, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
		),
	)

for _, p := range s.AsSlice() {
	fmt.Printf("%s - %s\n", p.Min(), p.Max())
}
Output:

2023-12-01 00:00:00 +0000 UTC - 2023-12-03 00:00:00 +0000 UTC
2023-12-05 00:00:00 +0000 UTC - 2023-12-07 00:00:00 +0000 UTC
2023-12-08 00:00:00 +0000 UTC - 2023-12-10 00:00:00 +0000 UTC
Example (Range)
s := EmptySet[int]().
	Add(
		NewRange[int](5, 6),
		NewRange[int](9, 10),
		NewRange[int](2, 3),
		NewRange[int](6, 7),
		NewRange[int](8, 9),
		NewRange[int](1, 2),
	)

for _, p := range s.AsSlice() {
	fmt.Printf("%d - %d\n", p.Min(), p.Max())
}
Output:

1 - 3
5 - 7
8 - 10

func (*IntervalSet[T]) AsSlice

func (p *IntervalSet[T]) AsSlice() []Interval[T]

AsSlice returns the underlying set of intervals as a slice.

func (*IntervalSet[T]) Complement

func (p *IntervalSet[T]) Complement(q Interval[T]) *IntervalSet[T]

Complement returns a new set containing the intervals in q that are not in p.

Example (Period)
s := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 4, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 7, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 8, 0, 0, 0, 0, time.UTC),
		),
	)

c := s.Complement(
	NewPeriod(
		time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
		time.Date(2023, time.December, 10, 0, 0, 0, 0, time.UTC),
	),
)

for _, p := range c.AsSlice() {
	fmt.Printf("%s - %s\n", p.Min(), p.Max())
}
Output:

2023-12-02 00:00:00 +0000 UTC - 2023-12-04 00:00:00 +0000 UTC
2023-12-05 00:00:00 +0000 UTC - 2023-12-07 00:00:00 +0000 UTC
2023-12-08 00:00:00 +0000 UTC - 2023-12-10 00:00:00 +0000 UTC
Example (Range)
s := EmptySet[int]().
	Add(
		NewRange[int](1, 2),
		NewRange[int](4, 5),
		NewRange[int](7, 8),
	)

c := s.Complement(NewRange[int](1, 10))

for _, p := range c.AsSlice() {
	fmt.Printf("%d - %d\n", p.Min(), p.Max())
}
Output:

2 - 4
5 - 7
8 - 10

func (*IntervalSet[T]) Difference

func (p *IntervalSet[T]) Difference(q *IntervalSet[T]) *IntervalSet[T]

Difference returns a new set containing the intervals in p that are not in q.

Example (Period)
a := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 4, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 7, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 8, 0, 0, 0, 0, time.UTC),
		),
	)

b := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 6, 0, 0, 0, 0, time.UTC),
		),
	)

// ab = a – b
ab := a.Difference(b)

for _, p := range ab.AsSlice() {
	fmt.Printf("%s - %s\n", p.Min(), p.Max())
}
Output:

2023-12-07 00:00:00 +0000 UTC - 2023-12-08 00:00:00 +0000 UTC
Example (Range)
a := EmptySet[int]().
	Add(
		NewRange[int](1, 2),
		NewRange[int](4, 5),
		NewRange[int](7, 8),
	)

b := EmptySet[int]().
	Add(
		NewRange[int](1, 6),
	)

// ab = a – b
ab := a.Difference(b)

for _, p := range ab.AsSlice() {
	fmt.Printf("%d - %d\n", p.Min(), p.Max())
}
Output:

7 - 8

func (*IntervalSet[T]) Equal

func (p *IntervalSet[T]) Equal(q *IntervalSet[T]) bool

Equal reports whether the set is equal to another set.

func (*IntervalSet[T]) IsEmpty

func (p *IntervalSet[T]) IsEmpty() bool

IsEmpty reports whether the set is empty.

func (*IntervalSet[T]) IsSubset

func (p *IntervalSet[T]) IsSubset(s *IntervalSet[T]) bool

IsSubset reports whether s is a subset of p.

func (*IntervalSet[T]) Iter added in v0.2.0

func (p *IntervalSet[T]) Iter(f func(Interval[T]) bool)

Iter iterates over the set and pass intervals to the anonymous function. It stops when the function returns false or when there are no more intervals to consume.

func (*IntervalSet[T]) IterBetween added in v0.2.0

func (p *IntervalSet[T]) IterBetween(q Interval[T], f func(Interval[T]) bool)

IterBetween iterates over the set between the given interval. Each interval is truncated to fit within q and pass intervals to the anonymous function. It stops when the function returns false or when there are no more intervals to consume.

func (*IntervalSet[T]) Overlaps

func (p *IntervalSet[T]) Overlaps(q Interval[T]) *IntervalSet[T]

Overlaps returns a new set containing the intervals overlapping q.

Example (Period)
s := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 4, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 6, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 8, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 10, 0, 0, 0, 0, time.UTC),
		),
	)

o := s.Overlaps(
	NewPeriod(
		time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
		time.Date(2023, time.December, 9, 0, 0, 0, 0, time.UTC),
	),
)

for _, p := range o.AsSlice() {
	fmt.Printf("%s - %s\n", p.Min(), p.Max())
}
Output:

2023-12-05 00:00:00 +0000 UTC - 2023-12-06 00:00:00 +0000 UTC
2023-12-08 00:00:00 +0000 UTC - 2023-12-09 00:00:00 +0000 UTC
Example (Range)
s := EmptySet[int]().
	Add(
		NewRange[int](4, 6),
		NewRange[int](8, 10),
	)

o := s.Overlaps(NewRange[int](5, 9))

for _, p := range o.AsSlice() {
	fmt.Printf("%d - %d\n", p.Min(), p.Max())
}
Output:

5 - 6
8 - 9

func (*IntervalSet[T]) Sub

func (p *IntervalSet[T]) Sub(intervals ...Interval[T]) *IntervalSet[T]

Sub subtracts the given intervals from the set.

Example (Period)
s := EmptySet[time.Time]().
	Add(
		NewPeriod(
			time.Date(2023, time.December, 1, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 10, 0, 0, 0, 0, time.UTC),
		),
	).
	Sub(
		NewPeriod(
			time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 4, 0, 0, 0, 0, time.UTC),
		),
		NewPeriod(
			time.Date(2023, time.December, 6, 0, 0, 0, 0, time.UTC),
			time.Date(2023, time.December, 8, 0, 0, 0, 0, time.UTC),
		),
	)

for _, p := range s.AsSlice() {
	fmt.Printf("%s - %s\n", p.Min(), p.Max())
}
Output:

2023-12-01 00:00:00 +0000 UTC - 2023-12-02 00:00:00 +0000 UTC
2023-12-04 00:00:00 +0000 UTC - 2023-12-06 00:00:00 +0000 UTC
2023-12-08 00:00:00 +0000 UTC - 2023-12-10 00:00:00 +0000 UTC
Example (Range)
s := EmptySet[int]().
	Add(
		NewRange[int](1, 10),
	).
	Sub(
		NewRange[int](2, 4),
		NewRange[int](6, 8),
	)

for _, p := range s.AsSlice() {
	fmt.Printf("%d - %d\n", p.Min(), p.Max())
}
Output:

1 - 2
4 - 6
8 - 10

type Number

type Number interface {
	constraints.Float | constraints.Integer
}

Number represents a value in a range.

type Period

type Period[T time.Time] struct {
	// contains filtered or unexported fields
}

Period represents a portion of time.

func NewPeriod

func NewPeriod(s, e time.Time) Period[time.Time]

NewPeriod returns a new period with the given start and end dates.

func (Period[T]) After

func (p Period[T]) After(q Interval[T]) bool

After reports whether p starts after the end of q.

func (Period[T]) Before

func (p Period[T]) Before(q Interval[T]) bool

Before reports whether p ends before the beginning of q.

func (Period[T]) Contains

func (p Period[T]) Contains(q Interval[T]) bool

Contains reports whether p contains q.

func (Period[T]) Encompass

func (p Period[T]) Encompass(q Interval[T]) Interval[T]

Encompass returns a new period encompassing both periods. Both periods must overlap otherwise it returns a zero value period.

Example
a := NewPeriod(
	time.Date(2023, time.December, 3, 0, 0, 0, 0, time.UTC),
	time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
)

b := NewPeriod(
	time.Date(2023, time.December, 4, 0, 0, 0, 0, time.UTC),
	time.Date(2023, time.December, 6, 0, 0, 0, 0, time.UTC),
)

ab := a.Encompass(b)

fmt.Printf("%s - %s\n", ab.Min(), ab.Max())
Output:

2023-12-03 00:00:00 +0000 UTC - 2023-12-06 00:00:00 +0000 UTC

func (Period[T]) Equal

func (p Period[T]) Equal(q Interval[T]) bool

Equal reports whether p is equal to q. Two periods are equal when their start & end dates are equal.

func (Period[T]) Intersect

func (p Period[T]) Intersect(q Interval[T]) Interval[T]

Intersect returns a new period representing the intersection of both periods. The new period is either a valid and non-empty period (its start date being strictly greater than its end date) or a zero value period.

Example
a := NewPeriod(
	time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
	time.Date(2023, time.December, 7, 0, 0, 0, 0, time.UTC),
)

b := NewPeriod(
	time.Date(2023, time.December, 3, 0, 0, 0, 0, time.UTC),
	time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
)

r := a.Intersect(b)

fmt.Printf("%s - %s\n", r.Min(), r.Max())
Output:

2023-12-03 00:00:00 +0000 UTC - 2023-12-05 00:00:00 +0000 UTC

func (Period[T]) IsEmpty

func (p Period[T]) IsEmpty() bool

IsEmpty reports whether the period's start date is equal to its end date, meaning the period's duration would be equal to zero and therefore be empty.

func (Period[T]) IsValid

func (p Period[T]) IsValid() bool

IsValid reports whether the period's start date is lower than or equal to its end date. A period with a start date greater than its end date would be indeed invalid.

func (Period[T]) IsZero

func (p Period[T]) IsZero() bool

IsZero reports whether both start & end dates are zero values.

func (Period[T]) Max

func (p Period[T]) Max() T

Max returns the period's maximum value.

func (Period[T]) Min

func (p Period[T]) Min() T

Min returns the period's minimum value.

func (Period[T]) Overlaps

func (p Period[T]) Overlaps(q Interval[T]) bool

Overlaps reports whether p overlaps q.

func (Period[T]) Punch

func (p Period[T]) Punch(q Interval[T]) (Interval[T], Interval[T])

Punch cuts q out of p and returns the remaining periods.

Example
a := NewPeriod(
	time.Date(2023, time.December, 2, 0, 0, 0, 0, time.UTC),
	time.Date(2023, time.December, 7, 0, 0, 0, 0, time.UTC),
)

b := NewPeriod(
	time.Date(2023, time.December, 3, 0, 0, 0, 0, time.UTC),
	time.Date(2023, time.December, 5, 0, 0, 0, 0, time.UTC),
)

l, r := a.Punch(b)

fmt.Printf("%s - %s\n", l.Min(), l.Max())
fmt.Printf("%s - %s\n", r.Min(), r.Max())
Output:

2023-12-02 00:00:00 +0000 UTC - 2023-12-03 00:00:00 +0000 UTC
2023-12-05 00:00:00 +0000 UTC - 2023-12-07 00:00:00 +0000 UTC

type Range

type Range[T Number] struct {
	// contains filtered or unexported fields
}

Range represents a range between two numbers.

func NewRange

func NewRange[T Number](l, u T) Range[T]

NewRange returns a new range between lower and upper values.

func (Range[T]) After

func (p Range[T]) After(q Interval[T]) bool

After reports whether p lower value is greater than q upper value.

func (Range[T]) Before

func (p Range[T]) Before(q Interval[T]) bool

Before reports whether p upper value is lower than q lower value.

func (Range[T]) Contains

func (p Range[T]) Contains(q Interval[T]) bool

Contains reports whether p contains q.

func (Range[T]) Encompass

func (p Range[T]) Encompass(q Interval[T]) Interval[T]

Encompass returns a new range encompassing both ranges. Both ranges must overlap otherwise it returns a zero value range.

Example
a := NewRange[int](3, 5)
b := NewRange[int](4, 6)

ab := a.Encompass(b)

fmt.Printf("%d - %d\n", ab.Min(), ab.Max())
Output:

3 - 6

func (Range[T]) Equal

func (p Range[T]) Equal(q Interval[T]) bool

Equal reports whether p is equal to q. Two ranges are equal when their lower & upper values are equal.

func (Range[T]) Intersect

func (p Range[T]) Intersect(q Interval[T]) Interval[T]

Intersect returns a new range representing the intersection of both ranges. The new range is either a valid and non-empty range (its lower value being strictly greater than its upper value) or a zero value range.

Example
a := NewRange[int](2, 7)
b := NewRange[int](3, 5)

r := a.Intersect(b)

fmt.Printf("%d - %d\n", r.Min(), r.Max())
Output:

3 - 5

func (Range[T]) IsEmpty

func (p Range[T]) IsEmpty() bool

IsEmpty reports whether the range's values are equal.

func (Range[T]) IsValid

func (p Range[T]) IsValid() bool

IsValid reports whether the range's lower value is actually lower than or equal to the upper value.

func (Range[T]) IsZero

func (p Range[T]) IsZero() bool

IsZero reports whether both lower & upper values are zero values.

func (Range[T]) Max

func (p Range[T]) Max() T

Max returns the range's maximum value.

func (Range[T]) Min

func (p Range[T]) Min() T

Min returns the range's minimum value.

func (Range[T]) Overlaps

func (p Range[T]) Overlaps(q Interval[T]) bool

Overlaps reports whether p overlaps q.

func (Range[T]) Punch

func (p Range[T]) Punch(q Interval[T]) (Interval[T], Interval[T])

Punch cuts q out of p and returns the remaining ranges.

Example
a := NewRange(2, 7)
b := NewRange(3, 5)

l, r := a.Punch(b)

fmt.Printf("%d - %d\n", l.Min(), l.Max())
fmt.Printf("%d - %d\n", r.Min(), r.Max())
Output:

2 - 3
5 - 7

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL