Skip to content

Commit 45745ae

Browse files
authored
Merge pull request #543 from JuliaRobotics/feat/20Q3/zonedtime
Change DateTime to ZonedDateTime
2 parents 18ff7cc + 1e6886e commit 45745ae

14 files changed

+89
-43
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Neo4j = "d2adbeaf-5838-5367-8a2f-e46d570981db"
1717
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1818
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
1919
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
20+
TimeZones = "f269a46b-ccf7-5d73-abea-4c690281aa53"
2021
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
2122
Unmarshal = "cbff2730-442d-58d7-89d1-8e530c41eb02"
2223

@@ -31,6 +32,7 @@ LightGraphs = "1.2, 1.3"
3132
Neo4j = "2"
3233
Reexport = "0.2, 0.3, 0.4, 0.5, 1"
3334
Requires = "0.5, 0.6, 0.7, 0.8, 0.9, 0.10, 1"
35+
TimeZones = "1.3.1"
3436
Unmarshal = "0.3, 0.4"
3537
julia = "1.2"
3638

src/Deprecated.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
## Remove in 0.10
88
##==============================================================================
99

10+
# temporary promote with warning
11+
Base.promote_rule(::Type{DateTime}, ::Type{ZonedDateTime}) = DateTime
12+
function Base.convert(::Type{DateTime}, ts::ZonedDateTime)
13+
@warn "DFG now uses ZonedDateTime, temporary promoting and converting to DateTime local time"
14+
return DateTime(ts, Local)
15+
end
16+
1017
export listSolvekeys
1118

1219
@deprecate listSolvekeys(x...) listSolveKeys(x...)

src/DistributedFactorGraphs.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ using Base
1818
using DocStringExtensions
1919
using Requires
2020
using Dates
21+
using TimeZones
2122
using Distributions
2223
using Reexport
2324
using JSON

