diff --git a/cmd/fdsn-ws/etc/fdsn-station-test.xml b/cmd/fdsn-ws/etc/fdsn-station-test.xml
index c5670fa1..e1904f42 100644
--- a/cmd/fdsn-ws/etc/fdsn-station-test.xml
+++ b/cmd/fdsn-ws/etc/fdsn-station-test.xml
@@ -1 +1 @@
-GeoNetWEL(GNS_Test)Delta2017-09-26T02:37:17New Zealand National Seismograph Network22002Private seismograph sitesLocation is given in NZGD2000-38.62769176.12006420Aratiatia Landcorp Farm9 km north of Taupo2007-05-20T23:00:0099Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.1200642000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/35412007-05-20T21:00:012011-03-06T22:00:007.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.12006420000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/35412007-05-20T21:00:012011-03-06T22:00:007.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.120064200900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/35412007-05-20T21:00:012011-03-06T22:00:007.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.1200642000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/33392011-03-06T22:00:012011-06-20T04:00:007.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.12006420000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/33392011-03-06T22:00:012011-06-20T04:00:007.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.120064200900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/33392011-03-06T22:00:012011-06-20T04:00:007.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.1200642000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/35412011-06-20T04:00:017.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.12006420000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/35412011-06-20T04:00:017.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.120064200900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00DataloggerQ330QuanterraQ330/35412011-06-20T04:00:017.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Hawke's Bay regional seismic networkLocation is given in WGS84-39.2631176.9959270Aropaoanui28 km north of Napier2010-03-11T00:00:0066Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.995927000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00DataloggerQ330QuanterraQ330/322362010-03-11T21:15:012012-01-19T22:29:011.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.9959270000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00DataloggerQ330QuanterraQ330/322362010-03-11T21:15:012012-01-19T22:29:011.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.99592700900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00DataloggerQ330QuanterraQ330/322362010-03-11T21:15:012012-01-19T22:29:011.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.995927000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00DataloggerQ330QuanterraQ330/336162012-01-19T22:30:011.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.9959270000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00DataloggerQ330QuanterraQ330/336162012-01-19T22:30:011.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.99592700900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00DataloggerQ330QuanterraQ330/336162012-01-19T22:30:011.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115
\ No newline at end of file
+GeoNetWEL(GNS_Test)Delta2017-09-26T02:37:17ZNew Zealand National Seismograph Network22002Private seismograph sitesLocation is given in NZGD2000-38.62769176.12006420Aratiatia Landcorp Farm9 km north of Taupo2007-05-20T23:00:00Z99Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.1200642000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/35412007-05-20T21:00:01Z2011-03-06T22:00:00Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.12006420000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/35412007-05-20T21:00:01Z2011-03-06T22:00:00Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.120064200900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/35412007-05-20T21:00:01Z2011-03-06T22:00:00Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.1200642000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/33392011-03-06T22:00:01Z2011-06-20T04:00:00Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.12006420000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/33392011-03-06T22:00:01Z2011-06-20T04:00:00Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.120064200900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/33392011-03-06T22:00:01Z2011-06-20T04:00:00Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.1200642000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/35412011-06-20T04:00:01Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.12006420000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/35412011-06-20T04:00:01Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from external GPS measurementLocation is given in NZGD2000Sensor orientation not known-38.62769176.120064200900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerL4C-3DSercelL4C-3D29892007-05-20T23:00:00ZDataloggerQ330QuanterraQ330/35412011-06-20T04:00:01Z7.457472512e+0715m/scountm/sVLAPLACE (RADIANS/SECOND)0.9995555150145211150000-4.20974.6644-4.2097-4.6644177.815VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Hawke's Bay regional seismic networkLocation is given in WGS84-39.2631176.9959270Aropaoanui28 km north of Napier2010-03-11T00:00:00Z66Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.995927000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00ZDataloggerQ330QuanterraQ330/322362010-03-11T21:15:01Z2012-01-19T22:29:01Z1.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.9959270000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00ZDataloggerQ330QuanterraQ330/322362010-03-11T21:15:01Z2012-01-19T22:29:01Z1.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.99592700900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00ZDataloggerQ330QuanterraQ330/322362010-03-11T21:15:01Z2012-01-19T22:29:01Z1.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.995927000-90CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00ZDataloggerQ330QuanterraQ330/336162012-01-19T22:30:01Z1.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.9959270000CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00ZDataloggerQ330QuanterraQ330/336162012-01-19T22:30:01Z1.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115Location estimated from internal GPS clockLocation is given in WGS84Sensor orientation not known-39.2631176.99592700900CONTINUOUSGEOPHYSICAL1001001Steim20.0001Short Period SeismometerLE-3DliteMkIILennartzLE-3DliteMkIII-06522010-03-11T21:16:00ZDataloggerQ330QuanterraQ330/336162012-01-19T22:30:01Z1.6777216e+0815m/scountm/sVLAPLACE (RADIANS/SECOND)1.00007590629430815000000-4.4444.444-4.444-4.444-1.083040015VcountDIGITAL1001000419430.415countcountNONE1.3154932e-110.000150106530.0133968140.164429240.568809410.51738348-0.26083604-0.122032930.25718129-0.20290260.0707588050.038796662-0.114313470.13547966-0.111447460.067054813-0.019271235-0.0209312860.047680563-0.0593382880.057579308-0.0462333070.029777146-0.01248294-0.00236607510.012788211-0.0184698220.018797255-0.0171386550.012781987-0.00767578680.0032551587-8.9475628e-05-0.00177875750.0025960431-0.00266616850.002307403-0.00177051550.0012186428-0.000746049220.00039217516-0.000158366472.437801e-053.807573e-05-5.6180479e-055.152771e-05-3.8564693e-052.5302859e-05-1.512465e-058.7397951e-06-4.6481172e-061.3762756e-067.042064e-072.2418734e-07-1.2510258e-061.0667707e-072.6428765e-073.2266382e-07-8.0741625e-08-1.0990485e-07-3.3252027e-081.3885057e-081.0562748e-082.5779114e-09-7.0186227e-101001000115
\ No newline at end of file
diff --git a/cmd/fdsn-ws/fdsn_dataselect.go b/cmd/fdsn-ws/fdsn_dataselect.go
index 22fce08e..492b6b16 100644
--- a/cmd/fdsn-ws/fdsn_dataselect.go
+++ b/cmd/fdsn-ws/fdsn_dataselect.go
@@ -77,7 +77,7 @@ func fdsnDataMetricsV1Handler(r *http.Request, h http.Header, b *bytes.Buffer) e
switch r.Method {
case "POST":
- defer r.Body.Close()
+ defer func() { _ = r.Body.Close() }()
if err := fdsn.ParseDataSelectPost(r.Body, ¶ms); err != nil {
return fdsnError{StatusError: weft.StatusError{Code: http.StatusBadRequest, Err: err}, url: r.URL.String(), timestamp: tm}
}
@@ -144,7 +144,7 @@ func fdsnDataselectV1Handler(r *http.Request, w http.ResponseWriter) (int64, err
switch r.Method {
case "POST":
- defer r.Body.Close()
+ defer func() { _ = r.Body.Close() }()
if err := fdsn.ParseDataSelectPost(r.Body, ¶ms); err != nil {
return 0, fdsnError{StatusError: weft.StatusError{Code: http.StatusBadRequest, Err: err}, url: r.URL.String(), timestamp: tm}
}
@@ -181,7 +181,7 @@ func fdsnDataselectV1Handler(r *http.Request, w http.ResponseWriter) (int64, err
for _, v := range params {
//flick gtHalfHour to true if the request is longer than half an hour
- gtHalfHour = gtHalfHour || v.EndTime.Sub(time.Time(v.StartTime.Time)) > time.Minute*30
+ gtHalfHour = gtHalfHour || v.EndTime.Sub(v.StartTime.Time) > time.Minute*30
d, err := v.Regexp()
if err != nil {
@@ -303,7 +303,7 @@ func fdsnDataselectVersion(r *http.Request, h http.Header, b *bytes.Buffer) erro
}
h.Set("Content-Type", "text/plain")
- _, err = b.WriteString("1.1")
+ _, err = b.WriteString(dataselectVersion)
return err
}
diff --git a/cmd/fdsn-ws/fdsn_event.go b/cmd/fdsn-ws/fdsn_event.go
index 175ec030..bd49f486 100644
--- a/cmd/fdsn-ws/fdsn_event.go
+++ b/cmd/fdsn-ws/fdsn_event.go
@@ -36,33 +36,29 @@ var eventAbbreviations = map[string]string{
// supported query parameters for the event service from http://www.fdsn.org/webservices/FDSN-WS-Specifications-1.1.pdf
type fdsnEventV1 struct {
// required
- StartTime Time `schema:"starttime"` // limit to events on or after the specified start time.
- EndTime Time `schema:"endtime"` // limit to events on or before the specified end time.
- MinLatitude float64 `schema:"minlatitude"` // limit to events with a latitude larger than or equal to the specified minimum.
- MaxLatitude float64 `schema:"maxlatitude"` // limit to events with a latitude smaller than or equal to the specified maximum.
- MinLongitude float64 `schema:"minlongitude"` // limit to events with a longitude larger than or equal to the specified minimum.
- MaxLongitude float64 `schema:"maxlongitude"` // limit to events with a longitude smaller than or equal to the specified maximum.
- MinDepth float64 `schema:"mindepth"` // limit to events with depth more than the specified minimum.
- MaxDepth float64 `schema:"maxdepth"` // limit to events with depth less than the specified maximum.
- MinMagnitude float64 `schema:"minmagnitude"` // limit to events with a magnitude larger than the specified minimum.
- MaxMagnitude float64 `schema:"maxmagnitude"` // limit to events with a magnitude smaller than the specified maximum.
- OrderBy string `schema:"orderby"` // order the result by time or magnitude with the following possibilities: time, time-asc, magnitude, magnitude-asc
+ StartTime fdsn.WsDateTime `schema:"starttime"` // limit to events on or after the specified start time.
+ EndTime fdsn.WsDateTime `schema:"endtime"` // limit to events on or before the specified end time.
+ MinLatitude float64 `schema:"minlatitude"` // limit to events with a latitude larger than or equal to the specified minimum.
+ MaxLatitude float64 `schema:"maxlatitude"` // limit to events with a latitude smaller than or equal to the specified maximum.
+ MinLongitude float64 `schema:"minlongitude"` // limit to events with a longitude larger than or equal to the specified minimum.
+ MaxLongitude float64 `schema:"maxlongitude"` // limit to events with a longitude smaller than or equal to the specified maximum.
+ MinDepth float64 `schema:"mindepth"` // limit to events with depth more than the specified minimum.
+ MaxDepth float64 `schema:"maxdepth"` // limit to events with depth less than the specified maximum.
+ MinMagnitude float64 `schema:"minmagnitude"` // limit to events with a magnitude larger than the specified minimum.
+ MaxMagnitude float64 `schema:"maxmagnitude"` // limit to events with a magnitude smaller than the specified maximum.
+ OrderBy string `schema:"orderby"` // order the result by time or magnitude with the following possibilities: time, time-asc, magnitude, magnitude-asc
// supported optionals
- Latitude float64 `schema:"latitude"`
- Longitude float64 `schema:"longitude"`
- MinRadius float64 `schema:"minradius"`
- MaxRadius float64 `schema:"maxradius"`
- PublicID string `schema:"eventid"` // select a specific event by ID; event identifiers are data center specific.
- UpdatedAfter Time `schema:"updatedafter"` // Limit to events updated after the specified time.
- Format string `schema:"format"`
- NoData int `schema:"nodata"` // Select status code for “no data”, either ‘204’ (default) or ‘404’.
- EventType string `schema:"eventtype"`
- eventTypeSlice []interface{} // interal use only. holds matched eventtypes
-}
-
-type Time struct {
- time.Time
+ Latitude float64 `schema:"latitude"`
+ Longitude float64 `schema:"longitude"`
+ MinRadius float64 `schema:"minradius"`
+ MaxRadius float64 `schema:"maxradius"`
+ PublicID string `schema:"eventid"` // select a specific event by ID; event identifiers are data center specific.
+ UpdatedAfter fdsn.WsDateTime `schema:"updatedafter"` // Limit to events updated after the specified time.
+ Format string `schema:"format"`
+ NoData int `schema:"nodata"` // Select status code for “no data”, either ‘204’ (default) or ‘404’.
+ EventType string `schema:"eventtype"`
+ eventTypeSlice []interface{} // interal use only. holds matched eventtypes
}
var fdsnEventWadlFile []byte
@@ -230,11 +226,11 @@ func parseEventV1(v url.Values) (fdsnEventV1, error) {
}
if e.Format != "xml" && e.Format != "text" {
- return e, errors.New("Invalid format.")
+ return e, errors.New("invalid format")
}
if e.NoData != 204 && e.NoData != 404 {
- return e, errors.New("nodata must be 204 or 404.")
+ return e, errors.New("nodata must be 204 or 404")
}
// geometry bounds checking
@@ -276,17 +272,17 @@ func parseEventV1(v url.Values) (fdsnEventV1, error) {
}
if e.MaxRadius < 0 || e.MaxRadius > 180.0 {
- err = fmt.Errorf("invalid maxradius value.")
+ err = fmt.Errorf("invalid maxradius value")
return e, err
}
if e.MinRadius < 0 || e.MinRadius > 180.0 {
- err = fmt.Errorf("invalid minradius value.")
+ err = fmt.Errorf("invalid minradius value")
return e, err
}
if e.MinRadius > e.MaxRadius {
- err = fmt.Errorf("minradius or maxradius range error.")
+ err = fmt.Errorf("minradius or maxradius range error")
return e, err
}
}
@@ -451,19 +447,19 @@ func (e *fdsnEventV1) filter() (q string, args []interface{}) {
i++
}
- if !e.StartTime.Time.IsZero() {
+ if !e.StartTime.IsZero() {
q = fmt.Sprintf("%s origintime >= $%d AND", q, i)
args = append(args, e.StartTime.Time)
i++
}
- if !e.EndTime.Time.IsZero() {
+ if !e.EndTime.IsZero() {
q = fmt.Sprintf("%s origintime <= $%d AND", q, i)
args = append(args, e.EndTime.Time)
i++
}
- if !e.UpdatedAfter.Time.IsZero() {
+ if !e.UpdatedAfter.IsZero() {
q = fmt.Sprintf("%s modificationtime >= $%d AND", q, i)
args = append(args, e.UpdatedAfter.Time)
i++
@@ -531,7 +527,7 @@ func fdsnEventV1Handler(r *http.Request, h http.Header, b *bytes.Buffer) error {
if err != nil {
return fdsnError{StatusError: weft.StatusError{Code: http.StatusInternalServerError, Err: err}, url: r.URL.String(), timestamp: tm}
}
- defer rows.Close()
+ defer func() { _ = rows.Close() }()
b.WriteString(`
@@ -556,7 +552,7 @@ func fdsnEventV1Handler(r *http.Request, h http.Header, b *bytes.Buffer) error {
if err != nil {
return fdsnError{StatusError: weft.StatusError{Code: http.StatusInternalServerError, Err: err}, url: r.URL.String(), timestamp: tm}
}
- defer rows.Close()
+ defer func() { _ = rows.Close() }()
b.WriteString("#EventID | Time | Latitude | Longitude | Depth/km | Author | Catalog | Contributor | ContributorID | MagType | Magnitude | MagAuthor | EventLocationName | EventType\n")
@@ -572,7 +568,7 @@ func fdsnEventV1Handler(r *http.Request, h http.Header, b *bytes.Buffer) error {
if l, err := wgs84.ClosestNZ(latitude, longitude); err == nil {
loc = l.Description()
}
- 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)
+ s := fmt.Sprintf("%s|%s|%.3f|%.3f|%.1f|GNS|GNS|GNS|%s|%s|%.1f|GNS|%s|%s\n", eventID, tm.UTC().Format(fdsn.WsMarshalTimeFormat), latitude, longitude, depth, eventID, magType, magnitude, loc, eventType)
b.WriteString(s)
}
@@ -591,7 +587,7 @@ func fdsnEventVersion(r *http.Request, h http.Header, b *bytes.Buffer) error {
}
h.Set("Content-Type", "text/plain")
- _, err = b.WriteString("1.1")
+ _, err = b.WriteString(eventVersion)
return err
}
diff --git a/cmd/fdsn-ws/fdsn_event_test.go b/cmd/fdsn-ws/fdsn_event_test.go
index 4f43e628..781d02a7 100644
--- a/cmd/fdsn-ws/fdsn_event_test.go
+++ b/cmd/fdsn-ws/fdsn_event_test.go
@@ -6,7 +6,8 @@ import (
"net/url"
"reflect"
"testing"
- "time"
+
+ "github.com/GeoNet/fdsn/internal/fdsn"
)
func TestEventV1Query(t *testing.T) {
@@ -54,13 +55,11 @@ func TestEventV1Query(t *testing.T) {
EventType: "*", // default value
}
- ex.StartTime.Time, err = time.Parse(time.RFC3339Nano, "2015-01-12T12:12:12.000000000Z")
- if err != nil {
+ if err = ex.StartTime.UnmarshalText([]byte("2015-01-12T12:12:12.000000")); err != nil {
t.Error(err)
}
- ex.EndTime.Time, err = time.Parse(time.RFC3339Nano, "2015-02-12T12:12:12.000000000Z")
- if err != nil {
+ if err = ex.EndTime.UnmarshalText([]byte("2015-02-12T12:12:12.000000")); err != nil {
t.Error(err)
}
@@ -103,26 +102,6 @@ func TestEventV1OrderBy(t *testing.T) {
}
}
-func TestTimeParse(t *testing.T) {
- var tm Time
-
- if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12.999999")); err != nil {
- t.Error(err)
- }
-
- if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12")); err != nil {
- t.Error(err)
- }
-
- if err := tm.UnmarshalText([]byte("2015-01-12")); err != nil {
- t.Error(err)
- }
-
- if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12.invalid")); err == nil {
- t.Error("expected an error for invalid time string.")
- }
-}
-
func TestEventQuery(t *testing.T) {
setup(t)
defer teardown()
@@ -334,14 +313,16 @@ func TestEventAbbreviations(t *testing.T) {
t.Errorf("expected 2.2 for maxmag %f.\n", e.MaxMagnitude)
}
- tm, _ := time.Parse(time.RFC3339Nano, "2016-09-04T00:00:00.000000000Z")
- if !e.StartTime.Equal(tm) {
- t.Errorf("start parameter error: %s", e.StartTime.Format(time.RFC3339Nano))
+ var tm fdsn.WsDateTime
+
+ _ = tm.UnmarshalText([]byte("2016-09-04T00:00:00.000000"))
+ if !e.StartTime.Equal(tm.Time) {
+ t.Errorf("start parameter error: %v", e.StartTime)
}
- tm, _ = time.Parse(time.RFC3339Nano, "2016-09-05T00:00:00.000000000Z")
- if !e.EndTime.Equal(tm) {
- t.Errorf("end parameter error: %s", e.EndTime.Format(time.RFC3339Nano))
+ _ = tm.UnmarshalText([]byte("2016-09-05T00:00:00"))
+ if !e.EndTime.Equal(tm.Time) {
+ t.Errorf("end parameter error: %v", e.EndTime)
}
}
diff --git a/cmd/fdsn-ws/fdsn_station.go b/cmd/fdsn-ws/fdsn_station.go
index b44221fb..4cd5c2e7 100644
--- a/cmd/fdsn-ws/fdsn_station.go
+++ b/cmd/fdsn-ws/fdsn_station.go
@@ -59,32 +59,32 @@ var stationAbbreviations = map[string]string{
// supported query parameters for the station service from http://www.fdsn.org/webservices/FDSN-WS-Specifications-1.1.pdf
type fdsnStationV1Parm struct {
- StartTime Time `schema:"starttime"` // Limit to metadata epochs starting on or after the specified start time.
- EndTime Time `schema:"endtime"` // Limit to metadata epochs ending on or before the specified end time.
- Network []string `schema:"network"` // Select one or more network codes. Can be SEED network codes or data center defined codes. Multiple codes are comma-separated.
- Station []string `schema:"station"` // Select one or more SEED station codes. Multiple codes are comma-separated.
- Location []string `schema:"location"` // Select one or more SEED location identifiers. Multiple identifiers are comma- separated. As a special case “--“ (two dashes) will be translated to a string of two space characters to match blank location IDs.
- Channel []string `schema:"channel"` // Select one or more SEED channel codes. Multiple codes are comma-separated.
- MinLatitude float64 `schema:"minlatitude"` // Limit to stations with a latitude larger than or equal to the specified minimum.
- MaxLatitude float64 `schema:"maxlatitude"` // Limit to stations with a latitude smaller than or equal to the specified maximum.
- MinLongitude float64 `schema:"minlongitude"` // Limit to stations with a longitude larger than or equal to the specified minimum.
- MaxLongitude float64 `schema:"maxlongitude"` // Limit to stations with a longitude smaller than or equal to the specified maximum.
- Level string `schema:"level"` // Specify the level of detail for the results.
- Format string `schema:"format"` // Format of result. Either "xml" or "text".
- IncludeAvailability bool `schema:"includeavailability"`
- IncludeRestricted bool `schema:"includerestricted"`
- MatchTimeSeries bool `schema:"matchtimeseries"`
- Latitude float64 `schema:"latitude"`
- Longitude float64 `schema:"longitude"`
- MinRadius float64 `schema:"minradius"`
- MaxRadius float64 `schema:"maxradius"`
- StartBefore Time `schema:"startbefore"`
- StartAfter Time `schema:"startafter"`
- EndBefore Time `schema:"endbefore"`
- EndAfter Time `schema:"endafter"`
- NoData int `schema:"nodata"` // Select status code for “no data”, either ‘204’ (default) or ‘404’.
- startMode int // BEFORE, ONBEFOREEND, AFTER
- endMode int // BEFORE, ONAFTERSTART, AFTER
+ StartTime fdsn.WsDateTime `schema:"starttime"` // Limit to metadata epochs starting on or after the specified start time.
+ EndTime fdsn.WsDateTime `schema:"endtime"` // Limit to metadata epochs ending on or before the specified end time.
+ Network []string `schema:"network"` // Select one or more network codes. Can be SEED network codes or data center defined codes. Multiple codes are comma-separated.
+ Station []string `schema:"station"` // Select one or more SEED station codes. Multiple codes are comma-separated.
+ Location []string `schema:"location"` // Select one or more SEED location identifiers. Multiple identifiers are comma- separated. As a special case “--“ (two dashes) will be translated to a string of two space characters to match blank location IDs.
+ Channel []string `schema:"channel"` // Select one or more SEED channel codes. Multiple codes are comma-separated.
+ MinLatitude float64 `schema:"minlatitude"` // Limit to stations with a latitude larger than or equal to the specified minimum.
+ MaxLatitude float64 `schema:"maxlatitude"` // Limit to stations with a latitude smaller than or equal to the specified maximum.
+ MinLongitude float64 `schema:"minlongitude"` // Limit to stations with a longitude larger than or equal to the specified minimum.
+ MaxLongitude float64 `schema:"maxlongitude"` // Limit to stations with a longitude smaller than or equal to the specified maximum.
+ Level string `schema:"level"` // Specify the level of detail for the results.
+ Format string `schema:"format"` // Format of result. Either "xml" or "text".
+ IncludeAvailability bool `schema:"includeavailability"`
+ IncludeRestricted bool `schema:"includerestricted"`
+ MatchTimeSeries bool `schema:"matchtimeseries"`
+ Latitude float64 `schema:"latitude"`
+ Longitude float64 `schema:"longitude"`
+ MinRadius float64 `schema:"minradius"`
+ MaxRadius float64 `schema:"maxradius"`
+ StartBefore fdsn.WsDateTime `schema:"startbefore"`
+ StartAfter fdsn.WsDateTime `schema:"startafter"`
+ EndBefore fdsn.WsDateTime `schema:"endbefore"`
+ EndAfter fdsn.WsDateTime `schema:"endafter"`
+ NoData int `schema:"nodata"` // Select status code for “no data”, either ‘204’ (default) or ‘404’.
+ startMode int // BEFORE, ONBEFOREEND, AFTER
+ endMode int // BEFORE, ONAFTERSTART, AFTER
}
type fdsnStationV1Search struct {
@@ -107,7 +107,7 @@ var (
fdsnStationIndex []byte
fdsnStations fdsnStationObj
emptyDateTime = time.Date(9999, 1, 1, 0, 0, 0, 0, time.UTC)
- errNotModified = fmt.Errorf("Not modified.")
+ errNotModified = fmt.Errorf("not modified")
stationXMLBucket string
stationXMLKey string
)
@@ -145,8 +145,7 @@ func initStationXML() {
if s, err = os.Stat("etc/" + stationXMLKey); err == nil {
log.Println("Loading fdsn station xml file ", "etc/"+stationXMLKey)
var f *os.File
- if f, err = os.Open("etc/" + stationXMLKey); err == nil {
-
+ if f, err = os.Open("etc/" + stationXMLKey); err == nil { // nolint:gosec
if _, err = io.Copy(by, f); err != nil {
log.Println("Error copying station xml file", err)
}
@@ -243,12 +242,12 @@ func parseStationV1(v url.Values) (fdsnStationV1Search, error) {
Level: "station",
Format: "xml",
IncludeRestricted: true,
- StartTime: Time{zeroDateTime}, // 0001-01-01T00:00:00
- EndTime: Time{emptyDateTime}, // 9999-01-01T00:00:00
- StartBefore: Time{emptyDateTime}, // 9999-01-01T00:00:00
- EndBefore: Time{emptyDateTime}, // 9999-01-01T00:00:00
- StartAfter: Time{emptyDateTime}, // 9999-01-01T00:00:00
- EndAfter: Time{emptyDateTime}, // 9999-01-01T00:00:00
+ StartTime: fdsn.ZeroWsDateTime, // 0001-01-01T00:00:00
+ EndTime: fdsn.EmptyWsDateTime, // 9999-01-01T00:00:00
+ StartBefore: fdsn.EmptyWsDateTime, // 9999-01-01T00:00:00
+ EndBefore: fdsn.EmptyWsDateTime, // 9999-01-01T00:00:00
+ StartAfter: fdsn.EmptyWsDateTime, // 9999-01-01T00:00:00
+ EndAfter: fdsn.EmptyWsDateTime, // 9999-01-01T00:00:00
Latitude: math.MaxFloat64,
Longitude: math.MaxFloat64,
MinRadius: 0.0,
@@ -289,16 +288,16 @@ func parseStationV1(v url.Values) (fdsnStationV1Search, error) {
}
count := 0
- if p.StartTime.Time != zeroDateTime {
+ if p.StartTime != fdsn.ZeroWsDateTime {
count++
p.startMode = ONBEFOREEND
}
- if p.StartAfter.Time != emptyDateTime {
+ if p.StartAfter != fdsn.EmptyWsDateTime {
count++
p.startMode = AFTER
p.StartTime = p.StartAfter
}
- if p.StartBefore.Time != emptyDateTime {
+ if p.StartBefore != fdsn.EmptyWsDateTime {
count++
p.startMode = BEFORE
p.StartTime = p.StartBefore
@@ -308,18 +307,18 @@ func parseStationV1(v url.Values) (fdsnStationV1Search, error) {
}
count = 0
- if p.EndTime.Time != emptyDateTime {
+ if p.EndTime != fdsn.EmptyWsDateTime {
count++
p.endMode = ONAFTERSTART
}
- if p.EndAfter.Time != emptyDateTime {
+ if p.EndAfter != fdsn.EmptyWsDateTime {
count++
p.endMode = AFTER
p.EndTime = p.EndAfter
}
- if p.EndBefore.Time != emptyDateTime {
+ if p.EndBefore != fdsn.EmptyWsDateTime {
count++
p.endMode = BEFORE
p.EndTime = p.EndBefore
@@ -438,7 +437,7 @@ func fdsnStationVersion(r *http.Request, h http.Header, b *bytes.Buffer) error {
}
h.Set("Content-Type", "text/plain")
- _, err = b.WriteString("1.2")
+ _, err = b.WriteString(stationVersion)
return err
}
@@ -573,26 +572,26 @@ func (r *FDSNStationXML) marshalText(levelVal int) *bytes.Buffer {
for n := 0; n < len(r.Network); n++ {
net := &r.Network[n]
if levelVal == STATION_LEVEL_NETWORK {
- by.WriteString(fmt.Sprintf("%s|%s|%s|%s|%d\n",
+ fmt.Fprintf(by, "%s|%s|%s|%s|%d\n",
net.Code, net.Description,
net.StartDate.MarshalFormatText(), net.EndDate.MarshalFormatText(),
- net.TotalNumberStations))
+ net.TotalNumberStations)
} else {
if levelVal == STATION_LEVEL_STATION && len(net.Station) == 0 {
// Write Network name only
- by.WriteString(fmt.Sprintf("%s|||||||\n", net.Code))
+ fmt.Fprintf(by, "%s|||||||\n", net.Code)
}
for s := 0; s < len(net.Station); s++ {
sta := &net.Station[s]
if levelVal == STATION_LEVEL_STATION {
- by.WriteString(fmt.Sprintf("%s|%s|%f|%f|%f|%s|%s|%s\n",
+ fmt.Fprintf(by, "%s|%s|%f|%f|%f|%s|%s|%s\n",
net.Code, sta.Code,
sta.Latitude.Value, sta.Longitude.Value, sta.Elevation.Value,
- sta.Site.Name, sta.StartDate.MarshalFormatText(), sta.EndDate.MarshalFormatText()))
+ sta.Site.Name, sta.StartDate.MarshalFormatText(), sta.EndDate.MarshalFormatText())
} else {
if len(sta.Channel) == 0 {
// Write Station name only
- by.WriteString(fmt.Sprintf("%s|%s|||||||||||||||\n", net.Code, sta.Code))
+ fmt.Fprintf(by, "%s|%s|||||||||||||||\n", net.Code, sta.Code)
}
for c := 0; c < len(sta.Channel); c++ {
cha := &sta.Channel[c]
@@ -612,7 +611,7 @@ func (r *FDSNStationXML) marshalText(levelVal int) *bytes.Buffer {
}
}
- by.WriteString(fmt.Sprintf("%s|%s|%s|%s|%f|%f|%f|%f|%f|%f|%s|%s|%s|%s|%f|%s|%s\n",
+ fmt.Fprintf(by, "%s|%s|%s|%s|%f|%f|%f|%f|%f|%f|%s|%s|%s|%s|%f|%s|%s\n",
net.Code, sta.Code, cha.LocationCode, cha.Code,
cha.Latitude.Value, cha.Longitude.Value, cha.Elevation.Value,
cha.Depth.Value, cha.Azimuth.Value, cha.Dip.Value,
@@ -621,7 +620,7 @@ func (r *FDSNStationXML) marshalText(levelVal int) *bytes.Buffer {
frequency,
unitsName,
cha.SampleRate.Value,
- cha.StartDate.MarshalFormatText(), cha.EndDate.MarshalFormatText()))
+ cha.StartDate.MarshalFormatText(), cha.EndDate.MarshalFormatText())
}
}
@@ -799,35 +798,35 @@ func (v fdsnStationV1Search) validStartEnd(start, end time.Time, level int) bool
return true
}
// For start/end, the "no-value" could be "0001-01-01T00:00:00" or "9999-01-01T00:00:00"
- if v.StartTime.Time != zeroDateTime {
+ if st := v.StartTime; st != fdsn.ZeroWsDateTime {
switch v.startMode {
case ONBEFOREEND: // startTime
- if !end.IsZero() && end.Before(v.StartTime.Time) {
+ if !end.IsZero() && end.Before(st.Time) {
return false
}
case BEFORE: // startBefore
- if !start.Equal(emptyDateTime) && !start.Before(v.StartTime.Time) {
+ if !start.Equal(fdsn.EmptyWsDateTime.Time) && !start.Before(st.Time) {
return false
}
case AFTER: // startAfter
- if start.Equal(emptyDateTime) || !start.After(v.StartTime.Time) {
+ if start.Equal(emptyDateTime) || !start.After(st.Time) {
return false
}
}
}
- if v.EndTime.Time != emptyDateTime {
+ if et := v.EndTime; et != fdsn.EmptyWsDateTime {
switch v.endMode {
case ONAFTERSTART: // endTime
- if !start.Equal(emptyDateTime) && start.After(v.EndTime.Time) {
+ if !start.Equal(fdsn.EmptyWsDateTime.Time) && start.After(et.Time) {
return false
}
case BEFORE: // endBefore
- if end.IsZero() || !end.Before(v.EndTime.Time) {
+ if end.IsZero() || !end.Before(et.Time) {
return false
}
case AFTER: // endAfter
- if !end.IsZero() && !end.After(v.EndTime.Time) {
+ if !end.IsZero() && !end.After(et.Time) {
return false
}
}
@@ -895,7 +894,7 @@ func downloadStationXML(since time.Time) (by *bytes.Buffer, modified time.Time,
}
if !tp.After(since) {
- return nil, zeroDateTime, errNotModified
+ return nil, time.Time(zeroDateTime), errNotModified
}
log.Println("Downloading fdsn station xml file from S3: ", stationXMLBucket+"/"+stationXMLKey)
@@ -908,11 +907,11 @@ func downloadStationXML(since time.Time) (by *bytes.Buffer, modified time.Time,
// load from local to make debugging easier.
// s3Meta be the path to station xml
var f *os.File
- f, err = os.Open(stationXMLKey)
+ f, err = os.Open(stationXMLKey) // nolint:gosec
if err != nil {
return
}
- defer f.Close()
+ defer func() { _ = f.Close() }()
_, err = by.ReadFrom(f)
tp = time.Now()
}
@@ -1015,7 +1014,7 @@ func (d xsdDateTime) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
// For attr in an XML element
func (d xsdDateTime) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
- if time.Time(d).Equal(zeroDateTime) || time.Time(d).Equal(emptyDateTime) {
+ if time.Time(d).Equal(time.Time(zeroDateTime)) || time.Time(d).Equal(time.Time(emptyDateTime)) {
return xml.Attr{}, nil
}
@@ -1027,13 +1026,13 @@ func (d xsdDateTime) MarshalXMLAttr(name xml.Name) (xml.Attr, error) {
return xml.Attr{Name: name, Value: string(t)}, nil
}
-// For format=text - now outputs RFC3339Nano with Z timezone
+// For format=text - still marshaling into FDSN WS date-time: RFC3339 without trailing 'Z'
func (d xsdDateTime) MarshalFormatText() string {
if time.Time(d).Equal(zeroDateTime) || time.Time(d).Equal(emptyDateTime) {
return ""
}
- return time.Time(d).UTC().Format(time.RFC3339Nano)
+ return time.Time(d).UTC().Format(fdsn.WsMarshalTimeFormat)
}
func contains(slice []string, value string) bool {
diff --git a/cmd/fdsn-ws/fdsn_station_test.go b/cmd/fdsn-ws/fdsn_station_test.go
index 52dcb1f1..d254ec9a 100644
--- a/cmd/fdsn-ws/fdsn_station_test.go
+++ b/cmd/fdsn-ws/fdsn_station_test.go
@@ -376,10 +376,10 @@ func TestFormatText(t *testing.T) {
c.doFilter([]fdsnStationV1Search{e})
b := c.marshalText(STATION_LEVEL_CHANNEL)
exp := `#Network | Station | Location | Channel | Latitude | Longitude | Elevation | Depth | Azimuth | Dip | SensorDescription | Scale | ScaleFreq | ScaleUnits | SampleRate | StartTime | EndTime
-NZ|ARAZ|10|EHZ|-38.627690|176.120060|420.000000|0.000000|0.000000|-90.000000|Short Period Seismometer|74574725.120000|15.000000|m/s|100.000000|2011-06-20T04:00:01Z|
+NZ|ARAZ|10|EHZ|-38.627690|176.120060|420.000000|0.000000|0.000000|-90.000000|Short Period Seismometer|74574725.120000|15.000000|m/s|100.000000|2011-06-20T04:00:01|
`
if b.String() != exp {
- t.Errorf("Incorrect text result.")
+ t.Errorf("Incorrect text result: %s", b.String())
}
c = *fdsnStations.fdsn
@@ -391,7 +391,7 @@ NZ|ARAZ|10|EHZ|-38.627690|176.120060|420.000000|0.000000|0.000000|-90.000000|Sho
c.doFilter([]fdsnStationV1Search{e})
b = c.marshalText(STATION_LEVEL_NETWORK)
exp = `#Network | Description | StartTime | EndTime | TotalStations
-NZ|New Zealand National Seismograph Network|1884-02-01T00:00:00Z||2
+NZ|New Zealand National Seismograph Network|1884-02-01T00:00:00||2
`
if b.String() != exp {
t.Errorf("Incorrect text result.")
@@ -406,7 +406,7 @@ NZ|New Zealand National Seismograph Network|1884-02-01T00:00:00Z||2
c.doFilter([]fdsnStationV1Search{e})
b = c.marshalText(STATION_LEVEL_STATION)
exp = `#Network | Station | Latitude | Longitude | Elevation | SiteName | StartTime | EndTime
-NZ|ARAZ|-38.627690|176.120060|420.000000|Aratiatia Landcorp Farm|2007-05-20T23:00:00Z|
+NZ|ARAZ|-38.627690|176.120060|420.000000|Aratiatia Landcorp Farm|2007-05-20T23:00:00|
`
if b.String() != exp {
t.Errorf("Incorrect text result.")
@@ -460,8 +460,8 @@ NZ ARA* * EHE* 2001-01-01T00:00:00 *
NZ ARH? * EHN* 2001-01-01T00:00:00 *`
expected := strings.TrimSpace(`
#Network | Station | Latitude | Longitude | Elevation | SiteName | StartTime | EndTime
-NZ|ARAZ|-38.627690|176.120060|420.000000|Aratiatia Landcorp Farm|2007-05-20T23:00:00Z|
-NZ|ARHZ|-39.263100|176.995900|270.000000|Aropaoanui|2010-03-11T00:00:00Z|`)
+NZ|ARAZ|-38.627690|176.120060|420.000000|Aratiatia Landcorp Farm|2007-05-20T23:00:00|
+NZ|ARHZ|-39.263100|176.995900|270.000000|Aropaoanui|2010-03-11T00:00:00|`)
route := wt.Request{ID: wt.L(), URL: "/fdsnws/station/1/query", Method: "POST", PostBody: []byte(body), Content: "text/plain"}
@@ -484,12 +484,12 @@ NZ ARH? * EHN* 2001-01-01T00:00:00 *`
GeoNet
WEL(GNS_Test)
Delta
- 2017-09-26T02:37:17
-
+ 2017-09-26T02:37:17Z
+
New Zealand National Seismograph Network
2
2
-
+
Private seismograph sites
Location is given in NZGD2000
@@ -501,11 +501,11 @@ NZ ARH? * EHN* 2001-01-01T00:00:00 *`
Aratiatia Landcorp Farm
9 km north of Taupo
- 2007-05-20T23:00:00
+ 2007-05-20T23:00:00Z
9
3
-
+
Hawke's Bay regional seismic network
Location is given in WGS84
@@ -517,7 +517,7 @@ NZ ARH? * EHN* 2001-01-01T00:00:00 *`
Aropaoanui
28 km north of Napier
- 2010-03-11T00:00:00
+ 2010-03-11T00:00:00Z
6
2
diff --git a/cmd/fdsn-ws/fdsn_station_type.go b/cmd/fdsn-ws/fdsn_station_type.go
index b4059341..7c26f918 100644
--- a/cmd/fdsn-ws/fdsn_station_type.go
+++ b/cmd/fdsn-ws/fdsn_station_type.go
@@ -3,8 +3,6 @@ package main
import (
"bytes"
"time"
-
- "github.com/GeoNet/fdsn/internal/fdsn"
)
// May be one of MACLAURIN
@@ -484,32 +482,9 @@ func IntToCounterType(i int) *CounterType {
c := CounterType(i)
return &c
}
+
func _unmarshalTime(text []byte, t *time.Time) (err error) {
s := string(bytes.TrimSpace(text))
-
- // Try RFC3339Nano first (new format)
*t, err = time.Parse(time.RFC3339Nano, s)
- if err == nil {
- return nil
- }
-
- // Try legacy format for backward compatibility
- *t, err = time.Parse("2006-01-02T15:04:05.999999999", s)
- if err == nil {
- return nil
- }
-
- // Try legacy format with timezone
- *t, err = time.Parse("2006-01-02T15:04:05.999999999Z07:00", s)
return err
}
-
-// for decoder.Decode
-func (t *Time) UnmarshalText(text []byte) (err error) {
- tm, err := fdsn.UnmarshalTime(text)
- if err != nil {
- return err
- }
- t.Time = tm
- return nil
-}
diff --git a/cmd/fdsn-ws/routes_test.go b/cmd/fdsn-ws/routes_test.go
index 49b6603f..4579fd21 100644
--- a/cmd/fdsn-ws/routes_test.go
+++ b/cmd/fdsn-ws/routes_test.go
@@ -50,8 +50,12 @@ var routes = wt.Requests{
{ID: wt.L(), URL: "/fdsnws/station/1/query", Content: "application/xml"},
{ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:00", Content: "application/xml"},
{ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01", Content: "application/xml"},
- {ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:00.123", Content: "application/xml"},
+ {ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:00Z", Content: "application/xml"},
+ {ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:00.1", Content: "application/xml"},
+ {ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:00.135", Content: "application/xml"},
+ {ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:00.12345", Content: "application/xml"},
{ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:00.123456", Content: "application/xml"},
+ {ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:00.123456Z", Content: "application/xml"}, // extra tolerance
{ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-01T00:00:0", Content: "text/plain; charset=utf-8", Status: http.StatusBadRequest},
{ID: wt.L(), URL: "/fdsnws/station/1/query?level=channel&starttime=1900-01-0", Content: "text/plain; charset=utf-8", Status: http.StatusBadRequest},
{ID: wt.L(), URL: "/fdsnws/station/1/query?minlat=-41&maxlon=177", Content: "application/xml"},
diff --git a/cmd/fdsn-ws/server.go b/cmd/fdsn-ws/server.go
index 452b9693..2fc9485c 100644
--- a/cmd/fdsn-ws/server.go
+++ b/cmd/fdsn-ws/server.go
@@ -26,7 +26,7 @@ var (
LOG_EXTRA bool // Whether POST body is logged.
)
-var stationVersion = "1.2"
+var stationVersion = "1.1"
var eventVersion = "1.2"
var dataselectVersion = "1.1"
var zeroDateTime = time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)
@@ -69,7 +69,7 @@ func main() {
if err != nil {
log.Fatalf("error with DB config: %s", err)
}
- defer db.Close()
+ defer func() { _ = db.Close() }()
db.SetMaxIdleConns(p.MaxIdle)
db.SetMaxOpenConns(p.MaxOpen)
diff --git a/cmd/fdsn-ws/server_test.go b/cmd/fdsn-ws/server_test.go
index e412fa64..9ca076e1 100644
--- a/cmd/fdsn-ws/server_test.go
+++ b/cmd/fdsn-ws/server_test.go
@@ -98,5 +98,5 @@ func setup(t *testing.T) {
func teardown() {
ts.Close()
- db.Close()
+ _ = db.Close()
}
diff --git a/internal/fdsn/dataselect.go b/internal/fdsn/dataselect.go
index 708caffc..4584c009 100644
--- a/internal/fdsn/dataselect.go
+++ b/internal/fdsn/dataselect.go
@@ -42,19 +42,15 @@ var eventTypeReg = regexp.MustCompile(`^([\w*?, ]+(?:[ -][\w*?,]+)*|--)$`) // sp
var nslcRegPassPattern = regexp.MustCompile(`^(\^[A-Z0-9\*\?\.]{2,6}\$)(\|?(\^[A-Z0-9\*\?\.]{2,6}\$))*$`) // "^WEL$|^VIZ$"
type DataSelect struct {
- StartTime Time `schema:"starttime"` // limit to data on or after the specified start time.
- EndTime Time `schema:"endtime"` // limit to data on or before the specified end time.
- Network []string `schema:"network"` // network name of data to query
- Station []string `schema:"station"` // station name of data to query
- Location []string `schema:"location"` // location name of data to query
- Channel []string `schema:"channel"` // channel number of data to query
- Format string `schema:"format"`
- LongestOnly bool `schema:"longestonly"`
- NoData int `schema:"nodata"` // Select status code for “no data”, either ‘204’ (default) or ‘404’.
-}
-
-type Time struct {
- time.Time
+ StartTime WsDateTime `schema:"starttime"` // limit to data on or after the specified start time.
+ EndTime WsDateTime `schema:"endtime"` // limit to data on or before the specified end time.
+ Network []string `schema:"network"` // network name of data to query
+ Station []string `schema:"station"` // station name of data to query
+ Location []string `schema:"location"` // location name of data to query
+ Channel []string `schema:"channel"` // channel number of data to query
+ Format string `schema:"format"`
+ LongestOnly bool `schema:"longestonly"`
+ NoData int `schema:"nodata"` // Select status code for “no data”, either ‘204’ (default) or ‘404’.
}
type DataSearch struct {
@@ -69,67 +65,6 @@ func init() {
})
}
-/*
-parses the time in text as per the FDSN spec. Pads text for parsing with
-time.RFC3339Nano. Accepted formats are (UTC):
-
- YYYY-MM-DDTHH:MM:SS.ssssss[Z] // length 26(27)
- YYYY-MM-DDTHH:MM:SS[Z] // length 19(20)
- YYYY-MM-DD // length 10
-
-Implements the encoding.TextUnmarshaler interface.
-*/
-
-func (t *Time) UnmarshalText(text []byte) (err error) {
- s := string(text)
- l := len(s)
-
- if l <= 10 {
- // date only
- t.Time, err = time.Parse("2006-01-02", s)
- if err != nil {
- return fmt.Errorf("invalid time format: %s", s)
- }
- return nil
- }
-
- // Try RFC3339Nano first (new format)
- t.Time, err = time.Parse(time.RFC3339Nano, s)
- if err == nil {
- return nil
- }
-
- // Try with Z suffix added for backward compatibility
- if !strings.HasSuffix(s, "Z") {
- t.Time, err = time.Parse(time.RFC3339Nano, s+"Z")
- if err == nil {
- return nil
- }
- }
-
- // Try legacy format for backward compatibility
- t.Time, err = time.Parse("2006-01-02T15:04:05.999999999", s)
- if err == nil {
- return nil
- }
-
- // Try legacy format with timezone
- t.Time, err = time.Parse("2006-01-02T15:04:05.999999999Z07:00", s)
- if err == nil {
- return nil
- }
-
- return fmt.Errorf("invalid time format: %s", s)
-}
-
-// This function helps to expose the unmarshaler to the public
-// it's returning time.Time instead of fdsn.Time
-func UnmarshalTime(text []byte) (time.Time, error) {
- t := Time{}
- err := t.UnmarshalText(text)
- return t.Time, err
-}
-
// ParesDataSelectGet parses the FDSN dataselect parameters in r from a
// dataselect POST request.
func ParseDataSelectPost(r io.Reader, d *[]DataSelect) error {
@@ -165,12 +100,12 @@ func ParseDataSelectPost(r io.Reader, d *[]DataSelect) error {
return fmt.Errorf("incorrect number of fields in dataselect query POST body, expected 6 but observed: %d", len(fields))
}
- startTime := Time{}
+ startTime := WsDateTime{}
if err := startTime.UnmarshalText([]byte(fields[4])); err != nil {
return err
}
- endTime := Time{}
+ endTime := WsDateTime{}
if err := endTime.UnmarshalText([]byte(fields[5])); err != nil {
return err
}
diff --git a/internal/fdsn/dataselect_test.go b/internal/fdsn/dataselect_test.go
index 5ac9785d..ac6941a2 100644
--- a/internal/fdsn/dataselect_test.go
+++ b/internal/fdsn/dataselect_test.go
@@ -35,8 +35,8 @@ NZ ABCD 10 E*? 2017-01-02T00:00:00 2017-01-03T00:00:00
dsqExpected := []fdsn.DataSelect{
{
- StartTime: fdsn.Time{Time: t1},
- EndTime: fdsn.Time{Time: t2},
+ StartTime: fdsn.WsDateTime{t1},
+ EndTime: fdsn.WsDateTime{t2},
Network: []string{"NZ"},
Station: []string{"ALRZ"},
Location: []string{"10"},
@@ -45,8 +45,8 @@ NZ ABCD 10 E*? 2017-01-02T00:00:00 2017-01-03T00:00:00
NoData: 204,
},
{
- StartTime: fdsn.Time{Time: t3},
- EndTime: fdsn.Time{Time: t4},
+ StartTime: fdsn.WsDateTime{t3},
+ EndTime: fdsn.WsDateTime{t4},
Network: []string{"NZ"},
Station: []string{"ABCD"},
Location: []string{"10"},
@@ -77,7 +77,7 @@ func TestParseGet(t *testing.T) {
t.Fatal(err)
}
- var tms, tme fdsn.Time
+ var tms, tme fdsn.WsDateTime
if err = tms.UnmarshalText([]byte(ts)); err != nil {
t.Fatal(err)
@@ -191,36 +191,3 @@ func TestWillBeEmpty(t *testing.T) {
t.Error("expected to false got true")
}
}
-
-func TestUnmarshalTime(t *testing.T) {
- tests := []struct {
- ts string
- expected string
- pass bool
- }{
- {ts: "2020-01-01T00:00:00", expected: "2020-01-01T00:00:00Z", pass: true},
- {ts: "2020-01-01T00:00:00Z", expected: "2020-01-01T00:00:00Z", pass: true},
- {ts: "2020-01-01T00:00:00.123456Z", expected: "2020-01-01T00:00:00.123456Z", pass: true},
- {ts: "2020-01-01T00:00:00.123456", expected: "2020-01-01T00:00:00.123456Z", pass: true},
- {ts: "2020-01-01", expected: "2020-01-01T00:00:00Z", pass: true},
- // make some invalid cases
- {ts: "2020-01-01T00:00:00.abcZ", expected: "", pass: false},
- {ts: "2020-01-01T00:00:00.Z", expected: "", pass: false},
- {ts: "2020-01-01Z", expected: "", pass: false},
- }
-
- for _, test := range tests {
- tm, err := fdsn.UnmarshalTime([]byte(test.ts))
- if !test.pass && err == nil {
- t.Errorf("expected to be failed for %s", test.ts)
- } else if test.pass {
- if err != nil {
- t.Errorf("expected no error for %s, got %s", test.ts, err)
- }
- if tm.Format(time.RFC3339Nano) != test.expected {
- t.Errorf("expected %s got %s", test.expected, tm.Format(time.RFC3339Nano))
- }
- }
-
- }
-}
diff --git a/internal/fdsn/wsdatetime.go b/internal/fdsn/wsdatetime.go
new file mode 100644
index 00000000..d34b71ad
--- /dev/null
+++ b/internal/fdsn/wsdatetime.go
@@ -0,0 +1,43 @@
+package fdsn
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+ "time"
+)
+
+const WsMarshalTimeFormat = "2006-01-02T15:04:05"
+
+var EmptyWsDateTime = WsDateTime{time.Date(9999, 1, 1, 0, 0, 0, 0, time.UTC)}
+var ZeroWsDateTime = WsDateTime{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}
+
+type WsDateTime struct {
+ time.Time
+}
+
+func (t *WsDateTime) UnmarshalText(text []byte) error {
+ return _unmarshalWsTime(text, &t.Time)
+}
+
+func (t WsDateTime) MarshalText() ([]byte, error) {
+ return []byte(t.Time.UTC().Format(WsMarshalTimeFormat)), nil
+}
+
+func _unmarshalWsTime(text []byte, t *time.Time) (err error) {
+ // we allows query parameter with or without timezone 'Z'
+ // (in our code we only dealt with 'Z' so official go package can handle it easily)
+ // note: not accepting timezones other than 'Z', as FDSN only using UTC
+ s := string(bytes.TrimSpace(text))
+ if len(s) == 10 {
+ *t, err = time.Parse(time.DateOnly, s)
+ return err
+ }
+ if !strings.HasSuffix(s, "Z") {
+ s += "Z"
+ }
+ if *t, err = time.Parse(time.RFC3339Nano, s); err != nil {
+ return fmt.Errorf("invalid time string: %s - %s", s, err.Error())
+ }
+ return nil
+}
diff --git a/internal/fdsn/wsdatetime_test.go b/internal/fdsn/wsdatetime_test.go
new file mode 100644
index 00000000..2c78f25f
--- /dev/null
+++ b/internal/fdsn/wsdatetime_test.go
@@ -0,0 +1,57 @@
+package fdsn_test
+
+import (
+ "testing"
+ "time"
+
+ "github.com/GeoNet/fdsn/internal/fdsn"
+)
+
+func TestTimeParse(t *testing.T) {
+ var tm fdsn.WsDateTime
+
+ if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12.999999")); err != nil {
+ t.Error(err)
+ }
+
+ if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12")); err != nil {
+ t.Error(err)
+ }
+
+ if err := tm.UnmarshalText([]byte("2015-01-12")); err != nil {
+ t.Error(err)
+ }
+
+ if err := tm.UnmarshalText([]byte("2015-01-12T12:12:12-09:00")); err == nil {
+ t.Error("expected an error for invalid time string.")
+ }
+}
+
+// confirm that we'll trim subseconds
+func TestMarshalWsDateTime(t *testing.T) {
+ tests := []struct {
+ time time.Time
+ expected string
+ }{
+ {
+ time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC),
+ "2025-12-31T23:59:59",
+ },
+ {
+ time.Date(2025, 12, 31, 23, 59, 59, 123, time.UTC),
+ "2025-12-31T23:59:59",
+ },
+ {
+ time.Date(2025, 12, 31, 23, 59, 59, 123456, time.UTC),
+ "2025-12-31T23:59:59",
+ },
+ }
+
+ for _, v := range tests {
+ tm := fdsn.WsDateTime{v.time}
+ if s, _ := tm.MarshalText(); string(s) != v.expected {
+ t.Errorf("expected %s got %s", v.expected, string(s))
+ }
+
+ }
+}