gob/datetime/range.go

159 lines
4.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package datetime
import (
. "gitea.zaclys.com/bvaudour/gob/option"
)
// TimeComparator représente tout type dindication de temps.
type TimeComparator[E any] interface {
Eq(E) bool
Ne(E) bool
Gt(E) bool
Ge(E) bool
Lt(E) bool
Le(E) bool
IsNow() bool
IsPast() bool
IsFuture() bool
Now() E
}
// Min retourne le temps le plus petit.
func Min[C TimeComparator[C]](e C, args ...C) C {
out := e
for _, a := range args {
if a.Lt(out) {
out = a
}
}
return out
}
// Max retourne le temps le plus grand.
func Max[C TimeComparator[C]](e C, args ...C) C {
out := e
for _, a := range args {
if a.Gt(out) {
out = a
}
}
return out
}
// Range représente une période entre deux bornes temporelles.
type Range[C TimeComparator[C]] struct {
begin, end C
}
// NewRange retourne une période entre begin et end.
// Si begin < end, les bornes sont inversées.
func NewRange[C TimeComparator[C]](begin, end C) Range[C] {
if begin.Gt(end) {
begin, end = end, begin
}
return Range[C]{begin, end}
}
// Begin retourne le début de la période.
func (r Range[C]) Begin() C { return r.begin }
// End retourne la fin de la période.
func (r Range[C]) End() C { return r.end }
// Before retourne vrai si e est située avant la période.
func (r Range[C]) Before(e C) bool { return e.Lt(r.begin) }
// After retourne vrai si e est située après la période.
func (r Range[C]) After(e C) bool { return e.Gt(r.end) }
// Contains retourne vrai si e ∈ [begin;end].
func (r Range[C]) Contains(e C) bool { return e.Ge(r.begin) && e.Le(r.end) }
// ContainsStrictLeft retourne vrai si e ∈ ]begin;end].
func (r Range[C]) ContainsStrictLeft(e C) bool { return e.Gt(r.begin) && e.Le(r.end) }
// ContainsStrictRight retourne vrai si e ∈ [begin;end[.
func (r Range[C]) ContainsStrictRight(e C) bool { return e.Ge(r.begin) && e.Lt(r.end) }
// ContainsStrict retourne vrai si e ∈ ]begin;end[.
func (r Range[C]) ContainsStrict(e C) bool { return e.Gt(r.begin) && e.Lt(r.end) }
// IsNow retourne vrai si la période est en cours.
func (r Range[C]) IsNow() bool { return r.Contains(r.begin.Now()) }
// IsPast retourne vrai si la période est située dans le passé.
func (r Range[C]) IsPast() bool { return r.Before(r.begin.Now()) }
// IsFuture retourne vrai la période est située dans le futur.
func (r Range[C]) IsFuture() bool { return r.After(r.begin.Now()) }
// BeforeRange retourne vrai si r1 est terminée avant que r2 commence.
func (r1 Range[C]) BeforeRange(r2 Range[C]) bool { return r1.end.Le(r2.begin) }
// AfterRange retourne vrai si r2 est terminée avec que r1 commence.
func (r1 Range[C]) AfterRange(r2 Range[C]) bool { return r2.BeforeRange(r1) }
// ContainsRange retourne vrai si r2 est intégralement comprise dans r1.
func (r1 Range[C]) ContainsRange(r2 Range[C]) bool {
return r1.begin.Le(r2.begin) && r1.end.Ge(r2.end)
}
// InRange retourne vrai si r2 comprend intégralement r1.
func (r1 Range[C]) InRange(r2 Range[C]) bool { return r2.ContainsRange(r1) }
// Excludes retourne vrai si r1 et r2 ne se chevauchent pas.
func (r1 Range[C]) Excludes(r2 Range[C]) bool {
return r1.end.Le(r2.begin) || r1.begin.Ge(r2.end)
}
// Overlaps retourne vrai si r1 et r2 se chevauchent.
func (r1 Range[C]) Overlaps(r2 Range[C]) bool {
return r1.begin.Lt(r2.end) && r1.end.Gt(r2.begin)
}
// Intersection retourne la période commune entre deux périodes.
func (r1 Range[C]) Intersection(r2 Range[C]) (result Option[Range[C]]) {
if r1.Overlaps(r2) {
result = Some(NewRange(Max(r1.begin, r2.begin), Min(r1.end, r2.end)))
}
return
}
// Joins retourne la plus grande période contiguë formée par deux périodes.
func (r1 Range[C]) Joins(r2 Range[C]) (result Option[Range[C]]) {
if r1.begin.Le(r2.end) && r1.end.Ge(r2.begin) {
result = Some(NewRange(Min(r1.begin, r2.begin), Max(r1.end, r2.end)))
}
return
}
// Diff retourne la liste des périodes qui ne se chevauchent pas.
func (r1 Range[C]) Diff(r2 Range[C]) (result []Range[C]) {
if r1.begin.Ne(r2.begin) {
begin := Min(r1.begin, r2.begin)
var end C
if begin.Eq(r1.begin) {
end = Min(r1.end, r2.begin)
} else {
end = Min(r2.end, r1.begin)
}
result = append(result, NewRange(begin, end))
}
if r1.end.Ne(r2.end) {
end := Max(r1.end, r2.end)
var begin C
if end.Eq(r1.end) {
begin = Max(r1.begin, r2.end)
} else {
begin = Max(r2.begin, r1.end)
}
result = append(result, NewRange(begin, end))
}
return
}