src/entities/DFGFactor.jl

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ mutable struct GenericFunctionNodeData{T<:Union{PackedInferenceType, FunctorInfe
4343
solveInProgress::Int
4444

4545
# TODO deprecate all these inner constructors at end of DFG v0.9.x (was added for GFND.nullhypo::Float64 breaking change)
46-
GenericFunctionNodeData{T}() where T = new{T}()
4746
GenericFunctionNodeData{T}(el,po,ed,fn,mu::Vector{<:Real},ce::Vector{Int},so::Int) where T = new{T}(el,po,ed,fn,mu,ce,0.0,so)
4847
GenericFunctionNodeData{T}(el,po,ed,fn,mu::Vector{<:Real},ce::Vector{Int},nu::Real,so::Int) where T = new{T}(el,po,ed,fn,mu,ce,nu,so)
4948
end
@@ -106,7 +105,7 @@ struct DFGFactor{T, N} <: AbstractDFGFactor
106105
label::Symbol
107106
"""Variable timestamp.
108107
Accessors: [`getTimestamp`](@ref), [`setTimestamp`](@ref)"""
109-
timestamp::DateTime
108+
timestamp::ZonedDateTime
110109
"""Nano second time, for more resolution on timestamp (only subsecond information)"""
111110
nstime::Nanosecond
112111
"""Factor tags, e.g [:FACTOR].
@@ -122,14 +121,21 @@ struct DFGFactor{T, N} <: AbstractDFGFactor
122121
Accessors: [`getVariableOrder`](@ref)"""
123122
_variableOrderSymbols::NTuple{N,Symbol}
124123
# Inner constructor
125-
DFGFactor{T}(label::Symbol,
126-
timestamp::DateTime,
124+
function DFGFactor{T}(label::Symbol,
125+
timestamp::Union{DateTime,ZonedDateTime},
127126
nstime::Nanosecond,
128127
tags::Set{Symbol},
129128
solverData::GenericFunctionNodeData{T},
130129
solvable::Int,
131-
_variableOrderSymbols::NTuple{N,Symbol}) where {T,N} =
132-
new{T,N}(label, timestamp, nstime, tags, Ref(solverData), Ref(solvable), _variableOrderSymbols)
130+
_variableOrderSymbols::NTuple{N,Symbol}) where {T,N}
131+
132+
#TODO Deprecate remove in v0.10.
133+
if timestamp isa DateTime
134+
Base.depwarn("DFGFactor timestamp field is now a ZonedTimestamp", :DFGFactor)
135+
return new{T,N}(label, ZonedDateTime(timestamp, localzone()), nstime, tags, Ref(solverData), Ref(solvable), _variableOrderSymbols)
136+
end
137+
return new{T,N}(label, timestamp, nstime, tags, Ref(solverData), Ref(solvable), _variableOrderSymbols)
138+
end
133139

134140
end
135141

@@ -142,7 +148,7 @@ $(SIGNATURES)
142148
Construct a DFG factor given a label.
143149
"""
144150
DFGFactor(label::Symbol,
145-
timestamp::DateTime,
151+
timestamp::Union{DateTime,ZonedDateTime},
146152
nstime::Nanosecond,
147153
tags::Set{Symbol},
148154
solverData::GenericFunctionNodeData{T},
@@ -151,15 +157,15 @@ DFGFactor(label::Symbol,
151157
DFGFactor{T}(label, timestamp, nstime, tags, solverData, solvable, _variableOrderSymbols)
152158

153159

154-
DFGFactor{T}(label::Symbol, variableOrderSymbols::Vector{Symbol}, timestamp::DateTime=now(), data::GenericFunctionNodeData{T} = GenericFunctionNodeData{T}()) where {T} =
160+
DFGFactor{T}(label::Symbol, variableOrderSymbols::Vector{Symbol}, timestamp::Union{DateTime,ZonedDateTime}=now(localzone()), data::GenericFunctionNodeData{T} = GenericFunctionNodeData{T}()) where {T} =
155161
DFGFactor(label, timestamp, Nanosecond(0), Set{Symbol}(), data, 1, Tuple(variableOrderSymbols))
156162

157163

158164
DFGFactor(label::Symbol,
159165
variableOrderSymbols::Vector{Symbol},
160166
data::GenericFunctionNodeData{T};
161167
tags::Set{Symbol}=Set{Symbol}(),
162-
timestamp::DateTime=now(),
168+
timestamp::Union{DateTime,ZonedDateTime}=now(localzone()),
163169
solvable::Int=1,
164170
nstime::Nanosecond = Nanosecond(0)) where {T} =
165171
DFGFactor{T}(label, timestamp, nstime, tags, data, solvable, Tuple(variableOrderSymbols))
@@ -179,6 +185,10 @@ end
179185
Base.setproperty!(x::DFGFactor,f::Symbol, val) = begin
180186
if f == :solvable || f == :solverData
181187
getfield(x,f)[] = val
188+
elseif f == :timestamp && val isa DateTime
189+
# #TODO Deprecation - Remove in v0.10
190+
Base.depwarn("DFGFactor timestamp field is now a ZonedTimestamp", :setproperty!)
191+
setfield!(x,:timestamp, ZonedDateTime(val, localzone()))
182192
else
183193
setfield!(x,f,val)
184194
end
@@ -201,7 +211,7 @@ struct DFGFactorSummary <: AbstractDFGFactor
201211
label::Symbol
202212
"""Variable timestamp.
203213
Accessors: [`getTimestamp`](@ref)"""
204-
timestamp::DateTime
214+
timestamp::ZonedDateTime
205215
"""Factor tags, e.g [:FACTOR].
206216
Accessors: [`getTags`](@ref), [`mergeTags!`](@ref), and [`removeTags!`](@ref)"""
207217
tags::Set{Symbol}

src/entities/DFGVariable.jl

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ struct DFGVariable{T<:InferenceVariable} <: AbstractDFGVariable
184184
label::Symbol
185185
"""Variable timestamp.
186186
Accessors: [`getTimestamp`](@ref), [`setTimestamp`](@ref)"""
187-
timestamp::DateTime
187+
timestamp::ZonedDateTime
188188
"""Nano second time, for more resolution on timestamp (only subsecond information)"""
189189
nstime::Nanosecond
190190
"""Variable tags, e.g [:POSE, :VARIABLE, and :LANDMARK].
@@ -214,28 +214,38 @@ end
214214
$SIGNATURES
215215
The default DFGVariable constructor.
216216
"""
217-
DFGVariable(label::Symbol, softtype::T;
218-
timestamp::DateTime=now(),
217+
function DFGVariable(label::Symbol, softtype::T;
218+
timestamp::Union{DateTime,ZonedDateTime}=now(localzone()),
219219
nstime::Nanosecond = Nanosecond(0),
220220
tags::Set{Symbol}=Set{Symbol}(),
221221
estimateDict::Dict{Symbol, <: AbstractPointParametricEst}=Dict{Symbol, MeanMaxPPE}(),
222222
solverDataDict::Dict{Symbol, VariableNodeData{T}}=Dict{Symbol, VariableNodeData{T}}(),
223223
smallData::Dict{String, String}=Dict{String, String}(),
224224
dataDict::Dict{Symbol, AbstractDataEntry}=Dict{Symbol,AbstractDataEntry}(),
225-
solvable::Int=1) where {T <: InferenceVariable} =
226-
DFGVariable{T}(label, timestamp, nstime, tags, estimateDict, solverDataDict, smallData, dataDict, Ref(solvable))
225+
solvable::Int=1) where {T <: InferenceVariable}
227226

227+
if timestamp isa DateTime
228+
DFGVariable{T}(label, ZonedDateTime(timestamp, localzone()), nstime, tags, estimateDict, solverDataDict, smallData, dataDict, Ref(solvable))
229+
else
230+
DFGVariable{T}(label, timestamp, nstime, tags, estimateDict, solverDataDict, smallData, dataDict, Ref(solvable))
231+
end
232+
end
228233

229-
DFGVariable(label::Symbol,
234+
function DFGVariable(label::Symbol,
230235
solverData::VariableNodeData{T};
231-
timestamp::DateTime=now(),
236+
timestamp::Union{DateTime,ZonedDateTime}=now(localzone()),
232237
nstime::Nanosecond = Nanosecond(0),
233238
tags::Set{Symbol}=Set{Symbol}(),
234239
estimateDict::Dict{Symbol, <: AbstractPointParametricEst}=Dict{Symbol, MeanMaxPPE}(),
235240
smallData::Dict{String, String}=Dict{String, String}(),
236241
dataDict::Dict{Symbol, AbstractDataEntry}=Dict{Symbol,AbstractDataEntry}(),
237-
solvable::Int=1) where {T <: InferenceVariable} =
238-
DFGVariable{T}(label, timestamp, nstime, tags, estimateDict, Dict{Symbol, VariableNodeData{T}}(:default=>solverData), smallData, dataDict, Ref(solvable))
242+
solvable::Int=1) where {T <: InferenceVariable}
243+
if timestamp isa DateTime
244+
DFGVariable{T}(label, ZonedDateTime(timestamp, localzone()), nstime, tags, estimateDict, Dict{Symbol, VariableNodeData{T}}(:default=>solverData), smallData, dataDict, Ref(solvable))
245+
else
246+
DFGVariable{T}(label, timestamp, nstime, tags, estimateDict, Dict{Symbol, VariableNodeData{T}}(:default=>solverData), smallData, dataDict, Ref(solvable))
247+
end
248+
end
239249

240250
Base.getproperty(x::DFGVariable,f::Symbol) = begin
241251
if f == :solvable
@@ -254,8 +264,12 @@ Base.setproperty!(x::DFGVariable,f::Symbol, val) = begin
254264
getfield(x,f)[] = val
255265
elseif f == :bigData
256266
#TODO Deprecation - Remove in v0.10
257-
Base.depwarn("DFGVariable field bigData is deprecated, use `dataDict` instead",:setproperty!)
258-
setfield(x, :dataDict)
267+
Base.depwarn("DFGVariable field bigData is deprecated, use `dataDict` instead", :setproperty!)
268+
setfield(x, :dataDict, val)
269+
elseif f == :timestamp && val isa DateTime
270+
# #TODO Deprecation - Remove in v0.10
271+
Base.depwarn("DFGVariable timestamp field is now a ZonedTimestamp", :setproperty!)
272+
setfield!(x,:timestamp, ZonedDateTime(val, localzone()))
259273
else
260274
setfield!(x,f,val)
261275
end
@@ -288,7 +302,7 @@ struct DFGVariableSummary <: AbstractDFGVariable
288302
label::Symbol
289303
"""Variable timestamp.
290304
Accessors: [`getTimestamp`](@ref), [`setTimestamp`](@ref)"""
291-
timestamp::DateTime
305+
timestamp::ZonedDateTime
292306
"""Variable tags, e.g [:POSE, :VARIABLE, and :LANDMARK].
293307
Accessors: [`getTags`](@ref), [`mergeTags!`](@ref), and [`removeTags!`](@ref)"""
294308
tags::Set{Symbol}

src/services/AbstractDFG.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -766,14 +766,15 @@ end
766766
##==============================================================================
767767
## Finding
768768
##==============================================================================
769-
769+
# function findClosestTimestamp(setA::Vector{Tuple{DateTime,T}},
770+
# setB::Vector{Tuple{DateTime,S}}) where {S,T}
770771
"""
771772
$SIGNATURES
772773
773774
Find and return the closest timestamp from two sets of Tuples. Also return the minimum delta-time (`::Millisecond`) and how many elements match from the two sets are separated by the minimum delta-time.
774775
"""
775-
function findClosestTimestamp(setA::Vector{Tuple{DateTime,T}},
776-
setB::Vector{Tuple{DateTime,S}}) where {S,T}
776+
function findClosestTimestamp(setA::Vector{Tuple{ZonedDateTime,T}},
777+
setB::Vector{Tuple{ZonedDateTime,S}}) where {S,T}
777778
#
778779
# build matrix of delta times, ranges on rows x vars on columns
779780
DT = Array{Millisecond, 2}(undef, length(setA), length(setB))
@@ -813,7 +814,7 @@ Related
813814
ls, listVariables, findClosestTimestamp
814815
"""
815816
function findVariableNearTimestamp(dfg::AbstractDFG,
816-
timest::DateTime,
817+
timest::ZonedDateTime,
817818
regexFilter::Union{Nothing, Regex}=nothing;
818819
tags::Vector{Symbol}=Symbol[],
819820
solvable::Int=0,
@@ -853,6 +854,10 @@ function findVariableNearTimestamp(dfg::AbstractDFG,
853854
return RET
854855
end
855856

857+
findVariableNearTimestamp(dfg::AbstractDFG, timest::DateTime, regexFilter::Union{Nothing, Regex}=nothing;
858+
timezone=localzone(), kwargs...) =
859+
findVariableNearTimestamp(dfg, ZonedDateTime(timest, timezone), regexFilter; kwargs...)
860+
856861
##==============================================================================
857862
## Copy Functions
858863
##==============================================================================

src/services/CommonAccessors.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,16 @@ Note:
6262
Since `timestamp` is not mutable `setTimestamp!` calls `updateVariable!` internally.
6363
See also [`setTimestamp`](@ref)
6464
"""
65-
function setTimestamp!(dfg::AbstractDFG, lbl::Symbol, ts::DateTime)
65+
function setTimestamp!(dfg::AbstractDFG, lbl::Symbol, ts::ZonedDateTime)
6666
if isVariable(dfg, lbl)
67-
return updateVariable!(dfg, setTimestamp(getVariable(dfg,lbl), ts))
67+
return updateVariable!(dfg, setTimestamp(getVariable(dfg,lbl), ts; verbose=false))
6868
else
6969
return updateFactor!(dfg, setTimestamp(getFactor(dfg,lbl), ts))
7070
end
7171
end
7272

73+
setTimestamp!(dfg::AbstractDFG, lbl::Symbol, ts::DateTime, timezone=localzone()) = setTimestamp!(dfg, lbl, ZonedDateTime(ts, timezone))
74+
7375

7476

7577
##------------------------------------------------------------------------------

src/services/DFGFactor.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,13 @@ end
6767
## COMMON
6868
# getTimestamp
6969

70+
setTimestamp(f::AbstractDFGFactor, ts::DateTime, timezone=localzone()) = setTimestamp(f, ZonedDateTime(ts, timezone))
7071

71-
function setTimestamp(f::DFGFactor, ts::DateTime)
72+
function setTimestamp(f::DFGFactor, ts::ZonedDateTime)
7273
return DFGFactor(f.label, ts, f.nstime, f.tags, f.solverData, f.solvable, getfield(f,:_variableOrderSymbols))
7374
end
7475

75-
function setTimestamp(f::DFGFactorSummary, ts::DateTime)
76+
function setTimestamp(f::DFGFactorSummary, ts::ZonedDateTime)
7677
return DFGFactorSummary(f.label, ts, f.tags, f._variableOrderSymbols)
7778
end
7879

src/services/DFGVariable.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,16 @@ Since the `timestamp` field is not mutable `setTimestamp` returns a new variable
162162
Use [`updateVariable!`](@ref) on the returened variable to update it in the factor graph if needed. Alternatively use [`setTimestamp!`](@ref).
163163
See issue #315.
164164
"""
165-
function setTimestamp(v::DFGVariable, ts::DateTime; verbose::Bool=true)
165+
function setTimestamp(v::DFGVariable, ts::ZonedDateTime; verbose::Bool=true)
166166
if verbose
167167
@warn "verbose=true: setTimestamp(::DFGVariable,...) creates a returns a new immutable DFGVariable object (and didn't change a distributed factor graph object), make sure you are using the right pointers: getVariable(...). See setTimestamp!(...) and note suggested use is at addVariable!(..., [timestamp=...]). See DFG #315 for explanation."
168168
end
169169
return DFGVariable(v.label, ts, v.nstime, v.tags, v.ppeDict, v.solverDataDict, v.smallData, v.dataDict, Ref(v.solvable))
170170
end
171171

172-
function setTimestamp(v::DFGVariableSummary, ts::DateTime; verbose::Bool=true)
172+
setTimestamp(v::AbstractDFGVariable, ts::DateTime, timezone=localzone(); verbose::Bool=true) = setTimestamp(v, ZonedDateTime(ts, timezone); verbose=verbose)
173+
174+
function setTimestamp(v::DFGVariableSummary, ts::ZonedDateTime; verbose::Bool=true)
173175
if verbose
174176
@warn "verbose=true: setTimestamp(::DFGVariableSummary,...) creates and returns a new immutable DFGVariable object (and didn't change a distributed factor graph object), make sure you are using the right pointers: getVariable(...). See setTimestamp!(...) and note suggested use is at addVariable!(..., [timestamp=...]). See DFG #315 for explanation."
175177
end

src/services/Serialization.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const TYPEKEY = "_type"
88
function packVariable(dfg::G, v::DFGVariable)::Dict{String, Any} where G <: AbstractDFG
99
props = Dict{String, Any}()
1010
props["label"] = string(v.label)
11-
props["timestamp"] = string(v.timestamp)
11+
props["timestamp"] = Dates.format(v.timestamp, "yyyy-mm-ddTHH:MM:SS.ssszzz")#string(v.timestamp)
1212
props["nstime"] = string(v.nstime.value)
1313
props["tags"] = JSON2.write(v.tags)
1414
props["ppeDict"] = JSON2.write(v.ppeDict)
@@ -25,7 +25,7 @@ end
2525

2626
function unpackVariable(dfg::G, packedProps::Dict{String, Any})::DFGVariable where G <: AbstractDFG
2727
label = Symbol(packedProps["label"])
28-
timestamp = DateTime(packedProps["timestamp"])
28+
timestamp = ZonedDateTime(packedProps["timestamp"])
2929
nstime = Nanosecond(get(packedProps, "nstime", 0))
3030
tags = JSON2.read(packedProps["tags"], Vector{Symbol})
3131
#TODO this will work for some time, but unpacking in an <: AbstractPointParametricEst would be lekker.
@@ -114,7 +114,7 @@ function packFactor(dfg::G, f::DFGFactor)::Dict{String, Any} where G <: Abstract
114114
# Construct the properties to save
115115
props = Dict{String, Any}()
116116
props["label"] = string(f.label)
117-
props["timestamp"] = string(f.timestamp)
117+
props["timestamp"] = Dates.format(f.timestamp, "yyyy-mm-ddTHH:MM:SS.ssszzz")#string(f.timestamp)
118118
props["nstime"] = string(f.nstime.value)
119119
props["tags"] = JSON2.write(f.tags)
120120
# Pack the node data
@@ -151,7 +151,7 @@ end
151151

152152
function unpackFactor(dfg::G, packedProps::Dict{String, Any})::DFGFactor where G <: AbstractDFG
153153
label = packedProps["label"]
154-
timestamp = DateTime(packedProps["timestamp"])
154+
timestamp = ZonedDateTime(packedProps["timestamp"])
155155
nstime = Nanosecond(get(packedProps, "nstime", 0))
156156
tags = JSON2.read(packedProps["tags"], Vector{Symbol})
157157

0 commit comments

Comments
 (0)