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

Add a MySQL date parser that can handle abbreviated offsets [ci drivers]

Dependong on what timezone you're in, the system_time_zone can be
returned as abbreviated timezone identifier like CST or it can return
an abbreviated offset like -02. This commit adds some special handling
for the offset case.

Fixes #6483
parent 10c709f2
Branches
Tags
No related merge requests found
......@@ -292,11 +292,19 @@
[date-format-str]
(.withOffsetParsed ^DateTimeFormatter (tformat/formatter date-format-str)))
(defn- first-successful-parse
"Attempt to parse `time-str` with each of `date-formatters`, returning the first successful parse. If there are no
successful parses throws the exception that the last formatter threw."
[date-formatters time-str]
(or (some #(u/ignore-exceptions (tformat/parse % time-str)) date-formatters)
(doseq [formatter (reverse date-formatters)]
(tformat/parse formatter time-str))))
(defn make-current-db-time-fn
"Takes a clj-time date formatter `DATE-FORMATTER` and a native query
for the current time. Returns a function that executes the query and
parses the date returned preserving it's timezone"
[native-query date-formatter]
[native-query date-formatter & more-date-formatters]
(fn [driver database]
(let [settings (when-let [report-tz (report-timezone-if-supported driver)]
{:settings {:report-timezone report-tz}})
......@@ -311,7 +319,7 @@
(format "Error querying database '%s' for current time" (:name database)) e))))]
(try
(when time-str
(tformat/parse date-formatter time-str))
(first-successful-parse (cons date-formatter more-date-formatters) time-str))
(catch Exception e
(throw
(Exception.
......
......@@ -216,6 +216,11 @@
(def ^:private mysql-date-formatter
(driver/create-db-time-formatter "yyyy-MM-dd HH:mm:ss.SSSSSS zzz"))
(def ^:private mysql-offset-date-formatter
"In some timezones, MySQL doesn't return a timezone description but rather a truncated offset, such as '-02'. That
offset will fail to parse using a regular formatter"
(driver/create-db-time-formatter "yyyy-MM-dd HH:mm:ss.SSSSSS Z"))
(def ^:private mysql-db-time-query
"select CONCAT(DATE_FORMAT(current_timestamp, '%Y-%m-%d %H:%i:%S.%f' ), ' ', @@system_time_zone)")
......@@ -252,7 +257,7 @@
:display-name "Additional JDBC connection string options"
:placeholder "tinyInt1isBit=false"}]))
:humanize-connection-error-message (u/drop-first-arg humanize-connection-error-message)
:current-db-time (driver/make-current-db-time-fn mysql-db-time-query mysql-date-formatter)})
:current-db-time (driver/make-current-db-time-fn mysql-db-time-query mysql-date-formatter mysql-offset-date-formatter)})
sql/ISQLDriver
(merge (sql/ISQLDriverDefaultsMixin)
......
......@@ -87,6 +87,11 @@
"America/Los_Angeles"
(tu/db-timezone-id))
(expect-with-engine :mysql
"-02:00"
(with-redefs [metabase.driver/execute-query (constantly {:rows [["2018-01-09 18:39:08.000000 -02"]]})]
(tu/db-timezone-id)))
(expect (#'mysql/timezone-id->offset-str "US/Pacific") "-08:00")
(expect (#'mysql/timezone-id->offset-str "UTC") "+00:00")
(expect (#'mysql/timezone-id->offset-str "America/Los_Angeles") "-08:00")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment