Skip to content

Commit df6dc00

Browse files
committed
Use an array for lookup
1 parent bb31298 commit df6dc00

File tree

1 file changed

+44
-39
lines changed

1 file changed

+44
-39
lines changed

src/types/zoneddatetime.jl

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
using 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

1116
struct 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
2631
end
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)
4171
end
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...)
166197
end
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()
213235
end
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

Comments
 (0)