Skip to content

Commit ae608b0

Browse files
committed
Use an array for lookup
1 parent d2001ed commit ae608b0

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
@@ -170,15 +201,6 @@ function ZonedDateTime(date::Date, args...; kwargs...)
170201
return ZonedDateTime(DateTime(date), args...; kwargs...)
171202
end
172203

173-
function Base.getproperty(zdt::ZonedDateTime, field::Symbol)
174-
if field === :timezone || field === :zone
175-
tz, zone = ZDT_TZS[getfield(zdt, :tz_hash)]
176-
return field === :timezone ? tz : zone
177-
else
178-
return getfield(zdt, field)
179-
end
180-
end
181-
182204
# Promotion
183205

184206
# Because of the promoting fallback definitions for TimeType, we need a special case for
@@ -216,20 +238,3 @@ function Dates.validargs(::Type{ZonedDateTime}, y::Int64, m::Union{Int64, Int32}
216238
istimezone(tz) || return argerror("TimeZone: \"$tz\" is not a recognized time zone")
217239
return argerror()
218240
end
219-
220-
# Overload serialization to ensure timezone information is transferred correctly
221-
222-
function Serialization.serialize(s::AbstractSerializer, zdt::ZonedDateTime)
223-
Serialization.serialize_type(s, typeof(zdt))
224-
serialize(s, zdt.utc_datetime)
225-
serialize(s, zdt.timezone)
226-
serialize(s, zdt.zone)
227-
end
228-
229-
function Serialization.deserialize(s::AbstractSerializer, ::Type{ZonedDateTime})
230-
utc_datetime = deserialize(s)
231-
timezone = deserialize(s)
232-
zone = deserialize(s)
233-
234-
return ZonedDateTime(utc_datetime, timezone, zone)
235-
end

0 commit comments

Comments
 (0)