11using Dates: AbstractDateTime, argerror, validargs
22
3- const ZDT_TZS = Dict {UInt,Tuple{TimeZone,FixedTimeZone}} ()
3+ # Stores non-bits data outside of the `ZonedDateTime` structure
4+ const _ZDT_FIELDS = Vector {Tuple{TimeZone,FixedTimeZone}} ()
5+
6+ # Stored indexes into `_ZDT_FIELDS`
7+ const _TZ_INDEX = Dict {Tuple{TimeZone,FixedTimeZone},Int} ()
8+
49
510# """
611# ZonedDateTime
@@ -10,36 +15,62 @@ const ZDT_TZS = Dict{UInt,Tuple{TimeZone,FixedTimeZone}}()
1015
1116struct ZonedDateTime <: AbstractDateTime
1217 utc_datetime:: DateTime
13- tz_hash :: UInt
18+ _tz_index :: Int
1419
1520 function ZonedDateTime (utc_datetime:: DateTime , timezone:: TimeZone , zone:: FixedTimeZone )
16- return new (utc_datetime, gen_tz_hash (timezone, zone))
21+ return new (utc_datetime, _tz_index (timezone, zone))
1722 end
1823
1924 function ZonedDateTime (utc_datetime:: DateTime , timezone:: VariableTimeZone , zone:: FixedTimeZone )
2025 if timezone. cutoff != = nothing && utc_datetime >= timezone. cutoff
2126 throw (UnhandledTimeError (timezone))
2227 end
2328
24- return new (utc_datetime, gen_tz_hash (timezone, zone))
29+ return new (utc_datetime, _tz_index (timezone, zone))
2530 end
2631end
2732
28- function gen_tz_hash (tz:: TimeZone , zone:: FixedTimeZone )
29- h = hash (tz)
30- h = hash (zone, h)
33+ function _tz_index (tz:: TimeZone , zone:: FixedTimeZone )
34+ t = (tz, zone)
35+
36+ i = get! (_TZ_INDEX, t) do
37+ push! (_ZDT_FIELDS, t)
38+ lastindex (_ZDT_FIELDS)
39+ end
40+
41+ return i
42+ end
3143
32- if haskey (ZDT_TZS, h)
33- stored_tz, stored_zone = ZDT_TZS[h]
34- @assert tz == stored_tz
35- @assert zone == stored_zone
44+ function Base. getproperty (zdt:: ZonedDateTime , field:: Symbol )
45+ if field === :zone
46+ tz, zone = _ZDT_FIELDS[getfield (zdt, :_tz_index )]
47+ return zone
48+ elseif field === :timezone
49+ tz, zone = _ZDT_FIELDS[getfield (zdt, :_tz_index )]
50+ return tz
3651 else
37- ZDT_TZS[h] = (tz, zone )
52+ return getfield (zdt, field )
3853 end
54+ end
3955
40- return h
56+ # Overload serialization to ensure that `ZonedDateTime` serialization doesn't transfer
57+ # state information which is specific to the current Julia process.
58+ function Serialization. serialize (s:: AbstractSerializer , zdt:: ZonedDateTime )
59+ Serialization. serialize_type (s, typeof (zdt))
60+ serialize (s, zdt. utc_datetime)
61+ serialize (s, zdt. timezone)
62+ serialize (s, zdt. zone)
63+ end
64+
65+ function Serialization. deserialize (s:: AbstractSerializer , :: Type{ZonedDateTime} )
66+ utc_datetime = deserialize (s)
67+ timezone = deserialize (s)
68+ zone = deserialize (s)
69+
70+ return ZonedDateTime (utc_datetime, timezone, zone)
4171end
4272
73+
4374"""
4475 ZonedDateTime(dt::DateTime, tz::TimeZone; from_utc=false) -> ZonedDateTime
4576
@@ -165,15 +196,6 @@ function ZonedDateTime(date::Date, args...; kwargs...)
165196 return ZonedDateTime (DateTime (date), args... ; kwargs... )
166197end
167198
168- function Base. getproperty (zdt:: ZonedDateTime , field:: Symbol )
169- if field === :timezone || field === :zone
170- tz, zone = ZDT_TZS[getfield (zdt, :tz_hash )]
171- return field === :timezone ? tz : zone
172- else
173- return getfield (zdt, field)
174- end
175- end
176-
177199# Promotion
178200
179201# Because of the promoting fallback definitions for TimeType, we need a special case for
@@ -211,20 +233,3 @@ function Dates.validargs(::Type{ZonedDateTime}, y::Int64, m::Union{Int64, Int32}
211233 istimezone (tz) || return argerror (" TimeZone: \" $tz \" is not a recognized time zone" )
212234 return argerror ()
213235end
214-
215- # Overload serialization to ensure timezone information is transferred correctly
216-
217- function Serialization. serialize (s:: AbstractSerializer , zdt:: ZonedDateTime )
218- Serialization. serialize_type (s, typeof (zdt))
219- serialize (s, zdt. utc_datetime)
220- serialize (s, zdt. timezone)
221- serialize (s, zdt. zone)
222- end
223-
224- function Serialization. deserialize (s:: AbstractSerializer , :: Type{ZonedDateTime} )
225- utc_datetime = deserialize (s)
226- timezone = deserialize (s)
227- zone = deserialize (s)
228-
229- return ZonedDateTime (utc_datetime, timezone, zone)
230- end
0 commit comments