-
Notifications
You must be signed in to change notification settings - Fork 191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add optional chrono support (Uuid::to_utc() -> Option<DateTime<Utc>>
)
#405
Conversation
Adds feature-gated support for converting v1-embedded timestamps to a `chrono::DateTime<Utc>` via `Uuid::to_utc`. Relies on underlying functionality in `Uuid::to_timestamp` and mimics its signature. Attempted to match existing design for feature-gated components (e.g. `slog_support` module) as much as possible. Tests cover post-1970 dates, pre-1970 dates, and check that v3/v4/v5 variants return None.
Thanks for the PR @jonathanstrong! This looks like a well tested piece of code, however I don’t think we should necessarily provide and support this in |
You're welcome - happy to help! If I may, I'd like to present a more detailed case for its inclusion, which perhaps should have accompanied the original pull request: Imagine you're coming at this fresh: you have some V1 UUIDs with embedded timestamps, and you need to get them out. Pretty soon you realize the time comes in an unusual, esoteric format (as timestamps go) -- the number of 100ns intervals since 1582-10-15. Where would you go looking for an existing implementation to convert it to something that's actually usable? If you doubt that the V1 timestamp format is the ugly duckling here, consider that The "unix" timestamp passed to In my mind, the only other candidate for housing this functionality, other than my application, is in And on a related topic, this is Finally, you mentioned the pull request is well-tested. I appreciate the praise. But I'll admit, I'm far from a TDD-evangelizing, code coverage-measuring Ned Flanders of testing. It's because I've got scars from all the times I got dates and times wrong. Which brings me to my last point: it's not rocket science to convert the number of 100ns intervals since 1582 to the number of nanoseconds since 1970, but it's relatively easy to get wrong, and it takes a few minutes of careful concentration. That's exactly the type of code you want in a library. I'll be fine, I've written my implementation and I can use it from now on. But for the next guy coming along, asking himself "but why 1582-10-15?", consider saving him the trouble. Thanks for your consideration and your hard work on this great library. (edit: just realized I posted this with a work account. I am the original requestor.) |
Thanks for the extra details @jonathanstrong It sounds like we could do better with our v1 support (I don't personally use v1 UUIDs). The main concern I have is introducing a dependency on What if we took this opportunity to change pub struct Timestamp {
timestamp: u64,
counter: u16
}
impl Uuid {
pub fn new_v1<T>(
context: &T,
ts: Timestamp,
node_id: &[u8],
) -> Result<Self, crate::BytesError>
where
T: ClockSequence,
{
..
}
pub fn to_timestamp(&self) -> Option<Timestamp> { .. }
}
impl Timestamp {
pub fn from_rfc4122(ts: u64, counter: u16) -> Self { .. }
pub fn from_unix(secs: u64, nanos: u32) -> Self { .. }
pub fn to_rfc4122(&self) -> (u64, u16) { .. }
pub fn to_unix(&self) -> (u64, u32) { .. }
} That way we could be consistent in the shape of the timestamp passed in and out, and manage the trickier conversion from RFC4122 timestamps into UNIX timestamps for wrapping up in What do you think? |
It might need a little more thought with the |
Could be: pub struct Timestamp {
timestamp: u64,
counter: u16
}
impl Uuid {
pub fn new_v1(
ts: Timestamp,
node_id: &[u8],
) -> Result<Self, crate::BytesError> {
..
}
pub fn to_timestamp(&self) -> Option<Timestamp> { .. }
}
impl Timestamp {
pub fn from_rfc4122(ts: u64, counter: u16) -> Self { .. }
pub fn from_unix<T: ClockSequence>(secs: u64, nanos: u32, context: &T) -> Self { .. }
pub fn to_rfc4122(&self) -> (u64, u16) { .. }
pub fn to_unix(&self) -> (u64, u32) { .. }
} |
The alternative api proposed by @KodrAus is a huge improvement over the status quo, from my perspective. I'd be happy to file an alternative pull request matching it, but it may take a few days for me to get to it. On a related note, do you have any further information about the changes coming to |
Draft implementation of improved timestamp api discussed in github issue uuid-rs#405. Establishes new `Timestamp` struct in v1 mod that stores the (timestamp, counter) values that had been used previously. The core rationale/improvement is that `Timestamp` offers several conversion routines to/from RFC4122 and unix timestamp formats. The RFC4122 timestamp format in V1 UUIDs is relatively obscure -- this provides ready access to unix timestamp formats instead. The design also prevents possible confusion/misuse by use of clearly named constructors and ample documentation about the various formats in play. Tests covering previously existing functionality updated to reflect new api and passing. New functionality untested. Moved `Uuid::to_timestamp` from impl in src/lib.rs to v1 mod as it requires access to the new `Timestamp` struct defined in v1. Noting as this places `to_timestamp` behind the v1 feature gate, unlike prior to the change.
fyi - pushed draft implementation on a different branch here. Still needs tests, but thought I would solicit early feedback and check-in. It follows the proposed api discussed here pretty closely. |
Draft implementation of improved timestamp api discussed in github issue #405. Establishes new `Timestamp` struct in v1 mod that stores the (timestamp, counter) values that had been used previously. The core rationale/improvement is that `Timestamp` offers several conversion routines to/from RFC4122 and unix timestamp formats. The RFC4122 timestamp format in V1 UUIDs is relatively obscure -- this provides ready access to unix timestamp formats instead. The design also prevents possible confusion/misuse by use of clearly named constructors and ample documentation about the various formats in play. Tests covering previously existing functionality updated to reflect new api and passing. New functionality untested. Moved `Uuid::to_timestamp` from impl in src/lib.rs to v1 mod as it requires access to the new `Timestamp` struct defined in v1. Noting as this places `to_timestamp` behind the v1 feature gate, unlike prior to the change.
Hi @jonathanstrong 👋 Thanks for working on this! I'm working through some breaking changes and cleanups in #427. Your proposed draft implementation looks good to me! So I've cherry-picked it into #427 and made a few tweaks, which you can see here. |
427: Breaking API features and refactoring for `0.8` r=kinggoesgaming a=KodrAus **I'm submitting a(n)** (|feature|refactor|) # Description ## Modules and Errors This PR is a broad refactoring of our error types and module layout. The general pattern I've gone for is: - Define specific error types in submodules. These are currently private. - Collect these specific error types in an opaque root `Error`. All methods return this single `Error` type so it's easier for consumers to carry `uuid::Error`s in their own code. It'll also include some implementations for open PRs as we've been discussing. I imagine we'll want to spend time working through these changes :) I've hidden our `prelude` module for now, because I'm not sure it's something we'll want to stabilize with (it's only got a few bits in it afterall). ## 128bit support Re-enables support for 128-bit numbers in the form of constructors on `Uuid`, following the pattern that method names without an endian suffix are BE. ## No-std Refactors our `no-std` support so we always mark the crate as `no-std` so our std imports are always the same. This simplifies our std/core support so we need fewer modules. ## Timestamps Includes the design proposed in #405 for timestamp support originally implemented by @jonathanstrong. # Related Issue(s) - #406 # Related PR(s) - #405 - #416 Co-authored-by: Ashley Mannix <[email protected]> Co-authored-by: Jonathan Strong <[email protected]>
Alrighty, now that #427 is merged I think we can close this one, since it includes an implementation of this feature. Thanks again for working on this @jonathanstrong! |
@KodrAus definitely - appreciate you working with me to refine the idea and merging the code! Huge improvement for working with v1 embedded timestamps. |
I'm submitting a feature.
Description
Adds feature-gated support for converting v1-embedded timestamps to a
chrono::DateTime<Utc>
viaUuid::to_utc
. Relies on underlying functionality inUuid::to_timestamp
and mimics its signature. Attempted to match existing design for feature-gated components (e.g.slog_support
module) as much as possible. Tests cover post-1970 dates, pre-1970 dates, and check that v3/v4/v5 variants return None.Rationale
chrono is ubiquitous in rust ecosystem. It's convenient to return the time in a widely-used and well-designed datetime type.