Skip to content
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

UUIDUtil.extractTimestamp() is broken for versions 1 and 6 #105

Closed
gabrielbalan opened this issue May 17, 2024 · 1 comment · Fixed by #106
Closed

UUIDUtil.extractTimestamp() is broken for versions 1 and 6 #105

gabrielbalan opened this issue May 17, 2024 · 1 comment · Fixed by #106

Comments

@gabrielbalan
Copy link

gabrielbalan commented May 17, 2024

UUIDUtil.extractTimestamp() returns bad result for Generators.timeBasedGenerator() and Generators.timeBasedReorderedGenerator() in version 5.0.0.

The javadoc says

@return timestamp in milliseconds (since Epoch), or 0 if type does not support timestamps

Which makes me think I should be able to compare the milliseconds returned by UUIDUtil.extractTimestamp() against System.currentTimeMillis().

Here's the reproducer:

    @Test
    public void testExtractTimestampFromTimeBasedUUID() {
        testExtractTimestamp(Generators.timeBasedGenerator());
    }
    @Test
    public void testExtractTimestampFromTimeBasedReorderedUUID() {
        testExtractTimestamp(Generators.timeBasedReorderedGenerator());
    }
    @Test
    public void testExtractTimestampFromTimeBasedEpochdUUID() {
        testExtractTimestamp(Generators.timeBasedEpochGenerator());
    }

    public void testExtractTimestamp( NoArgGenerator generator){

        long before = System.currentTimeMillis();
        UUID timeBasedUUID =  generator.generate();
        long after = System.currentTimeMillis();

        long extracted = UUIDUtil.extractTimestamp(timeBasedUUID);
        if(extracted < before || extracted > after)
        {
            System.err.println("System.currentTimeMillis() before generate UUID: " + before);
            System.err.println("System.currentTimeMillis() after generate UUID:  " + after);
            System.err.println("UIDUtil.extractTimestamp from generated UUID:    " + extracted);
        }
        Assert.assertTrue(extracted>=before);
        Assert.assertTrue(extracted<=after);
    }

And here is the output:

System.currentTimeMillis() before generate UUID:  1715956528376
System.currentTimeMillis() after generate UUID:   1715956528376
UIDUtil.extractTimestamp from generated UUID:    139352493283760061

System.currentTimeMillis() before generate UUID:  1715956528397
System.currentTimeMillis() after generate UUID:   1715956528397
UIDUtil.extractTimestamp from generated UUID:    139352493283970062

I believe that UUIDUtil.extractTimestamp() returns

  • milliseconds since midnight, January 1, 1970 UTC (unix epoch) for timeBasedEpochGenerator;
  • hundreds of nanoseconds since since 00:00:00.00,15 October 1582 (the date of Gregorian reform to the Christian calendar) for timeBasedGenerator and timeBasedReorderedGenerator.

Therefore the fix for the two affected formats should be to divide by 10'000 and subtract the time-distance (in ms) between the gregorian epoch and the unix epoch.

@cowtowncoder
Copy link
Owner

No, this sounds like a plain old Bug to me: intent is to get 64-bit long timestamp Java world is used to. So if (and when) 100 nanos-style timestamp is not being converted that'd be a flaw.

And your suggestion of fix sounds correct.

@cowtowncoder cowtowncoder changed the title UUIDUtil.extractTimestamp() is broken UUIDUtil.extractTimestamp() is broken for versions 1 and 6 May 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants