spaniel

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2019 License: MIT Imports: 3 Imported by: 7

README

Spaniel

Time span handling for Go

godoc license build

Spaniel contains functionality for timespan handling, specifically for merging overlapping timespans and finding the intersections between multiple timespans. It lets you specify the type of interval you want to use (open, closed), and provide handlers for when you want to add more functionality when merging/intersecting.

Install

This package is "go-gettable", just do:

go get github.com/senseyeio/spaniel

Basics

Spaniel operates on lists of timespans, where a timespan is represented as the interval between a start and end time. It has a built-in minimal timespan representation for convenience, or you can use your own type, so long as it implements the timespan.Span interface.

To import spaniel and create a new list of timespans:

package main

import (
	"fmt"
	timespan "github.com/senseyeio/spaniel"
	"time"
)

func main() {
	// Times at half-hourly intervals
	var t1 = time.Date(2018, 1, 30, 0, 0, 0, 0, time.UTC)
	var t2 = time.Date(2018, 1, 30, 0, 30, 0, 0, time.UTC)
	var t3 = time.Date(2018, 1, 30, 1, 0, 0, 0, time.UTC)
	var t4 = time.Date(2018, 1, 30, 1, 30, 0, 0, time.UTC)

	input := timespan.Spans{
		timespan.New(t1, t3),
		timespan.New(t2, t4),
	}
	fmt.Println(input)
}

You can then use the Union function to merge the timestamps:

union := input.Union()
fmt.Println(union[0].Start(), "->", union[0].End()) // 2018-01-30 00:00:00 +0000 UTC -> 2018-01-30 01:30:00 +0000 UTC

Or the Intersection function to find the overlaps:

intersection := input.Intersection()
fmt.Println(intersection[0].Start(), "->", intersection[0].End()) // 2018-01-30 00:30:00 +0000 UTC -> 2018-01-30 01:00:00 +0000 UTC

Types

timespan.New sets the span to be [) by default - i.e. including the left-most point, excluding the right-most. In other words, [1,2,3) and [3,4,5) do not overlap, but are contiguous. Instants are [] by default (they contain a single time).

If you would like to override these types, you can use NewWithTypes:

openSpan := timespan.NewWithTypes(t1, t3, timespan.Open, timespan.Open)

You can see a more involved example of types in examples/types/types.go

Handlers

If you need to use a more complex object, you can call UnionWithHandler and IntersectionWithHandler. There is an example of this in examples/handlers/handlers.go.

More Examples

All of the above examples are available in the examples folder.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsInstant

func IsInstant(a Span) bool

IsInstant returns true if the interval is deemed instantaneous

Types

type ByEnd

type ByEnd Spans

ByEnd sorts a list of spans by their end point

Example
package main

import (
	"fmt"
	"github.com/senseyeio/spaniel"
	"sort"
)

var input spaniel.Spans

func main() {
	sort.Stable(spaniel.ByEnd(input))

	for i := range input {
		fmt.Println(input[i].End())
	}

}
Output:

2018-01-30 01:00:00 +0000 UTC
2018-01-30 01:30:00 +0000 UTC
2018-01-30 01:34:00 +0000 UTC
2018-01-30 01:35:00 +0000 UTC

func (ByEnd) Len

func (s ByEnd) Len() int

func (ByEnd) Less

func (s ByEnd) Less(i, j int) bool

func (ByEnd) Swap

func (s ByEnd) Swap(i, j int)

type ByStart

type ByStart Spans

ByStart sorts a list of spans by their start point

Example
package main

import (
	"fmt"
	"github.com/senseyeio/spaniel"
	"sort"
)

var input spaniel.Spans

func main() {
	sort.Stable(spaniel.ByStart(input))

	for i := range input {
		fmt.Println(input[i].Start())
	}

}
Output:

2018-01-30 00:00:00 +0000 UTC
2018-01-30 00:30:00 +0000 UTC
2018-01-30 01:31:00 +0000 UTC
2018-01-30 01:33:00 +0000 UTC

func (ByStart) Len

func (s ByStart) Len() int

func (ByStart) Less

func (s ByStart) Less(i, j int) bool

func (ByStart) Swap

func (s ByStart) Swap(i, j int)

type EndPoint

type EndPoint struct {
	Element time.Time
	Type    EndPointType
}

EndPoint represents an extreme of an interval, and whether it is inclusive or exclusive (Closed or Open)

type EndPointType

type EndPointType int

EndPointType represents whether the start or end of an interval is Closed or Open.

const (
	// Open means that the interval does not include a value
	Open EndPointType = iota
	// Closed means that the interval does include a value
	Closed
)

type IntersectionHandlerFunc

type IntersectionHandlerFunc func(intersectingEvent1, intersectingEvent2, intersectionSpan Span) Span

IntersectionHandlerFunc is used by IntersectionWithHandler to allow for custom functionality when two spans intersect. It is passed the two spans that intersect, and span representing the intersection.

type Span

type Span interface {
	Start() time.Time
	StartType() EndPointType
	End() time.Time
	EndType() EndPointType
}

Span represents a basic span, with a start and end time.

type Spans

type Spans []Span

Spans represents a list of spans, on which other functions operate.

func (Spans) Intersection

func (s Spans) Intersection() Spans

