Conversation
- Add associated constants with min/max limits to `ua::DateTime` - Check min/max limits when converting `time::OffsetDateTime` into `ua::DateTime`.
| pub fn to_utc(&self) -> Option<time::OffsetDateTime> { | ||
| use open62541_sys::{UA_DATETIME_UNIX_EPOCH, UA_DATETIME_USEC}; | ||
|
|
||
| // TODO: How to handle values that are out of range? |
There was a problem hiding this comment.
Since out-of-range values should never be sent over OPC UA, we can treat them as an exception. I would not panic, however, because those values are still runtime values from another system.
That being said, I'd treat them similar to the possible error from from_unix_timestamp_nanos() at the end of the function, i.e. by returning None.
There was a problem hiding this comment.
According to the spec out of range values should be clamped for encoding, i.e. either 0 (too low) or i64::MAX (too high):
https://reference.opcfoundation.org/Core/Part6/v105/docs/5.2.2.5
🤔
There was a problem hiding this comment.
So DateTime::MAX should never be sent over the wire. Strange rules.
There was a problem hiding this comment.
Yeah, that's how I read it, too—when the value is equal to 9999-12-31T11:59:59Z or later, then send i64::MAX (i.e. 9_223_372_036_854_775_807 instead of 2_650_466_915_990_000_000).
Similarly, for 1601-01-01T12:00:00Z or earlier, there is also the ambiguity that we can't know whether the value was exactly that time (encoded as 0) or earlier (also encoded as 0).
There was a problem hiding this comment.
That said, I think we have to handle this case specially, i.e. we should have the following conditions:
value < 0→None(not a valid value)value == 0→Some(Self::MIN), but it may have been clamped0 < value && value < 2_650_466_915_990_000_000→Some(…)2_650_466_915_990_000_000 <= value && value < 9_223_372_036_854_775_807→None(not a valid value)value == 9_223_372_036_854_775_807→Some(Self::MAX), but it may have been clamped
There was a problem hiding this comment.
We could expose the "possibly clamped" state in the return type, either as None, Some(…), or use a third state with an appropriate enum variant.
On the other hand, since time::OffsedDateTime can represent times outside the range of 1601-01-01 and 9999-12-31 (the latter with feature flag large-dates), we could accept such values when we receive them (marked with "not a valid value" above)—be conservative in what you send, be liberal in what you accept.
So, we could leave it to from_unix_timestamp_nanos() to deal with it, possibly only handling the value of i64::MAX explicitly because that has special meaning and may mean 9999-12-31T11:59:59Z instead (in which case, I'd probably return None).
| pub fn to_utc(&self) -> Option<time::OffsetDateTime> { | ||
| use open62541_sys::{UA_DATETIME_UNIX_EPOCH, UA_DATETIME_USEC}; | ||
|
|
||
| // TODO: How to handle values that are out of range? |
There was a problem hiding this comment.
Since out-of-range values should never be sent over OPC UA, we can treat them as an exception. I would not panic, however, because those values are still runtime values from another system.
That being said, I'd treat them similar to the possible error from from_unix_timestamp_nanos() at the end of the function, i.e. by returning None.
| /// Maximum value. | ||
| /// | ||
| /// See also: <https://reference.opcfoundation.org/Core/Part6/v105/docs/5.2.2.5> | ||
| pub const MAX: Self = Self(2_650_467_743_990_000_000); |
There was a problem hiding this comment.
Where does this exact value come from? Is it the number of 100 nanosecond intervals that matches 9999-12-31 23:59:59 UTC? Maybe we can add a comment or otherwise make it clearer what the value represents.
| /// Minimum UTC timestamp. | ||
| /// | ||
| /// See also: <https://reference.opcfoundation.org/Core/Part6/v105/docs/5.2.2.5> | ||
| #[cfg(feature = "time")] |
There was a problem hiding this comment.
You can move all the individually guarded attributes and method to_utc() to a separate impl block. This way, we'd only need one guard pragma, making it clearer what belongs together.
ua::DateTimetime::OffsetDateTimeintoua::DateTime.