Skip to content

Commit 8ddc8ab

Browse files
committed
feat: timestamps back to FDSN format for api query parameter and result. Only StationXML uses new RFC3339
1 parent 659c994 commit 8ddc8ab

14 files changed

Lines changed: 222 additions & 293 deletions

cmd/fdsn-ws/etc/fdsn-station-test.xml

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

cmd/fdsn-ws/fdsn_dataselect.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func fdsnDataMetricsV1Handler(r *http.Request, h http.Header, b *bytes.Buffer) e
7777

7878
switch r.Method {
7979
case "POST":
80-
defer r.Body.Close()
80+
defer func() { _ = r.Body.Close() }()
8181
if err := fdsn.ParseDataSelectPost(r.Body, &params); err != nil {
8282
return fdsnError{StatusError: weft.StatusError{Code: http.StatusBadRequest, Err: err}, url: r.URL.String(), timestamp: tm}
8383
}
@@ -144,7 +144,7 @@ func fdsnDataselectV1Handler(r *http.Request, w http.ResponseWriter) (int64, err
144144

145145
switch r.Method {
146146
case "POST":
147-
defer r.Body.Close()
147+
defer func() { _ = r.Body.Close() }()
148148
if err := fdsn.ParseDataSelectPost(r.Body, &params); err != nil {
149149
return 0, fdsnError{StatusError: weft.StatusError{Code: http.StatusBadRequest, Err: err}, url: r.URL.String(), timestamp: tm}
150150
}
@@ -181,7 +181,7 @@ func fdsnDataselectV1Handler(r *http.Request, w http.ResponseWriter) (int64, err
181181

182182
for _, v := range params {
183183
//flick gtHalfHour to true if the request is longer than half an hour
184-
gtHalfHour = gtHalfHour || v.EndTime.Sub(time.Time(v.StartTime.Time)) > time.Minute*30
184+
gtHalfHour = gtHalfHour || v.EndTime.Sub(v.StartTime.Time) > time.Minute*30
185185

186186
d, err := v.Regexp()
187187
if err != nil {
@@ -303,7 +303,7 @@ func fdsnDataselectVersion(r *http.Request, h http.Header, b *bytes.Buffer) erro
303303
}
304304

305305
h.Set("Content-Type", "text/plain")
306-
_, err = b.WriteString("1.1")
306+
_, err = b.WriteString(dataselectVersion)
307307

308308
return err
309309
}

cmd/fdsn-ws/fdsn_event.go

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -36,33 +36,29 @@ var eventAbbreviations = map[string]string{
3636
// supported query parameters for the event service from http://www.fdsn.org/webservices/FDSN-WS-Specifications-1.1.pdf
3737
type fdsnEventV1 struct {
3838
// required
39-
StartTime Time `schema:"starttime"` // limit to events on or after the specified start time.
40-
EndTime Time `schema:"endtime"` // limit to events on or before the specified end time.
41-
MinLatitude float64 `schema:"minlatitude"` // limit to events with a latitude larger than or equal to the specified minimum.
42-
MaxLatitude float64 `schema:"maxlatitude"` // limit to events with a latitude smaller than or equal to the specified maximum.
43-
MinLongitude float64 `schema:"minlongitude"` // limit to events with a longitude larger than or equal to the specified minimum.
44-
MaxLongitude float64 `schema:"maxlongitude"` // limit to events with a longitude smaller than or equal to the specified maximum.
45-
MinDepth float64 `schema:"mindepth"` // limit to events with depth more than the specified minimum.
46-
MaxDepth float64 `schema:"maxdepth"` // limit to events with depth less than the specified maximum.
47-
MinMagnitude float64 `schema:"minmagnitude"` // limit to events with a magnitude larger than the specified minimum.
48-
MaxMagnitude float64 `schema:"maxmagnitude"` // limit to events with a magnitude smaller than the specified maximum.
49-
OrderBy string `schema:"orderby"` // order the result by time or magnitude with the following possibilities: time, time-asc, magnitude, magnitude-asc
39+
StartTime fdsn.WsDateTime `schema:"starttime"` // limit to events on or after the specified start time.
40+
EndTime fdsn.WsDateTime `schema:"endtime"` // limit to events on or before the specified end time.
41+
MinLatitude float64 `schema:"minlatitude"` // limit to events with a latitude larger than or equal to the specified minimum.
42+
MaxLatitude float64 `schema:"maxlatitude"` // limit to events with a latitude smaller than or equal to the specified maximum.
43+
MinLongitude float64 `schema:"minlongitude"` // limit to events with a longitude larger than or equal to the specified minimum.
44+
MaxLongitude float64 `schema:"maxlongitude"` // limit to events with a longitude smaller than or equal to the specified maximum.
45+
MinDepth float64 `schema:"mindepth"` // limit to events with depth more than the specified minimum.
46+
MaxDepth float64 `schema:"maxdepth"` // limit to events with depth less than the specified maximum.
47+
MinMagnitude float64 `schema:"minmagnitude"` // limit to events with a magnitude larger than the specified minimum.
48+
MaxMagnitude float64 `schema:"maxmagnitude"` // limit to events with a magnitude smaller than the specified maximum.
49+
OrderBy string `schema:"orderby"` // order the result by time or magnitude with the following possibilities: time, time-asc, magnitude, magnitude-asc
5050

5151
// supported optionals
52-
Latitude float64 `schema:"latitude"`
53-
Longitude float64 `schema:"longitude"`
54-
MinRadius float64 `schema:"minradius"`
55-
MaxRadius float64 `schema:"maxradius"`
56-
PublicID string `schema:"eventid"` // select a specific event by ID; event identifiers are data center specific.
57-
UpdatedAfter Time `schema:"updatedafter"` // Limit to events updated after the specified time.
58-
Format string `schema:"format"`
59-
NoData int `schema:"nodata"` // Select status code for “no data”, either ‘204’ (default) or ‘404’.
60-
EventType string `schema:"eventtype"`
61-
eventTypeSlice []interface{} // interal use only. holds matched eventtypes
62-
}
63-
64-
type Time struct {
65-
time.Time
52+
Latitude float64 `schema:"latitude"`
53+
Longitude float64 `schema:"longitude"`
54+
MinRadius float64 `schema:"minradius"`
55+
MaxRadius float64 `schema:"maxradius"`
56+
PublicID string `schema:"eventid"` // select a specific event by ID; event identifiers are data center specific.
57+
UpdatedAfter fdsn.WsDateTime `schema:"updatedafter"` // Limit to events updated after the specified time.
58+
Format string `schema:"format"`
59+
NoData int `schema:"nodata"` // Select status code for “no data”, either ‘204’ (default) or ‘404’.
60+
EventType string `schema:"eventtype"`
61+
eventTypeSlice []interface{} // interal use only. holds matched eventtypes
6662
}
6763

6864
var fdsnEventWadlFile []byte
@@ -230,11 +226,11 @@ func parseEventV1(v url.Values) (fdsnEventV1, error) {
230226
}
231227

232228
if e.Format != "xml" && e.Format != "text" {
233-
return e, errors.New("Invalid format.")
229+
return e, errors.New("invalid format")
234230
}
235231

236232
if e.NoData != 204 && e.NoData != 404 {
237-
return e, errors.New("nodata must be 204 or 404.")
233+
return e, errors.New("nodata must be 204 or 404")
238234
}
239235

240236
// geometry bounds checking
@@ -276,17 +272,17 @@ func parseEventV1(v url.Values) (fdsnEventV1, error) {
276272
}
277273

278274
if e.MaxRadius < 0 || e.MaxRadius > 180.0 {
279-
err = fmt.Errorf("invalid maxradius value.")
275+
err = fmt.Errorf("invalid maxradius value")
280276
return e, err
281277
}
282278

283279
if e.MinRadius < 0 || e.MinRadius > 180.0 {
284-
err = fmt.Errorf("invalid minradius value.")
280+
err = fmt.Errorf("invalid minradius value")
285281
return e, err
286282
}
287283

288284
if e.MinRadius > e.MaxRadius {
289-
err = fmt.Errorf("minradius or maxradius range error.")
285+
err = fmt.Errorf("minradius or maxradius range error")
290286
return e, err
291287
}
292288
}
@@ -451,19 +447,19 @@ func (e *fdsnEventV1) filter() (q string, args []interface{}) {
451447
i++
452448
}
453449

454-
if !e.StartTime.Time.IsZero() {
450+
if !e.StartTime.IsZero() {
455451
q = fmt.Sprintf("%s origintime >= $%d AND", q, i)
456452
args = append(args, e.StartTime.Time)
457453
i++
458454
}
459455

460-
if !e.EndTime.Time.IsZero() {
456+
if !e.EndTime.IsZero() {
461457
q = fmt.Sprintf("%s origintime <= $%d AND", q, i)
462458
args = append(args, e.EndTime.Time)
463459
i++
464460
}
465461

466-
if !e.UpdatedAfter.Time.IsZero() {
462+
if !e.UpdatedAfter.IsZero() {
467463
q = fmt.Sprintf("%s modificationtime >= $%d AND", q, i)
468464
args = append(args, e.UpdatedAfter.Time)
469465
i++
@@ -531,7 +527,7 @@ func fdsnEventV1Handler(r *http.Request, h http.Header, b *bytes.Buffer) error {
531527
if err != nil {
532528
return fdsnError{StatusError: weft.StatusError{Code: http.StatusInternalServerError, Err: err}, url: r.URL.String(), timestamp: tm}
533529
}
534-
defer rows.Close()
530+
defer func() { _ = rows.Close() }()
535531

536532
b.WriteString(`<?xml version="1.0" encoding="UTF-8"?>
537533
<q:quakeml xmlns:q="http://quakeml.org/xmlns/quakeml/1.2" xmlns="http://quakeml.org/xmlns/bed/1.2">
@@ -556,7 +552,7 @@ func fdsnEventV1Handler(r *http.Request, h http.Header, b *bytes.Buffer) error {
556552
if err != nil {
557553
return fdsnError{StatusError: weft.StatusError{Code: http.StatusInternalServerError, Err: err}, url: r.URL.String(), timestamp: tm}
558554
}
559-
defer rows.Close()
555+
defer func() { _ = rows.Close() }()
560556

561557
b.WriteString("#EventID | Time | Latitude | Longitude | Depth/km | Author | Catalog | Contributor | ContributorID | MagType | Magnitude | MagAuthor | EventLocationName | EventType\n")
562558

@@ -572,7 +568,7 @@ func fdsnEventV1Handler(r *http.Request, h http.Header, b *bytes.Buffer) error {
572568
if l, err := wgs84.ClosestNZ(latitude, longitude); err == nil {
573569
loc = l.Description()
574570
}
575-
s := fmt.Sprintf("%s|%s|%.3f|%.3f|%.1f|GNS|GNS|GNS|%s|%s|%.1f|GNS|%s|%s\n", eventID, tm.UTC().Format(time.RFC3339Nano), latitude, longitude, depth, eventID, magType, magnitude, loc, eventType)
571+
s := fmt.Sprintf("%s|%s|%.3f|%.3f|%.1f|GNS|GNS|GNS|%s|%s|%.1f|GNS|%s|%s\n", eventID, tm.Format(fdsn.WsTimeFormat), latitude, longitude, depth, eventID, magType, magnitude, loc, eventType)
576572
b.WriteString(s)
577573
}
578574

@@ -591,7 +587,7 @@ func fdsnEventVersion(r *http.Request, h http.Header, b *bytes.Buffer) error {
591587
}
592588

593589
h.Set("Content-Type", "text/plain")
594-
_, err = b.WriteString("1.1")
590+
_, err = b.WriteString(eventVersion)
595591

596592
return err
597593
}

cmd/fdsn-ws/fdsn_event_test.go

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import (
66
"net/url"
77
"reflect"
88
"testing"
9-
"time"
9+
10+
"github.com/GeoNet/fdsn/internal/fdsn"
1011
)
1112

1213
func TestEventV1Query(t *testing.T) {
@@ -54,13 +55,11 @@ func TestEventV1Query(t *testing.T) {
5455
EventType: "*", // default value
5556
}
5657

57-
ex.StartTime.Time, err = time.Parse(time.RFC3339Nano, "2015-01-12T12:12:12.000000000Z")
58-
if err != nil {
58+
if err = ex.StartTime.UnmarshalText([]byte("2015-01-12T12:12:12.000000")); err != nil {
5959
t.Error(err)
6060
}
6161

62-
ex.EndTime.Time, err = time.Parse(time.RFC3339Nano, "2015-02-12T12:12:12.000000000Z")
63-
if err != nil {
62+
if err = ex.EndTime.UnmarshalText([]byte("2015-02-12T12:12:12.000000")); err != nil {
6463
t.Error(err)
6564
}
6665

@@ -103,26 +102,6 @@ func TestEventV1OrderBy(t *testing.T) {
103102
}
104103
}
105104

106-
func TestTimeParse(t *testing.T) {
107-
var tm Time
108-
109-
if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12.999999")); err != nil {
110-
t.Error(err)
111-
}
112-
113-
if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12")); err != nil {
114-
t.Error(err)
115-
}
116-
117-
if err := tm.UnmarshalText([]byte("2015-01-12")); err != nil {
118-
t.Error(err)
119-
}
120-
121-
if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12.invalid")); err == nil {
122-
t.Error("expected an error for invalid time string.")
123-
}
124-
}
125-
126105
func TestEventQuery(t *testing.T) {
127106
setup(t)
128107
defer teardown()
@@ -334,14 +313,16 @@ func TestEventAbbreviations(t *testing.T) {
334313
t.Errorf("expected 2.2 for maxmag %f.\n", e.MaxMagnitude)
335314
}
336315

337-
tm, _ := time.Parse(time.RFC3339Nano, "2016-09-04T00:00:00.000000000Z")
338-
if !e.StartTime.Equal(tm) {
339-
t.Errorf("start parameter error: %s", e.StartTime.Format(time.RFC3339Nano))
316+
var tm fdsn.WsDateTime
317+
318+
_ = tm.UnmarshalText([]byte("2016-09-04T00:00:00.000000"))
319+
if !e.StartTime.Equal(tm.Time) {
320+
t.Errorf("start parameter error: %v", e.StartTime)
340321
}
341322

342-
tm, _ = time.Parse(time.RFC3339Nano, "2016-09-05T00:00:00.000000000Z")
343-
if !e.EndTime.Equal(tm) {
344-
t.Errorf("end parameter error: %s", e.EndTime.Format(time.RFC3339Nano))
323+
_ = tm.UnmarshalText([]byte("2016-09-05T00:00:00"))
324+
if !e.EndTime.Equal(tm.Time) {
325+
t.Errorf("end parameter error: %v", e.EndTime)
345326
}
346327
}
347328

0 commit comments

Comments
 (0)