Background & Current State
In several recent PRs introducing or improving date/time converters (e.g., SqlTime*, Year*, OffsetDateTime*, SqlDate*, etc.), we noticed that there is some duplicated boilerplate code, along with inconsistencies in edge-case handling:
1. Inconsistent format extraction and empty string handling
-
Some implementations check StringUtils.isEmpty(format) and normalize it to null, while others pass empty strings directly downstream, which can lead to unexpected parsing errors.
-
The format extraction logic is repeatedly implemented across different converters:
String format = null;
if (contentProperty != null && contentProperty.getDateTimeFormatProperty() != null) {
format = contentProperty.getDateTimeFormatProperty().getFormat();
}
2. Layering issue with 1904 windowing check
Currently, DateUtils contains the following method:
public static boolean isDate1904(ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration)
This causes the low-level, general-purpose date utility class to directly depend on framework-level metadata models (ExcelContentProperty and GlobalConfiguration), introducing architectural coupling.
Proposed Options
To standardize the implementation for future date/time types, eliminate boilerplate code, and unify edge-case behaviors, I suggest we tidy up this bit of logic. Two main directions are being considered:
Option A: Centralize into DateUtils (Keep the status quo)
Add getDateTimeFormat(ExcelContentProperty) to DateUtils, keeping it at the same level as the existing isDate1904.
- Pros: Minimal changes required; no new class hierarchy introduced; keeps the codebase flat.
- Cons: The low-level utility class continues to take on framework-level metadata resolution, causing its responsibilities to bloat further.
Option B: Introduce an abstract base class AbstractDateTimeConverter<T>
-
Encapsulate getDateFormat(ExcelContentProperty) and isDate1904(ExcelContentProperty, GlobalConfiguration) within the base class.
-
Since DateUtils.isDate1904 was introduced recently and has not yet been included in any official release, it can be directly deprecated or removed without backwards-compatibility baggage. (already in the 2.1.0 release candidate)
-
Concrete converter subclasses can focus solely on core data conversion logic.
-
Pros:
- Unifies edge-case behaviors.
- Keeps metadata resolution visible only to date/time converters, preserving the purity and single responsibility of
DateUtils.
-
Cons: Introduces a new abstraction layer and inheritance hierarchy.
Feedback Welcome
Which option do you prefer? Or do you have alternative suggestions? Feel free to share your thoughts below!
+1 [Option A / Option B] {additional information - optional}
-1 [Option A / Option B] {reason}
+0 [Alternative proposals or thoughts]
Background & Current State
In several recent PRs introducing or improving date/time converters (e.g.,
SqlTime*,Year*,OffsetDateTime*,SqlDate*, etc.), we noticed that there is some duplicated boilerplate code, along with inconsistencies in edge-case handling:1. Inconsistent format extraction and empty string handling
Some implementations check
StringUtils.isEmpty(format)and normalize it tonull, while others pass empty strings directly downstream, which can lead to unexpected parsing errors.The format extraction logic is repeatedly implemented across different converters:
2. Layering issue with 1904 windowing check
Currently,
DateUtilscontains the following method:This causes the low-level, general-purpose date utility class to directly depend on framework-level metadata models (
ExcelContentPropertyandGlobalConfiguration), introducing architectural coupling.Proposed Options
To standardize the implementation for future date/time types, eliminate boilerplate code, and unify edge-case behaviors, I suggest we tidy up this bit of logic. Two main directions are being considered:
Option A: Centralize into
DateUtils(Keep the status quo)Add
getDateTimeFormat(ExcelContentProperty)toDateUtils, keeping it at the same level as the existingisDate1904.Option B: Introduce an abstract base class
AbstractDateTimeConverter<T>Encapsulate
getDateFormat(ExcelContentProperty)andisDate1904(ExcelContentProperty, GlobalConfiguration)within the base class.Since(already in the 2.1.0 release candidate)DateUtils.isDate1904was introduced recently and has not yet been included in any official release, it can be directly deprecated or removed without backwards-compatibility baggage.Concrete converter subclasses can focus solely on core data conversion logic.
Pros:
DateUtils.Cons: Introduces a new abstraction layer and inheritance hierarchy.
Feedback Welcome
Which option do you prefer? Or do you have alternative suggestions? Feel free to share your thoughts below!
+1 [Option A / Option B] {additional information - optional}-1 [Option A / Option B] {reason}+0 [Alternative proposals or thoughts]