-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinput.go
More file actions
88 lines (74 loc) · 2.46 KB
/
input.go
File metadata and controls
88 lines (74 loc) · 2.46 KB
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
81
82
83
84
85
86
87
88
package main
import (
"bufio"
"encoding/csv"
"errors"
"fmt"
"os"
"strconv"
"time"
)
type readProcessor struct {
reader *csv.Reader
}
type inputReader interface {
ReadRow() (row, error)
}
var _ inputReader = &readProcessor{}
func newReadProcessorCSV(path string, shouldReadFirstLine bool) (*readProcessor, func(), error) {
file, err := os.Open(path)
if err != nil {
return &readProcessor{}, func() {}, fmt.Errorf("error when opening input %w", err)
}
// use bufio to buffer the reading of the file
buf := bufio.NewReader(file)
reader := csv.NewReader(buf)
if shouldReadFirstLine {
columns, err := reader.Read()
if err != nil {
return &readProcessor{}, func() {}, fmt.Errorf("error when reading the head %w", err)
}
fmt.Println("coloumns are", columns)
}
return &readProcessor{reader: reader}, func() { file.Close() }, nil
}
func (r *readProcessor) ReadRow() (row, error) {
// condiser to set record reuse to true
records, err := r.reader.Read()
if err != nil {
return row{}, err
}
// each row has 3 feilds
if len(records) != 3 {
return row{}, FieldParseError{err: ErrInvalidFieldsCount}
}
// consider reusing a single row data and not to allocate from heap every time in convert funcitons
houseId, err := strconv.Atoi(records[0])
if err != nil {
return row{}, FieldParseError{err: errors.Join(err, ErrInvalidField), fieldName: "house-number"}
}
if houseId == 0 {
return row{}, FieldParseError{err: ErrInvalidField, fieldName: "house-number"}
}
consumption, err := strconv.ParseFloat(records[1], 64)
if err != nil {
return row{}, FieldParseError{err: errors.Join(err, ErrInvalidField), fieldName: "consumption"}
}
seconds, err := strconv.Atoi(records[2])
if err != nil {
return row{}, FieldParseError{err: errors.Join(err, ErrInvalidField), fieldName: "time"}
}
t := time.Unix(int64(seconds), 0)
if t.IsZero() {
return row{}, FieldParseError{err: ErrInvalidField, fieldName: "time"}
}
// no need to change the time zone, the standard unix time is in utc and when reading Time library will move it to local time
// however to make sure this code runs everywhere correctly we can set the time zone to amsterdam time at the begining
// location, err := time.LoadLocation("Europe/Amsterdam")
// if err != nil {
// fmt.Println("Error loading location:", err)
// return row{}, FieldParseError{error: ErrInvalidField, fieldName: "time"}
// }
// nlTime := t.In(location)
return row{consumption: consumption, houseId: houseId, time: t}, nil
}