-
Notifications
You must be signed in to change notification settings - Fork 58
Description
I have been poking around at at https://github.com/JuliaTime/TimeZones.jl/tree/cv/zdt-isbits-poc
The only reason creating a ZonedDateTime allocates is because of the lines in Interpret where a vector of interpetations is created and pushed to.
Lines 53 to 74 in af8797c
| function interpret(local_dt::DateTime, tz::VariableTimeZone, ::Type{Local}) | |
| interpretations = ZonedDateTime[] | |
| t = tz.transitions | |
| n = length(t) | |
| for i in transition_range(local_dt, tz, Local) | |
| # Convert the local DateTime into UTC | |
| utc_dt = local_dt - t[i].zone.offset | |
| if utc_dt >= t[i].utc_datetime && (i == n || utc_dt < t[i + 1].utc_datetime) | |
| push!(interpretations, ZonedDateTime(utc_dt, tz, t[i].zone)) | |
| end | |
| end | |
| return interpretations | |
| end | |
| function interpret(utc_dt::DateTime, tz::VariableTimeZone, ::Type{UTC}) | |
| range = transition_range(utc_dt, tz, UTC) | |
| length(range) == 1 || error("Internal TimeZones error: A UTC DateTime should only have a single interpretation") | |
| i = first(range) | |
| return [ZonedDateTime(utc_dt, tz, tz.transitions[i].zone)] | |
| end |
I did a benchmark of replacing just the UTC case with a tuple.
This case is easy, we know there is only going to be one result.
Allocations all gone, time for creation goes from:
julia> @btime ZonedDateTime(Date(2011, 6, 1), tz"America/Winnipeg", from_utc=true)
113.625 ns (1 allocation: 112 bytes)
2011-05-31T19:00:00-05:00down to
julia> @btime ZonedDateTime(Date(2011, 6, 1), tz"America/Winnipeg", from_utc=true)
85.499 ns (0 allocations: 0 bytes)
2011-05-31T19:00:00-05:00This case is particularly important is it shows up when you do things like adding 1 hour to a zoned date time.
So just changing that the a Tuple might be nice.
The other case has 2 allocations.
julia> @btime ZonedDateTime(Date(2011, 6, 1), tz"America/Winnipeg")
144.806 ns (2 allocations: 192 bytes)
2011-06-01T00:00:00-05:00Because we alocate a vector and push to it.
So we can give a good error message if there is 0 or 2 results.
Probably the easiest way to remove this is to change the logic for the constructor to not use interpret at all,
or to make a interpret1_or_error function, ether way to avoid a vector and just give one result or throw the error then and there