Skip to content

KAFKA-18585 Fix fail test ValuesTest#shouldConvertDateValues #18611

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

Merged
merged 2 commits into from
Jan 21, 2025

Conversation

m1a2st
Copy link
Collaborator

@m1a2st m1a2st commented Jan 18, 2025

Jira: https://issues.apache.org/jira/browse/KAFKA-18585

The test scenario involves inputting dates in ISO8601 format yyyy-MM-dd. At this point, the time information is already lost. Then in the Values#convertToDate method, the date conversion is performed using string manipulation, without any timezone information being provided. Therefore, it's expected and normal behavior that the time gets converted to 00:00:00.

The solution is to explicitly convert Java Date objects, which internally store UTC timestamps, to UTC+0 timezone

before:
CleanShot 2025-01-19 at 00 13 28@2x
after:
CleanShot 2025-01-19 at 00 14 17@2x

Committer Checklist (excluded from commit message)

  • Verify design and implementation
  • Verify test coverage and CI build status
  • Verify documentation (including upgrade notes)

@github-actions github-actions bot added triage PRs from the community connect tests Test fixes (including flaky tests) small Small PRs labels Jan 18, 2025
@github-actions github-actions bot removed the triage PRs from the community label Jan 20, 2025
@m1a2st
Copy link
Collaborator Author

m1a2st commented Jan 20, 2025

Hello @AndrewJSchofield, if you have free cycle, PTAL

java.util.Date d3 = Values.convertToDate(Date.SCHEMA, LocalDate.ofEpochDay(days).format(DateTimeFormatter.ISO_LOCAL_DATE));
assertEquals(currentDate, d3);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must be missing something here so please help me understand the following:

Java's util.Date is timezone agnostic (it's always epochs in UTC timezone) until you want to print it (where you can format it). Hence, the currentDate here should already be in UTC timezone. And the actual value from LocalDate.ofEpochDay(days).format(DateTimeFormatter.ISO_LOCAL_DATE) should also be in UTC. So, where is the disconnect here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'm not sure either. But I can believe it's possible to write a test that is timezone-dependent.

@AndrewJSchofield
Copy link
Member

Digging into this further, I would say that the behaviour for some of these tests with respect to timezones is incorrect, or at least unwise. I am not convinced by this patch, but I will dig into it further and give a more concrete answer shortly.

java.util.Date d3 = Values.convertToDate(Date.SCHEMA, LocalDate.ofEpochDay(days).format(DateTimeFormatter.ISO_LOCAL_DATE));
assertEquals(currentDate, d3);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@divijvaidya is correct that java.util.Date is timezone-agnostic. However, the LocalDate here is timezone-ignorant and the timezone offset is not accounted for. The methods available for manipulating dates and times with timezones are a bit limited, and I think that it's best to stop using LocalDate.ofEpochDay(long) and moving to LocalDateTime.ofInstant(Instant, ZoneId).

I suggest replacing the first line of the method with:

        LocalDateTime localTime = LocalDateTime.now();
        LocalDateTime localTimeTruncated = localTime.truncatedTo(ChronoUnit.DAYS);
        ZoneOffset zoneOffset = ZoneId.systemDefault().getRules().getOffset(localTime);
        java.util.Date current = new java.util.Date(localTime.toEpochSecond(zoneOffset) * 1000);

And then the check becomes:

        // ISO8601 strings - accept a string matching pattern "yyyy-MM-dd"
        java.util.Date d3 = Values.convertToDate(Date.SCHEMA, LocalDate.ofEpochDay(days).format(DateTimeFormatter.ISO_LOCAL_DATE));
        LocalDateTime date3 = LocalDateTime.ofInstant(Instant.ofEpochMilli(d3.getTime()), ZoneId.systemDefault());
        assertEquals(localTimeTruncated, date3);

I tried this with various timezones locally and it seems to work properly. Essentially, the time information is discarded in a way that a person in the timezone would expect looking at a clock.

Copy link
Collaborator Author

@m1a2st m1a2st Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can observe that when java.util.Date performs equals comparison, it takes timezone into account. Therefore, the equals comparison will yield different results under different timezones. In my case, being in UTC+8, it results in an 8-hour difference.

https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/Date.java#L1210

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@m1a2st Are you happy that this works now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, using LocalDateTime makes sense to me.

@AndrewJSchofield AndrewJSchofield merged commit b4674c0 into apache:trunk Jan 21, 2025
9 checks passed
pranavt84 pushed a commit to pranavt84/kafka that referenced this pull request Jan 27, 2025
airlock-confluentinc bot pushed a commit to confluentinc/kafka that referenced this pull request Jan 27, 2025
manoj-mathivanan pushed a commit to manoj-mathivanan/kafka that referenced this pull request Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
connect small Small PRs tests Test fixes (including flaky tests)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants