Skip to content
Snippets Groups Projects
Unverified Commit b523d0fa authored by metabase-bot[bot]'s avatar metabase-bot[bot] Committed by GitHub
Browse files

Formatter Gives correct year for dates near start/end of Year (#40410) (#40450)

Fixes: #40306

Our datetime formatter relies on the `java-time.api`, for which there are many different, sometimes confusing, formatter patterns: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatterBuilder.html#appendPattern-java.lang.String-

In this case, 'YYYY' is a week-of-year style year, which calculates which week a date falls into before returning the
year. Sometimes days near the start/end of a year will fall into a week in the wrong year.

For example, apparently 2023-12-31 falls into the 1st week of 2024, which probably not the year you'd expect to
see. What we probably do want is 'yyyy' which calculates what day of the year the date is and then returns the year
based off of that instead of the week number.

For an explanation, you can check out this SO answer: https://stackoverflow.com/a/46395342

 provides an explanation.

Co-authored-by: default avataradam-james <21064735+adam-james-v@users.noreply.github.com>
parent f9df6e11
No related branches found
No related tags found
No related merge requests found
......@@ -102,7 +102,13 @@
(str/replace #"DDD" "D")))]
(-> conditional-changes
;; 'D' formats as Day of year, we want Day of month, which is 'd' (issue #27469)
(str/replace #"D" "d"))))
(str/replace #"D" "d")
;; 'YYYY' formats as 'week-based-year', we want 'yyyy' which formats by 'year-of-era'
;; aka 'day-based-year'. We likely want that most (all?) of the time.
;; 'week-based-year' can report the wrong year on dates near the start/end of a year based on how
;; ISO-8601 defines what a week is: some days may end up in the 52nd or 1st week of the wrong year:
;; https://stackoverflow.com/a/46395342 provides an explanation.
(str/replace #"YYYY" "yyyy"))))
(def ^:private col-type
"The dispatch function logic for format format-timestring.
......
......@@ -241,3 +241,20 @@
(let [col {:unit :default}]
(is (= "15:30:45Z"
(datetime/format-temporal-str "UTC" "15:30:45Z" col nil)))))))
(deftest year-in-dates-near-start-or-end-of-year-is-correct-test
(testing "When the date is at the start/end of the year, the year is formatted properly. (#40306)"
;; Our datetime formatter relies on the `java-time.api`, for which there are many different, sometimes confusing,
;; formatter patterns: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatterBuilder.html#appendPattern-java.lang.String-
;; In this case, 'YYYY' is a week-of-year style year, which calculates which week a date falls into before returning the year.
;; Sometimes days near the start/end of a year will fall into a week in the wrong year.
;; For example, apparently 2023-12-31 falls into the 1st week of 2024, which probably not the year you'd expect to see.
;; What we probably do want is 'yyyy' which calculates what day of the year the date is and then returns the year.
(let [dates (fn [year] [(format "%s-01-01" year) (format "%s-12-31" year)])
fmt (fn [s]
(datetime/format-temporal-str "UTC" s {:field_ref [:column_name "created_at"]
:effective_type :type/Date}
{::mb.viz/column-settings
{{::mb.viz/column-name "created_at"} {::mb.viz/date-style "YYYY-MM-dd"}}}))]
(doseq [the-date (mapcat dates (range 2008 3008))]
(is (= the-date (fmt the-date)))))))
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