2019-02-13 19:09:26 -05:00
|
|
|
package chart
|
|
|
|
|
|
|
|
import "time"
|
|
|
|
|
|
|
|
// SecondsPerXYZ
|
|
|
|
const (
|
|
|
|
SecondsPerHour = 60 * 60
|
|
|
|
SecondsPerDay = 60 * 60 * 24
|
|
|
|
)
|
|
|
|
|
|
|
|
// TimeMillis returns a duration as a float millis.
|
|
|
|
func TimeMillis(d time.Duration) float64 {
|
|
|
|
return float64(d) / float64(time.Millisecond)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DiffHours returns the difference in hours between two times.
|
|
|
|
func DiffHours(t1, t2 time.Time) (hours int) {
|
|
|
|
t1n := t1.Unix()
|
|
|
|
t2n := t2.Unix()
|
|
|
|
var diff int64
|
|
|
|
if t1n > t2n {
|
|
|
|
diff = t1n - t2n
|
|
|
|
} else {
|
|
|
|
diff = t2n - t1n
|
|
|
|
}
|
|
|
|
return int(diff / (SecondsPerHour))
|
|
|
|
}
|
|
|
|
|
|
|
|
// TimeMin returns the minimum and maximum times in a given range.
|
|
|
|
func TimeMin(times ...time.Time) (min time.Time) {
|
|
|
|
if len(times) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
min = times[0]
|
|
|
|
for index := 1; index < len(times); index++ {
|
|
|
|
if times[index].Before(min) {
|
|
|
|
min = times[index]
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// TimeMax returns the minimum and maximum times in a given range.
|
|
|
|
func TimeMax(times ...time.Time) (max time.Time) {
|
|
|
|
if len(times) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
max = times[0]
|
|
|
|
|
|
|
|
for index := 1; index < len(times); index++ {
|
|
|
|
if times[index].After(max) {
|
|
|
|
max = times[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// TimeMinMax returns the minimum and maximum times in a given range.
|
|
|
|
func TimeMinMax(times ...time.Time) (min, max time.Time) {
|
|
|
|
if len(times) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
min = times[0]
|
|
|
|
max = times[0]
|
|
|
|
|
|
|
|
for index := 1; index < len(times); index++ {
|
|
|
|
if times[index].Before(min) {
|
|
|
|
min = times[index]
|
|
|
|
}
|
|
|
|
if times[index].After(max) {
|
|
|
|
max = times[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// TimeToFloat64 returns a float64 representation of a time.
|
|
|
|
func TimeToFloat64(t time.Time) float64 {
|
2023-12-08 10:20:57 -05:00
|
|
|
if t.IsZero() {
|
|
|
|
return 0
|
|
|
|
}
|
2019-02-13 19:09:26 -05:00
|
|
|
return float64(t.UnixNano())
|
|
|
|
}
|
|
|
|
|
2023-12-08 10:20:57 -05:00
|
|
|
// TimeFromFloat64 returns a time in nanosecond from a float64.
|
2019-02-13 21:55:13 -05:00
|
|
|
func TimeFromFloat64(tf float64) time.Time {
|
2023-12-08 10:20:57 -05:00
|
|
|
if tf == 0 {
|
|
|
|
return time.Time{}
|
|
|
|
}
|
2019-02-13 21:55:13 -05:00
|
|
|
return time.Unix(0, int64(tf))
|
|
|
|
}
|
|
|
|
|
2019-02-13 19:09:26 -05:00
|
|
|
// TimeDescending sorts a given list of times ascending, or min to max.
|
|
|
|
type TimeDescending []time.Time
|
|
|
|
|
|
|
|
// Len implements sort.Sorter
|
|
|
|
func (d TimeDescending) Len() int { return len(d) }
|
|
|
|
|
|
|
|
// Swap implements sort.Sorter
|
|
|
|
func (d TimeDescending) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
|
|
|
|
|
|
|
|
// Less implements sort.Sorter
|
|
|
|
func (d TimeDescending) Less(i, j int) bool { return d[i].After(d[j]) }
|
|
|
|
|
|
|
|
// TimeAscending sorts a given list of times ascending, or min to max.
|
|
|
|
type TimeAscending []time.Time
|
|
|
|
|
|
|
|
// Len implements sort.Sorter
|
|
|
|
func (a TimeAscending) Len() int { return len(a) }
|
|
|
|
|
|
|
|
// Swap implements sort.Sorter
|
|
|
|
func (a TimeAscending) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
|
|
|
|
|
|
// Less implements sort.Sorter
|
|
|
|
func (a TimeAscending) Less(i, j int) bool { return a[i].Before(a[j]) }
|
2019-02-13 21:55:13 -05:00
|
|
|
|
|
|
|
// Days generates a seq of timestamps by day, from -days to today.
|
|
|
|
func Days(days int) []time.Time {
|
|
|
|
var values []time.Time
|
|
|
|
for day := days; day >= 0; day-- {
|
|
|
|
values = append(values, time.Now().AddDate(0, 0, -day))
|
|
|
|
}
|
|
|
|
return values
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hours returns a sequence of times by the hour for a given number of hours
|
|
|
|
// after a given start.
|
|
|
|
func Hours(start time.Time, totalHours int) []time.Time {
|
|
|
|
times := make([]time.Time, totalHours)
|
|
|
|
|
|
|
|
last := start
|
|
|
|
for i := 0; i < totalHours; i++ {
|
|
|
|
times[i] = last
|
|
|
|
last = last.Add(time.Hour)
|
|
|
|
}
|
|
|
|
|
|
|
|
return times
|
|
|
|
}
|
|
|
|
|
|
|
|
// HoursFilled adds zero values for the data bounded by the start and end of the xdata array.
|
|
|
|
func HoursFilled(xdata []time.Time, ydata []float64) ([]time.Time, []float64) {
|
|
|
|
start, end := TimeMinMax(xdata...)
|
|
|
|
totalHours := DiffHours(start, end)
|
|
|
|
|
|
|
|
finalTimes := Hours(start, totalHours+1)
|
|
|
|
finalValues := make([]float64, totalHours+1)
|
|
|
|
|
|
|
|
var hoursFromStart int
|
|
|
|
for i, xd := range xdata {
|
|
|
|
hoursFromStart = DiffHours(start, xd)
|
|
|
|
finalValues[hoursFromStart] = ydata[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
return finalTimes, finalValues
|
|
|
|
}
|