Files
kouiz/internal/timex/interval.go
2025-06-15 14:46:32 +02:00

128 lines
3.2 KiB
Go

package timex
import (
"fmt"
"time"
)
type Interval struct {
intervalDuration time.Duration
periodType PeriodType
}
type PeriodType string
const (
PeriodHourly PeriodType = "hourly"
PeriodDaily PeriodType = "daily"
PeriodMonthly PeriodType = "monthly"
PeriodYearly PeriodType = "yearly"
)
func NewInterval(intervalDuration time.Duration, periodType PeriodType) *Interval {
return &Interval{
intervalDuration: intervalDuration,
periodType: periodType,
}
}
func (i *Interval) GetCurrent() int {
return i.GetIntervalForTime(time.Now().UTC())
}
func (i *Interval) GetIntervalForTime(t time.Time) int {
t = t.UTC()
periodStart := i.getPeriodStart(t)
elapsed := t.Sub(periodStart)
intervalIndex := int(elapsed / i.intervalDuration)
// S'assurer que l'index n'est pas négatif
if intervalIndex < 0 {
intervalIndex = 0
}
return intervalIndex
}
func (i *Interval) getPeriodStart(t time.Time) time.Time {
t = t.UTC()
switch i.periodType {
case PeriodHourly:
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, time.UTC)
case PeriodDaily:
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
case PeriodMonthly:
return time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.UTC)
case PeriodYearly:
return time.Date(t.Year(), 1, 1, 0, 0, 0, 0, time.UTC)
default:
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC)
}
}
func (i *Interval) GetTotalIntervalsInPeriod(referenceTime time.Time) int {
referenceTime = referenceTime.UTC()
periodStart := i.getPeriodStart(referenceTime)
periodEnd := i.getPeriodEnd(referenceTime)
totalDuration := periodEnd.Sub(periodStart)
return int(totalDuration / i.intervalDuration)
}
func (i *Interval) getPeriodEnd(t time.Time) time.Time {
t = t.UTC()
switch i.periodType {
case PeriodHourly:
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour()+1, 0, 0, 0, time.UTC)
case PeriodDaily:
return time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, time.UTC)
case PeriodMonthly:
return time.Date(t.Year(), t.Month()+1, 1, 0, 0, 0, 0, time.UTC)
case PeriodYearly:
return time.Date(t.Year()+1, 1, 1, 0, 0, 0, 0, time.UTC)
default:
return time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, time.UTC)
}
}
func (i *Interval) GetIntervalBounds(index int, referenceTime time.Time) (time.Time, time.Time) {
referenceTime = referenceTime.UTC()
periodStart := i.getPeriodStart(referenceTime)
intervalStart := periodStart.Add(time.Duration(index) * i.intervalDuration)
intervalEnd := intervalStart.Add(i.intervalDuration)
return intervalStart.UTC(), intervalEnd.UTC()
}
func (i *Interval) GetIntervalInfo(t time.Time) IntervalInfo {
t = t.UTC()
index := i.GetIntervalForTime(t)
start, end := i.GetIntervalBounds(index, t)
return IntervalInfo{
Index: index,
Start: start,
End: end,
Duration: i.intervalDuration,
Reference: t,
}
}
type IntervalInfo struct {
Index int
Start time.Time
End time.Time
Duration time.Duration
Reference time.Time
}
func (ii IntervalInfo) String() string {
return fmt.Sprintf("Interval %d: %s -> %s (Duration: %v)",
ii.Index,
ii.Start.Format("2006-01-02 15:04:05"),
ii.End.Format("2006-01-02 15:04:05"),
ii.Duration)
}