Search code examples
julia

ERROR: MethodError: Cannot `convert` an object of type TimeZones.FixedTimeZone to an object of type TimeZones.VariableTimeZone


I am using the Julia model GlobalEnergyGIS (https://github.com/niclasmattsson/GlobalEnergyGIS.git) and get the error is in the title. Has anyone dealt with this type of error before and can help how to fix it, because I have no idea where to even start since I am not familiar with Julia.

function regional_timezone_offsets_Jan1(; gisregion="Europe8", scenarioyear="ssp2_2050", era_year=2018)
    println("\nCalculating population-weighted regional time zone offsets...")
    regions, offshoreregions, regionlist, lonrange, latrange = loadregions(gisregion)
    tzindices, tznames = loadtimezones(lonrange, latrange)
    popscale = 1e5
    pop = JLD.load(in_datafolder("population_$scenarioyear.jld"), "population")[lonrange,latrange] ./ popscale   # scale down for better precision
    numreg = length(regionlist)
    numhours = 24*daysinyear(era_year)
    offsets = zeros(numreg)
    population = zeros(numreg)
    zone_maxpop = fill(TimeZone("Europe/London"), numreg)
    updateprogress = Progress(numreg, 1)
    for r = 1:numreg
        reg = (regions .== r)
        regindices = tzindices[reg]
        regpop = pop[reg]
        zoneindices = unique(regindices)
        weightedoffset = 0.0
        zones = TimeZone[]
        pops = Float64[]
        for idx in zoneindices
            tzname = tznames[idx]
            zone = tzname[1:3] == "Etc" ? TimeZone(tzname, TimeZones.Class(:LEGACY)) : TimeZone(tzname)
            push!(zones, zone)
            firsthour = ZonedDateTime(DateTime(era_year,1,1,0), zone)
            hours = firsthour : Hour(1) : firsthour + Hour(numhours-1)
            offset = tzoffset(hours[1])
            localpop = sum(regpop[regindices.==idx])
            push!(pops, localpop)
            weightedoffset += localpop * offset
        end
        _, i = findmax(pops)    # find time zone with the most population
        zone_maxpop[r] = zones[i]
        population[r] = sum(pops) * popscale    # scale up again
        offsets[r] = weightedoffset / sum(pops)
        next!(updateprogress)
    end

    return offsets, zone_maxpop, population
end
julia> show(err)
1-element ExceptionStack:
MethodError: Cannot `convert` an object of type TimeZones.FixedTimeZone to an object of type TimeZones.VariableTimeZone

Closest candidates are:
  convert(::Type{T}, ::T) where T
   @ Base Base.jl:84

Stacktrace:
 [1] setindex!(A::Vector{TimeZones.VariableTimeZone}, x::TimeZones.FixedTimeZone, i1::Int64)
   @ Base ./array.jl:1021
 [2] regional_timezone_offsets_Jan1(; gisregion::String, scenarioyear::String, era_year::Int64)
   @ GlobalEnergyGIS ~/Documents/MPhil_Energy_Technologies/Dissertation_Project/GlobalEnergyGIS/GlobalEnergyGIS/src/syntheticdemand_inputdata.jl:248
 [3] regional_timezone_offsets_Jan1
   @ ~/Documents/MPhil_Energy_Technologies/Dissertation_Project/GlobalEnergyGIS/GlobalEnergyGIS/src/syntheticdemand_inputdata.jl:216 [inlined]
 [4] buildtrainingdata(; gisregion::String, sspscenario::String, sspyear::Int64, era_year::Int64, numcenters::Int64, mindist::Float64)
   @ GlobalEnergyGIS ~/Documents/MPhil_Energy_Technologies/Dissertation_Project/GlobalEnergyGIS/GlobalEnergyGIS/src/syntheticdemand_inputdata.jl:151
 [5] buildtrainingdata
   @ ~/Documents/MPhil_Energy_Technologies/Dissertation_Project/GlobalEnergyGIS/GlobalEnergyGIS/src/syntheticdemand_inputdata.jl:145 [inlined]
 [6] predictdemand(; variables::Vector{Symbol}, gisregion::String, sspscenario::String, sspyear::Int64, era_year::Int64, numcenters::Int64, mindist::Float64, nrounds::Int64, max_depth::Int64, eta::Float64, subsample::Float64, metrics::Vector{String}, more_xgoptions::@Kwargs{})
   @ GlobalEnergyGIS ~/Documents/MPhil_Energy_Technologies/Dissertation_Project/GlobalEnergyGIS/GlobalEnergyGIS/src/syntheticdemand_training.jl:11
 [7] top-level scope
   @ REPL[17]:1

Solution

  • The first issue is that zone_maxpop is initialised as a VariableTimeZone. You need to initialise it as a FixedTimeZone (just use UTC).

    The next issue that will occur is that this will not accept UTC +-00:00 as input:

    zone = tzname[1:3] == "Etc" ? TimeZone(tzname, TimeZones.Class(:LEGACY)) : TimeZone(tzname)
    

    I just used an if statement to prevent that.