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
|
|||
|
}
|