Intersection returns a list of Spans representing the overlaps between the contained spans. For example, given a list [A,B] where A and B overlap, a list [C] would be returned, with the span C covering the intersection of A and B.

Example
package main

import (
	"fmt"
	"github.com/senseyeio/spaniel"
)

var input spaniel.Spans

func main() {
	intersection := input.Intersection()

	for i := range intersection {
		fmt.Println(intersection[i].Start(), "->", intersection[i].End(), ": ", intersection[i].End().Sub(intersection[i].Start()))
	}

}
Output:

2018-01-30 00:30:00 +0000 UTC -> 2018-01-30 01:00:00 +0000 UTC :  30m0s
2018-01-30 01:33:00 +0000 UTC -> 2018-01-30 01:34:00 +0000 UTC :  1m0s

func (Spans) IntersectionBetween

func (s Spans) IntersectionBetween(b Spans) Spans

IntersectionBetween returns the slice of spans representing the overlaps between the contained spans and a given set of spans.

func (Spans) IntersectionBetweenWithHandler

func (s Spans) IntersectionBetweenWithHandler(candidates Spans, intersectHandlerFunc IntersectionHandlerFunc) Spans

IntersectionBetweenWithHandler returns a list of pointers to Spans representing the overlaps between the contained spans and a given set of spans. It calls intersectHandlerFunc for each pair of spans that are intersected.

func (Spans) IntersectionWithHandler

func (s Spans) IntersectionWithHandler(intersectHandlerFunc IntersectionHandlerFunc) Spans

IntersectionWithHandler returns a list of Spans representing the overlaps between the contained spans. For example, given a list [A,B] where A and B overlap, a list [C] would be returned, with the span C covering the intersection of the A and B. The provided handler function is notified of the two spans that have been found to overlap, and the span representing the overlap.

func (Spans) Union

func (s Spans) Union() Spans

Union returns a list of Spans representing the union of all of the spans. For example, given a list [A,B] where A and B overlap, a list [C] would be returned, with the span C spanning both A and B.

Example
package main

import (
	"fmt"
	"github.com/senseyeio/spaniel"
)

var input spaniel.Spans

func main() {
	union := input.Union()

	for u := range union {
		fmt.Println(union[u].Start(), "->", union[u].End(), ": ", union[u].End().Sub(union[u].Start()))
	}

}
Output:

2018-01-30 00:00:00 +0000 UTC -> 2018-01-30 01:30:00 +0000 UTC :  1h30m0s
2018-01-30 01:31:00 +0000 UTC -> 2018-01-30 01:35:00 +0000 UTC :  4m0s

func (Spans) UnionWithHandler

func (s Spans) UnionWithHandler(unionHandlerFunc UnionHandlerFunc) Spans

UnionWithHandler returns a list of Spans representing the union of all of the spans. For example, given a list [A,B] where A and B overlap, a list [C] would be returned, with the span C spanning both A and B. The provided handler is passed the source and destination spans, and the currently merged empty span.

type TimeSpan

type TimeSpan struct {
	// contains filtered or unexported fields
}

TimeSpan represents a simple span of time, with no additional properties. It should be constructed with NewEmpty.

Example
package main

import (
	"fmt"
	"github.com/senseyeio/spaniel"
	"time"
)

func main() {
	start, _ := time.Parse("2006-01-02 15:04:05", "2018-01-01 00:00:00")
	timespan := spaniel.New(start, time.Unix(1514768400, 0).UTC())

	fmt.Printf("Start: %v (%v)\nEnd: %v (%v)\n", timespan.Start(), timespan.StartType(), timespan.End(), timespan.EndType())

}
Output:

Start: 2018-01-01 00:00:00 +0000 UTC (1)
End: 2018-01-01 01:00:00 +0000 UTC (0)

func New

func New(start time.Time, end time.Time) *TimeSpan

New creates a span with a start and end time, with the types set to [] for instants and [) for spans.

func NewInstant

func NewInstant(time time.Time) *TimeSpan

NewInstant creates a span with just a single time.

func NewWithTypes

func NewWithTypes(start, end time.Time, startType, endType EndPointType) *TimeSpan

NewWithTypes creates a span with just a start and end time, and associated types, and is used when no handlers are provided to Union or Intersection.

func (TimeSpan) End

func (ts TimeSpan) End() time.Time

End returns the end time of a span

func (TimeSpan) EndType

func (ts TimeSpan) EndType() EndPointType

EndType returns the type of the end of the interval (Closed in this case)

func (TimeSpan) MarshalJSON

func (ts TimeSpan) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshal

func (TimeSpan) Start

func (ts TimeSpan) Start() time.Time

Start returns the start time of a span

func (TimeSpan) StartType

func (ts TimeSpan) StartType() EndPointType

StartType returns the type of the start of the interval (Open in this case)

func (TimeSpan) String

func (ts TimeSpan) String() string

String returns a string representation of a timespan

func (*TimeSpan) UnmarshalJSON

func (ts *TimeSpan) UnmarshalJSON(b []byte) (err error)

UnmarshalJSON implements json.Unmarshal

type UnionHandlerFunc

type UnionHandlerFunc func(mergeInto, mergeFrom, mergeSpan Span) Span

UnionHandlerFunc is used by UnionWithHandler to allow for custom functionality when two spans are merged. It is passed the two spans to be merged, and span which will result from the union.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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