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 }