@@ -155,9 +155,7 @@ private void SetNumericMeterValue(ISOSpatialRow isoSpatialRow, NumericWorkingDat
155155 {
156156 //There are multiple product allocations for the device element
157157 //Find the product allocation that governs this timestamp
158- ISOProductAllocation relevantPan = productAllocationsForDeviceElement . FirstOrDefault ( p => Offset ( p . AllocationStamp . Start ) <= spatialRecord . Timestamp &&
159- ( p . AllocationStamp . Stop == null ||
160- Offset ( p . AllocationStamp . Stop ) >= spatialRecord . Timestamp ) ) ;
158+ ISOProductAllocation relevantPan = productAllocationsForDeviceElement . FirstOrDefault ( p => GovernsTimestamp ( p , spatialRecord ) ) ;
161159 if ( relevantPan == null )
162160 {
163161 //We couldn't correlate strictly based on time. Check for a more general match on date alone before returning null.
@@ -187,6 +185,50 @@ private void SetNumericMeterValue(ISOSpatialRow isoSpatialRow, NumericWorkingDat
187185 }
188186 }
189187
188+ /// <summary>
189+ /// Return true if the product allocation governs the timestamp for the SpatialRecord
190+ /// </summary>
191+ private bool GovernsTimestamp ( ISOProductAllocation p , SpatialRecord spatialRecord )
192+ {
193+ DateTime ? allocationStart = Offset ( p . AllocationStamp . Start ) ;
194+ DateTime ? allocationStop = p . AllocationStamp . Stop != null ? Offset ( p . AllocationStamp . Stop ) : null ;
195+ DateTime spatialRecordTimestampUtc = ToUtc ( spatialRecord . Timestamp ) ;
196+
197+ return
198+ ToUtc ( allocationStart ) <= spatialRecordTimestampUtc &&
199+ ( p . AllocationStamp . Stop == null || ToUtc ( allocationStop ) >= spatialRecordTimestampUtc ) ;
200+ }
201+
202+ // Comparing DateTime values with different Kind values leads to inaccurate results.
203+ // Convert DateTimes to UTC if possible before comparing them
204+ private DateTime ? ToUtc ( DateTime ? nullableDateTime )
205+ {
206+ return nullableDateTime . HasValue ? ToUtc ( nullableDateTime . Value ) : nullableDateTime ;
207+ }
208+
209+ private DateTime ToUtc ( DateTime dateTime )
210+ {
211+ if ( dateTime . Kind == DateTimeKind . Utc )
212+ return dateTime ;
213+
214+ DateTime utc ;
215+ if ( dateTime . Kind == DateTimeKind . Local )
216+ {
217+ utc = dateTime . ToUniversalTime ( ) ;
218+ }
219+ else if ( dateTime . Kind == DateTimeKind . Unspecified && _taskDataMapper . GPSToLocalDelta . HasValue )
220+ {
221+ utc = new DateTime ( dateTime . AddHours ( - _taskDataMapper . GPSToLocalDelta . Value ) . Ticks , DateTimeKind . Utc ) ;
222+ }
223+ else
224+ {
225+ // Nothing left to try; return original value
226+ utc = dateTime ;
227+ }
228+
229+ return utc ;
230+ }
231+
190232 private DateTime ? Offset ( DateTime ? input )
191233 {
192234 if ( _effectiveTimeZoneOffset . HasValue && input . HasValue )
0 commit comments