Skip to content

MID-11078 Fix false dateTime updates due to seconds normalization in admin GUI#583

Merged
1azyman merged 2 commits intomasterfrom
fix/MID-11078
Apr 9, 2026
Merged

MID-11078 Fix false dateTime updates due to seconds normalization in admin GUI#583
1azyman merged 2 commits intomasterfrom
fix/MID-11078

Conversation

@kay1313
Copy link
Copy Markdown
Contributor

@kay1313 kay1313 commented Mar 27, 2026

The admin GUI date picker operates at minute precision and drops seconds/milliseconds on submit.
The existing guard in XmlGregorianCalendarModel used GregorianCalendar.equals(...), which compares full calendar state (including timezone), not just the actual time value.

This caused false differences when:

-stored value contained seconds (e.g. 09:32:12),
-GUI round-trip produced 09:32:00,
-or calendars differed only in internal representation (e.g. timezone/configuration),
-even though both represented the same effective minute.
As a result, the GUI incorrectly overwrote values and preview showed spurious changes.

Solution

Replace strict GregorianCalendar.equals(...) with comparison of normalized minute-precision timestamps using getTimeInMillis() after stripping seconds and milliseconds.

This ensures:
-no change is produced when only GUI precision differs,
-false differences caused by calendar metadata (including timezone representation) are avoided,
-real differences in actual time are still detected.
In particular:
-real timezone differences → still cause update (correct)
-fake differences from calendar equality → no longer cause update (fixed)

@1azyman 1azyman self-requested a review March 31, 2026 14:39
Copy link
Copy Markdown
Member

@1azyman 1azyman left a comment

Choose a reason for hiding this comment

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

Hi @vanesa, can you please have a look at few comments I have for the tests? The fix in model seems to be fine otherwise. Thank you very much.


@AfterMethod
void restoreDefaultTimeZone() {
TimeZone.setDefault(originalDefaultTimeZone);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is probably not a good idea changing timezone for whole VM. Same below.


public class TestXmlGregorianCalendarModel extends AbstractGuiUnitTest {

private static final DatatypeFactory DF = datatypeFactory();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not necessary to setup your datafactory, we have util class that helps with XML gregorian calendar, check XmlTypeConverter.createXMLGregorianCalendar(...) and other methods.

}

private static Date minuteDate(int minute) {
GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("Europe/Prague"));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Probably nicer to call Calendar.getInstance(TimeZone.getTimeZone(...))

return calendar.getTime();
}

private static XMLGregorianCalendar storedFromDate(Date date) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here, use if possible XmlTypeConverter

}
}

private static final class SimpleModel implements IModel<XMLGregorianCalendar> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This class is unnecessary, you can use Model.of(object)

}

@Test
void testKeepStoredValueWhenGuiOnlyDropsSeconds() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This test seems to be way too complicated. Aren't we testing XmlGregorianCalendarModel whether it will NOT change value if model.setObject() is called with the same value as it's already in model (only that new value has seconds/millis zeroed?) Or am I missing something?


// Forces toGregorianCalendar() to return a calendar configuration that reproduces
// the old GregorianCalendar.equals(...) mismatch for the same normalized minute.
private static final class CalendarOverride extends XMLGregorianCalendar {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand why this is needed. Both params have the same date/time only types are different.

@kay1313
Copy link
Copy Markdown
Contributor Author

kay1313 commented Apr 8, 2026

1.)Replaced DatatypeFactory usage with XmlTypeConverter as suggested.
2.)Removed changing default JVM timezone; test now uses explicit timezone where needed.
3.)Updated to use Calendar.getInstance(TimeZone) as suggested.
4.)Removed SimpleModel. Model.of(...) cannot be used here because XMLGregorianCalendar is not Serializable, so replaced with a minimal inline IModel.

5.)The test was simplified where possible, but it still needs to reproduce a specific edge case.

The issue here is that two values can represent the same normalized minute, but their GregorianCalendar representations are not equal (GregorianCalendar.equals(...) returns false). The previous implementation relied on equals(), which caused incorrect replacement.

CalendarOverride is used to force this mismatch so the test actually reproduces the original failure. Without it, the test would also pass on master and would not verify the fix.

@1azyman 1azyman merged commit 9bba377 into master Apr 9, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants