14287: Ensure timestamps in responses have 9 digits of nanoseconds.
authorTom Clegg <tclegg@veritasgenetics.com>
Wed, 8 May 2019 15:43:33 +0000 (11:43 -0400)
committerTom Clegg <tclegg@veritasgenetics.com>
Mon, 17 Jun 2019 13:54:39 +0000 (09:54 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tclegg@veritasgenetics.com>

lib/controller/router/response.go

index 65e0159fa9cdccfedf1074a12aeb5c225af3b506..ddbeee666ff13f3ce4bd6b0a601c2774efc46622 100644 (file)
@@ -7,11 +7,15 @@ package router
 import (
        "encoding/json"
        "net/http"
+       "strings"
+       "time"
 
        "git.curoverse.com/arvados.git/sdk/go/arvados"
        "git.curoverse.com/arvados.git/sdk/go/httpserver"
 )
 
+const rfc3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
+
 type responseOptions struct {
        Select []string
 }
@@ -41,6 +45,29 @@ func (rtr *router) sendResponse(w http.ResponseWriter, resp interface{}, opts re
                }
                tmp = selected
        }
+       // Format non-nil timestamps as rfc3339NanoFixed (by default
+       // they will have been encoded to time.RFC3339Nano, which
+       // omits trailing zeroes).
+       for k, v := range tmp {
+               if !strings.HasSuffix(k, "_at") {
+                       continue
+               }
+               switch tv := v.(type) {
+               case *time.Time:
+                       if tv == nil {
+                               break
+                       }
+                       tmp[k] = tv.Format(rfc3339NanoFixed)
+               case time.Time:
+                       tmp[k] = tv.Format(rfc3339NanoFixed)
+               case string:
+                       t, err := time.Parse(time.RFC3339Nano, tv)
+                       if err != nil {
+                               break
+                       }
+                       tmp[k] = t.Format(rfc3339NanoFixed)
+               }
+       }
        json.NewEncoder(w).Encode(tmp)
 }