128 lines
3.2 KiB
Go
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)
|
|
}
|