-
Notifications
You must be signed in to change notification settings - Fork 3
/
observation.go
80 lines (62 loc) · 1.38 KB
/
observation.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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package main
import (
"encoding/csv"
"fmt"
"io"
"math"
"strconv"
"time"
)
type obs struct {
t time.Time
v, e float64
}
type observation struct {
obs []obs
}
func (o *observation) read(f io.Reader) (err error) {
r := csv.NewReader(f)
r.FieldsPerRecord = 3
// read the header line and ignore it.
_, err = r.Read()
if err != nil {
return err
}
rawObs, err := r.ReadAll()
if err != nil {
return err
}
o.obs = make([]obs, len(rawObs))
for i, r := range rawObs {
obs := obs{}
obs.t, err = time.Parse(time.RFC3339Nano, r[0])
if err != nil {
return fmt.Errorf("error parsing date time in row %d: %s", i+1, r[0])
}
obs.v, err = strconv.ParseFloat(r[1], 64)
if err != nil {
return fmt.Errorf("error parsing value in row %d: %s", i+1, r[1])
}
if math.IsNaN(obs.v) {
return fmt.Errorf("Found NaN value in row %d: %s", i+1, r[1])
}
obs.e, err = strconv.ParseFloat(r[2], 64)
if err != nil {
return fmt.Errorf("error parsing error in row %d: %s", i+1, r[2])
}
if math.IsNaN(obs.e) {
return fmt.Errorf("Found NaN error in row %d: %s", i+1, r[2])
}
o.obs[i] = obs
}
// Check for duplicate date times in the data.
d := make(map[string]int, len(o.obs))
for _, v := range o.obs {
d[v.t.Format(time.RFC3339)] = 1
}
dups := len(o.obs) - len(d)
if dups != 0 {
return fmt.Errorf("found %d duplicate timestamp(s)", dups)
}
return err
}