123 lines
3.8 KiB
Go
123 lines
3.8 KiB
Go
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 l’ensemble 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
|
||
}
|