aeus-admin/pkg/chartjs/series.go

127 lines
2.8 KiB
Go

package chartjs
import (
"sync"
"time"
)
const (
Minute = "minute"
Hour = "hour"
Day = "day"
Method = "method"
)
// 时间序列值, 实现了按时间进行分组的值计算
type TimeSeries struct {
mutex sync.Mutex
step string
values []*TimeseriesValue
}
func (s *TimeSeries) cutTimeSeries(tm time.Time) int64 {
switch s.step {
case Method:
return time.Date(tm.Year(), tm.Month(), 0, 0, 0, 0, 0, time.Local).Unix()
case Day:
return time.Date(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0, time.Local).Unix()
case Hour:
return time.Date(tm.Year(), tm.Month(), tm.Day(), tm.Hour(), 0, 0, 0, time.Local).Unix()
default:
return time.Date(tm.Year(), tm.Month(), tm.Day(), tm.Hour(), tm.Minute(), 0, 0, time.Local).Unix()
}
}
func (s *TimeSeries) truncateTime(ts int64) int64 {
tm := time.Unix(ts, 0)
switch s.step {
case Method:
return time.Date(tm.Year(), tm.Month(), 0, 0, 0, 0, 0, time.Local).Unix()
case Day:
return time.Date(tm.Year(), tm.Month(), tm.Day(), 0, 0, 0, 0, time.Local).Unix()
case Hour:
return time.Date(tm.Year(), tm.Month(), tm.Day(), tm.Hour(), 0, 0, 0, time.Local).Unix()
default:
return time.Date(tm.Year(), tm.Month(), tm.Day(), tm.Hour(), tm.Minute(), 0, 0, time.Local).Unix()
}
return tm.Unix()
}
func (s *TimeSeries) nextTimestamp(ts int64) int64 {
tm := time.Unix(ts, 0)
switch s.step {
case Method:
return tm.AddDate(0, 1, 0).Unix()
case Day:
return tm.AddDate(0, 0, 1).Unix()
case Hour:
return ts + 3600
default:
return ts + 60
}
}
func (s *TimeSeries) Inc(tm time.Time, value float64) {
s.mutex.Lock()
defer s.mutex.Unlock()
ts := s.cutTimeSeries(tm)
for _, v := range s.values {
if v.Timestamp == ts {
v.Value += value
return
}
}
s.values = append(s.values, &TimeseriesValue{
Timestamp: ts,
Value: value,
})
}
func (s *TimeSeries) Dec(tm time.Time, value float64) {
s.mutex.Lock()
defer s.mutex.Unlock()
ts := s.cutTimeSeries(tm)
for _, v := range s.values {
if v.Timestamp == ts {
v.Value -= value
return
}
}
}
func (s *TimeSeries) Values(sts, ets int64) []*TimeseriesValue {
var (
nextStamp int64
)
sts = s.truncateTime(sts)
ets = s.truncateTime(ets)
series := make([]*TimeseriesValue, 0, len(s.values))
nextStamp = sts
for _, row := range s.values {
for row.Timestamp > nextStamp {
series = append(series, &TimeseriesValue{
Timestamp: nextStamp,
Value: 0,
})
nextStamp = s.nextTimestamp(nextStamp)
}
series = append(series, row)
nextStamp = s.nextTimestamp(nextStamp)
}
for ets > nextStamp {
series = append(series, &TimeseriesValue{
Timestamp: nextStamp,
Value: 0,
})
nextStamp = s.nextTimestamp(nextStamp)
}
return series
}
func NewTimeSeries(step string) *TimeSeries {
return &TimeSeries{
step: step,
values: make([]*TimeseriesValue, 0, 64),
}
}