From 49358630495fc7b6e91b630be6a5975e1e55ab80 Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev <alex@bytopia.org> Date: Fri, 23 Aug 2024 08:55:31 +0300 Subject: [PATCH] perf: [date-2.parse] Add a fastpath for timestamps that are likely ISO instants (#47143) --- src/metabase/util/date_2/parse.clj | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/metabase/util/date_2/parse.clj b/src/metabase/util/date_2/parse.clj index 563b68784ce..5e9f8354aeb 100644 --- a/src/metabase/util/date_2/parse.clj +++ b/src/metabase/util/date_2/parse.clj @@ -7,8 +7,8 @@ [metabase.util.i18n :refer [tru]] [metabase.util.malli :as mu]) (:import - (java.time LocalDateTime OffsetDateTime OffsetTime ZonedDateTime ZoneOffset) - (java.time.format DateTimeFormatter) + (java.time Instant LocalDateTime OffsetDateTime OffsetTime ZonedDateTime ZoneOffset) + (java.time.format DateTimeFormatter DateTimeParseException) (java.time.temporal Temporal TemporalAccessor TemporalField TemporalQueries))) (set! *warn-on-reflection* true) @@ -49,6 +49,15 @@ (def ^:private utc-zone-region (t/zone-id "UTC")) +(defn- try-parse-as-iso-timestamp + "Fastpath for parsing ISO Instant timestamp if it matches the required length. Return nil if the length doesn't match + or the parsing fails, otherwise return a ZonedDateTime instance at UTC." + [^String s] + (when (and s (= (.length s) (.length "1970-01-01T00:00:00Z"))) + (try (let [temporal-accessor (.parse DateTimeFormatter/ISO_INSTANT s)] + (.atZone (Instant/from temporal-accessor) utc-zone-region)) + (catch DateTimeParseException _)))) + (mu/defn parse-with-formatter :- [:maybe InstanceOfTemporal] "Parse a String with a DateTimeFormatter, returning an appropriate instance of an `java.time` temporal class." [formattr @@ -137,4 +146,5 @@ (defn parse "Parse a string into a `java.time` object." [^String s] - (parse-with-formatter formatter s)) + (or (try-parse-as-iso-timestamp s) ;; Try the fastpath first. + (parse-with-formatter formatter s))) -- GitLab