-
Notifications
You must be signed in to change notification settings - Fork 0
/
forecast.go
75 lines (64 loc) · 1.92 KB
/
forecast.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
package ims
import (
"encoding/xml"
"fmt"
"io"
"net/http"
"time"
"golang.org/x/net/html/charset"
)
const forecastPath = "https://ims.gov.il/sites/default/files/ims_data/xml_files/IMS_001.xml"
type ForecastTime struct {
time.Time
}
func (c *ForecastTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
const format = "2/1/2006 15:04 MST"
var v string
d.DecodeElement(&v, &start)
// The IMS timestamps are given in the format "2/1/2006 15:04 MST". The timezone used is
// always set to "UTC" where it is actually should be in IDT.
v = v[:len(v)-3] + "IDT"
parse, err := time.Parse(format, v)
if err != nil {
return err
}
parse = parse.UTC()
*c = ForecastTime{parse}
return nil
}
type Forecast struct {
Name string `xml:"LocationMetaData>LocationName"`
Lat float32 `xml:"LocationMetaData>LocationLatitude"`
Long float32 `xml:"LocationMetaData>LocationLongitude"`
Elevation float32 `xml:"LocationMetaData>LocationHeight"`
Forecast []HourlyForecast `xml:"LocationData>Forecast"`
}
type HourlyForecast struct {
Time ForecastTime `xml:"ForecastTime"`
Temp float32 `xml:"Temperature"`
RelHum float32 `xml:"RelativeHumidity"`
WindSpeed float32 `xml:"WindSpeed"`
WindDir float32 `xml:"WindDirection"`
}
type forecastResponse struct {
XMLName xml.Name `xml:"HourlyLocationsForecast"`
Forecasts []Forecast `xml:"Location"`
}
func Predict() ([]Forecast, error) {
resp, err := http.Get(forecastPath)
if err != nil {
return nil, fmt.Errorf("fetching forecast: %s", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("bad status: %d", resp.StatusCode)
}
defer resp.Body.Close()
return predict(resp.Body)
}
func predict(r io.Reader) ([]Forecast, error) {
var data forecastResponse
d := xml.NewDecoder(r)
d.CharsetReader = charset.NewReaderLabel
err := d.Decode(&data)
return data.Forecasts, err
}