Skip to content
Snippets Groups Projects
Commit 2f8bd112 authored by Ryan Senior's avatar Ryan Senior
Browse files

On export, format dates to not include times

Currently all :type/DateTime values, including :type/Date values are
serialized as ISO timestamps, which includes the time and
timezone. This commit handles :type/Date fields differently, emitting
only the date (year, month and day).

Fixes #5828
parent f8c72765
No related branches found
No related tags found
No related merge requests found
(ns metabase.api.dataset
"/api/dataset endpoints."
(:require [cheshire.core :as json]
[clj-time.format :as tformat]
[clojure.string :as str]
[clojure.tools.logging :as log]
[compojure.core :refer [POST]]
......@@ -77,15 +78,41 @@
(or (get-in ex/export-formats [export-format :context])
(throw (Exception. (str "Invalid export format: " export-format)))))
(defn- datetime-str->date
"Dates are iso formatted, i.e. 2014-09-18T00:00:00.000-07:00. We can just drop the T and everything after it since
we don't want to change the timezone or alter the date part."
[^String date-str]
(subs date-str 0 (.indexOf date-str "T")))
(defn- swap-date-columns [date-col-indexes]
(fn [row]
(reduce (fn [acc idx]
(update acc idx datetime-str->date)) row date-col-indexes)))
(defn- date-column-indexes
"Given `column-metadata` find the `:type/Date` columns"
[column-metadata]
(transduce (comp (map-indexed (fn [idx col-map] [idx (:base_type col-map)]))
(filter (fn [[idx base-type]] (isa? base-type :type/Date)))
(map first))
conj [] column-metadata))
(defn- maybe-modify-date-values [column-metadata rows]
(let [date-indexes (date-column-indexes column-metadata)]
(if (seq date-indexes)
;; Not sure why, but rows aren't vectors, they're lists which makes updating difficult
(map (comp (swap-date-columns date-indexes) vec) rows)
rows)))
(defn as-format
"Return a response containing the RESULTS of a query in the specified format."
{:style/indent 1, :arglists '([export-format results])}
[export-format {{:keys [columns rows]} :data, :keys [status], :as response}]
[export-format {{:keys [columns rows cols]} :data, :keys [status], :as response}]
(api/let-404 [export-conf (ex/export-formats export-format)]
(if (= status :completed)
;; successful query, send file
{:status 200
:body ((:export-fn export-conf) columns rows)
:body ((:export-fn export-conf) columns (maybe-modify-date-values cols rows))
:headers {"Content-Type" (str (:content-type export-conf) "; charset=utf-8")
"Content-Disposition" (str "attachment; filename=\"query_result_" (u/date->iso-8601) "." (:ext export-conf) "\"")}}
;; failed query, send error message
......
(ns metabase.api.dataset-test
"Unit tests for /api/dataset endpoints."
(:require [cheshire.generate :as generate]
(:require [cheshire
[core :as json]
[generate :as generate]]
[clojure.data.csv :as csv]
[dk.ative.docjure.spreadsheet :as spreadsheet]
[expectations :refer :all]
[medley.core :as m]
......@@ -153,3 +156,34 @@
["ABC"]])
(spreadsheet/select-sheet "Results")
(spreadsheet/select-columns {:A "Values"})))
(defn- parse-and-sort-csv [response]
(sort-by
;; ID in CSV is a string, parse it and sort it to get the first 5
(comp #(Integer/parseInt %) first)
;; First row is the header
(rest (csv/read-csv response))))
;; Date columns should be emitted without time
(expect
[["1" "2014-04-07" "5" "12"]
["2" "2014-09-18" "1" "31"]
["3" "2014-09-15" "8" "56"]
["4" "2014-03-11" "5" "4"]
["5" "2013-05-05" "3" "49"]]
(let [result ((user->client :rasta) :post 200 "dataset/csv" :query
(json/generate-string (wrap-inner-query
(query checkins))))]
(take 5 (parse-and-sort-csv result))))
;; DateTime fields are untouched when exported
(expect
[["1" "Plato Yeshua" "2014-04-01T08:30:00.000Z"]
["2" "Felipinho Asklepios" "2014-12-05T15:15:00.000Z"]
["3" "Kaneonuskatew Eiran" "2014-11-06T16:15:00.000Z"]
["4" "Simcha Yan" "2014-01-01T08:30:00.000Z"]
["5" "Quentin Sören" "2014-10-03T17:30:00.000Z"]]
(let [result ((user->client :rasta) :post 200 "dataset/csv" :query
(json/generate-string (wrap-inner-query
(query users))))]
(take 5 (parse-and-sort-csv result))))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment