gob/datetime/range.go

123 lines
3.8 KiB
Go
Raw Normal View History

2023-10-31 10:18:00 +00:00
package datetime
import (
"time"
. "gitea.zaclys.com/bvaudour/gob/option"
)
// Range représente une période entre deux dates.
type Range struct {
begin time.Time
end time.Time
}
// NewRange initialise une période.
// Si t1 > t2, la date début de la période sera t2, et inversement si t1 < t2.
func NewRange(t1, t2 time.Time) Range {
if Gt(t1, t2) {
t1, t2 = t2, t1
}
return Range{
begin: t1,
end: t2,
}
}
// Begin retourne la date de début de la période.
func (r Range) Begin() time.Time { return r.begin }
// End retourne la date de fin de la période.
func (r Range) End() time.Time { return r.end }
// BeforeDate retourne vrai si la date est située avant la période.
func (r Range) BeforeDate(t time.Time) bool { return Lt(r.end, t) }
// AfterDate retourne vrai si la date est située après la période.
func (r Range) AfterDate(t time.Time) bool { return Gt(r.begin, t) }
// ContainsDate retourne vrai si t ∈ [begin; end].
func (r Range) ContainsDate(t time.Time) bool { return Le(r.begin, t) && Ge(r.end, t) }
// ContainsDateStrictBegin retourne vrai si t ∈ ]begin; end].
func (r Range) ContainsDateStrictBegin(t time.Time) bool { return Lt(r.begin, t) && Ge(r.end, t) }
// ContainsDateStrictEnd retourne vrai si t ∈ [begin; end[.
func (r Range) ContainsDateStrictEnd(t time.Time) bool { return Le(r.begin, t) && Gt(r.end, t) }
// ContainsDateStrict retourne vrai si t ∈ ]begin; end[.
func (r Range) ContainsDateStrict(t time.Time) bool { return Lt(r.begin, t) && Gt(r.end, t) }
// IsFuture retourne vrai si la période est située dans le futur.
func (r Range) IsFuture() bool { return r.AfterDate(time.Now()) }
// IsPast retourne vrai si la période est située dans le passé.
func (r Range) IsPast() bool { return r.BeforeDate(time.Now()) }
// IsNow retourne vrai si la période est en cours.
func (r Range) IsNow() bool { return r.ContainsDate(time.Now()) }
// Before retourne vrai si r est avant r2 sans la recouvrir.
func (r Range) Before(r2 Range) bool { return Le(r.end, r2.begin) }
// After retourne vrai si r est après r2 sans la recouvrir.
func (r Range) After(r2 Range) bool { return Ge(r.begin, r2.end) }
// Contains retourne vrai si r inclut complètement r2.
func (r Range) Contains(r2 Range) bool { return Le(r.begin, r2.begin) && Ge(r.end, r2.end) }
// In retourne vrai si r est complètement inclus dans r2.
func (r Range) In(r2 Range) bool { return r2.Contains(r) }
// Excludes retourne vrai si les périodes ne se chevauchent pas.
func (r Range) Excludes(r2 Range) bool { return Le(r.end, r2.begin) || Ge(r.begin, r2.end) }
// Overlaps retourne vrai si les périodes se chevauchent.
func (r Range) Overlaps(r2 Range) bool { return Lt(r.begin, r2.end) && Gt(r.end, r2.begin) }
// Intersection retourne la période commune aux deux périodes, si elle existe.
func (r Range) Intersection(r2 Range) (result Option[Range]) {
if r.Overlaps(r2) {
result = Some(NewRange(Max(r.begin, r2.begin), Min(r.end, r2.end)))
}
return
}
// Joins retourne la plus grande période contiguë entre deux période, si elle existe.
func (r Range) Joins(r2 Range) (result Option[Range]) {
if Le(r.begin, r2.end) && Ge(r.end, r2.begin) {
result = Some(NewRange(Min(r.begin, r2.begin), Max(r.end, r2.end)))
}
return
}
// Diff retourne lensemble des périodes non communes aux deux périodes.
func (r Range) Diff(r2 Range) (result []Range) {
if Ne(r.begin, r2.begin) {
begin := Min(r.begin, r2.begin)
var end time.Time
if begin == r.begin {
end = Min(r.end, r2.begin)
} else {
end = Min(r2.end, r.begin)
}
result = append(result, NewRange(begin, end))
}
if Ne(r.end, r2.end) {
end := Max(r.end, r2.end)
var begin time.Time
if end == r.end {
begin = Max(r.begin, r2.end)
} else {
begin = Max(r2.begin, r.end)
}
result = append(result, NewRange(begin, end))
}
return
}