/
average.go
52 lines (41 loc) · 1.18 KB
/
average.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package main
import (
"bytes"
"time"
)
// A RollingAverage is an average duration that can be updated with
// more data points.
type RollingAverage struct {
// Cur is the current duration. The jsonDuration type is a light
// wrapper around time.Duration to make it marshal to and unmarshal
// from JSON properly.
Cur jsonDuration `json:"cur"`
// Num is the number of data points that the current average was
// calculated from.
Num int64 `json:"num"`
}
// Update adds a new data point to the average.
func (r *RollingAverage) Update(new time.Duration) time.Duration {
r.Cur = jsonDuration(((int64(r.Cur) * r.Num) + int64(new)) / (r.Num + 1))
r.Num++
return time.Duration(r.Cur)
}
// jsonDuration is a thin wrapper around time.Duration to make it more
// JSON friendly.
type jsonDuration time.Duration
func (d jsonDuration) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
buf.WriteByte('"')
buf.WriteString(time.Duration(d).String())
buf.WriteByte('"')
return buf.Bytes(), nil
}
func (d *jsonDuration) UnmarshalJSON(data []byte) error {
data = bytes.Trim(data, `"`)
t, err := time.ParseDuration(string(data))
if err != nil {
return err
}
*d = jsonDuration(t)
return nil
}