diff --git a/stdlib/Dates/src/io.jl b/stdlib/Dates/src/io.jl index 1901661fff0e2..ba0958b57f613 100644 --- a/stdlib/Dates/src/io.jl +++ b/stdlib/Dates/src/io.jl @@ -332,6 +332,23 @@ const CONVERSION_TRANSLATIONS = IdDict{Type, Any}( Time => (Hour, Minute, Second, Millisecond, Microsecond, Nanosecond, AMPM), ) +# The `DateFormat(format, locale)` method just below consumes the following Regex. +# Constructing this Regex is fairly expensive; doing so in the method itself can +# consume half or better of `DateFormat(format, locale)`'s runtime. So instead we +# construct and cache it outside the method body. Note, however, that when +# `keys(CONVERSION_SPECIFIERS)` changes, the cached Regex must be updated accordingly; +# hence the mutability (Ref-ness) of the cache, the helper method with which to populate +# the cache, the cache of the hash of `keys(CONVERSION_SPECIFIERS)` (to facilitate checking +# for changes), and the lock (to maintain consistency of these objects across threads when +# threads simultaneously modify `CONVERSION_SPECIFIERS` and construct `DateFormat`s). +function compute_dateformat_regex(conversion_specifiers) + letters = String(collect(keys(conversion_specifiers))) + return Regex("(? DateFormat @@ -379,8 +396,20 @@ function DateFormat(f::AbstractString, locale::DateLocale=ENGLISH) prev = () prev_offset = 1 - letters = String(collect(keys(CONVERSION_SPECIFIERS))) - for m in eachmatch(Regex("(? s"\1") if !isempty(prev)