|
30 | 30 |
|
31 | 31 | import java.time.Instant; |
32 | 32 | import java.time.LocalDate; |
| 33 | +import java.time.LocalDateTime; |
| 34 | +import java.time.LocalTime; |
| 35 | +import java.time.ZonedDateTime; |
33 | 36 | import java.time.ZoneId; |
34 | 37 | import java.time.format.DateTimeFormatter; |
35 | 38 | import java.time.temporal.ChronoUnit; |
@@ -60,6 +63,12 @@ public Object processDateTime(Object input, DateTimeType inputType, |
60 | 63 | if (input == null || inputType == null) { |
61 | 64 | return null; |
62 | 65 | } |
| 66 | + // Fast path: same type, non-TZ-sensitive SQL types — no conversion needed |
| 67 | + if (inputType == outputType) { |
| 68 | + if (input instanceof java.sql.Date && inputType == DateTimeType.DATE) return input; |
| 69 | + if (input instanceof java.sql.Time && inputType == DateTimeType.TIME) return input; |
| 70 | + if (input instanceof java.sql.Timestamp && inputType == DateTimeType.TIMESTAMP) return input; |
| 71 | + } |
63 | 72 | try { |
64 | 73 | DingoDateTime internal = tierProcessor.convertInput(input, inputType); |
65 | 74 |
|
@@ -134,31 +143,135 @@ public ZoneId getStorageZone() { |
134 | 143 | } |
135 | 144 |
|
136 | 145 | public DingoDateTime dateAdd(DingoDateTime dateTime, long amount, ChronoUnit unit) { |
137 | | - ArithmeticOperations.AddOperation operation = new ArithmeticOperations.AddOperation(unit, amount); |
138 | | - |
139 | | - OperationResult result = (OperationResult) operation.execute(new DingoDateTime[]{dateTime}, getOutputZone()); |
| 146 | + if (dateTime.isTimeZoneSensitive()) { |
| 147 | + DingoDateTime.DingoTimestampTZ tzValue = (DingoDateTime.DingoTimestampTZ) dateTime; |
| 148 | + ZonedDateTime zdt = tzValue.getUtcValue().atZone(tzValue.getOriginalZone()); |
| 149 | + return new DingoDateTime.DingoTimestampTZ(zdt.plus(amount, unit).toInstant(), tzValue.getOriginalZone()); |
| 150 | + } |
| 151 | + Object value = dateTime.getValue(); |
| 152 | + if (value instanceof LocalDate) { |
| 153 | + return new DingoDateTime.DingoLocalDate(((LocalDate) value).plus(amount, unit)); |
| 154 | + } else if (value instanceof LocalDateTime) { |
| 155 | + return new DingoDateTime.DingoLocalDateTime(((LocalDateTime) value).plus(amount, unit)); |
| 156 | + } else if (value instanceof LocalTime) { |
| 157 | + return new DingoDateTime.DingoLocalTime(((LocalTime) value).plus(amount, unit)); |
| 158 | + } |
| 159 | + throw new DateTimeProcessingException("Unsupported type for add: " + value.getClass()); |
| 160 | + } |
140 | 161 |
|
141 | | - if (result.isSuccess() && result.getValue() instanceof DingoDateTime) { |
142 | | - return (DingoDateTime) result.getValue(); |
| 162 | + public DingoDateTime dateSubtract(DingoDateTime dateTime, long amount, ChronoUnit unit) { |
| 163 | + if (dateTime.isTimeZoneSensitive()) { |
| 164 | + DingoDateTime.DingoTimestampTZ tzValue = (DingoDateTime.DingoTimestampTZ) dateTime; |
| 165 | + ZonedDateTime zdt = tzValue.getUtcValue().atZone(tzValue.getOriginalZone()); |
| 166 | + return new DingoDateTime.DingoTimestampTZ(zdt.minus(amount, unit).toInstant(), tzValue.getOriginalZone()); |
143 | 167 | } |
| 168 | + Object value = dateTime.getValue(); |
| 169 | + if (value instanceof LocalDate) { |
| 170 | + return new DingoDateTime.DingoLocalDate(((LocalDate) value).minus(amount, unit)); |
| 171 | + } else if (value instanceof LocalDateTime) { |
| 172 | + return new DingoDateTime.DingoLocalDateTime(((LocalDateTime) value).minus(amount, unit)); |
| 173 | + } else if (value instanceof LocalTime) { |
| 174 | + return new DingoDateTime.DingoLocalTime(((LocalTime) value).minus(amount, unit)); |
| 175 | + } |
| 176 | + throw new DateTimeProcessingException("Unsupported type for subtract: " + value.getClass()); |
| 177 | + } |
144 | 178 |
|
145 | | - throw new DateTimeProcessingException("Date add operation failed: " |
146 | | - + (result.getErrorMessage() != null ? result.getErrorMessage() : "Unknown error")); |
| 179 | + // ------------------------------------------------------------------------- |
| 180 | + // Type-specialized extraction fast paths — bypass the full pipeline |
| 181 | + // for non-timezone-sensitive java.sql types (Date, Timestamp). |
| 182 | + // ------------------------------------------------------------------------- |
| 183 | + |
| 184 | + public Integer extractYear(java.sql.Date value) { |
| 185 | + return value == null ? null : value.toLocalDate().getYear(); |
147 | 186 | } |
148 | 187 |
|
149 | | - public DingoDateTime dateSubtract(DingoDateTime dateTime, long amount, ChronoUnit unit) { |
150 | | - ArithmeticOperations.SubtractOperation operation = new ArithmeticOperations.SubtractOperation(unit, amount); |
| 188 | + public Integer extractYear(java.sql.Timestamp value) { |
| 189 | + return value == null ? null : value.toLocalDateTime().getYear(); |
| 190 | + } |
151 | 191 |
|
152 | | - OperationResult result = (OperationResult) operation.execute(new DingoDateTime[]{dateTime}, getOutputZone()); |
| 192 | + public Integer extractMonth(java.sql.Date value) { |
| 193 | + return value == null ? null : value.toLocalDate().getMonthValue(); |
| 194 | + } |
153 | 195 |
|
154 | | - if (result.isSuccess() && result.getValue() instanceof DingoDateTime) { |
155 | | - return (DingoDateTime) result.getValue(); |
156 | | - } |
| 196 | + public Integer extractMonth(java.sql.Timestamp value) { |
| 197 | + return value == null ? null : value.toLocalDateTime().getMonthValue(); |
| 198 | + } |
157 | 199 |
|
158 | | - throw new DateTimeProcessingException("Date subtract operation failed: " |
159 | | - + (result.getErrorMessage() != null ? result.getErrorMessage() : "Unknown error")); |
| 200 | + public Integer extractDay(java.sql.Date value) { |
| 201 | + return value == null ? null : value.toLocalDate().getDayOfMonth(); |
| 202 | + } |
| 203 | + |
| 204 | + public Integer extractDay(java.sql.Timestamp value) { |
| 205 | + return value == null ? null : value.toLocalDateTime().getDayOfMonth(); |
| 206 | + } |
| 207 | + |
| 208 | + public Integer extractQuarter(java.sql.Date value) { |
| 209 | + return value == null ? null : (value.toLocalDate().getMonthValue() - 1) / 3 + 1; |
| 210 | + } |
| 211 | + |
| 212 | + public Integer extractQuarter(java.sql.Timestamp value) { |
| 213 | + return value == null ? null : (value.toLocalDateTime().getMonthValue() - 1) / 3 + 1; |
160 | 214 | } |
161 | 215 |
|
| 216 | + public Integer extractWeek(java.sql.Date value) { |
| 217 | + if (value == null) return null; |
| 218 | + return value.toLocalDate().get(java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR); |
| 219 | + } |
| 220 | + |
| 221 | + public Integer extractWeek(java.sql.Timestamp value) { |
| 222 | + if (value == null) return null; |
| 223 | + return value.toLocalDateTime().get(java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR); |
| 224 | + } |
| 225 | + |
| 226 | + public Integer extractHour(java.sql.Date value) { |
| 227 | + return 0; |
| 228 | + } |
| 229 | + |
| 230 | + public Integer extractHour(java.sql.Timestamp value) { |
| 231 | + return value == null ? 0 : value.toLocalDateTime().getHour(); |
| 232 | + } |
| 233 | + |
| 234 | + public Integer extractHour(java.sql.Time value) { |
| 235 | + return value == null ? 0 : value.toLocalTime().getHour(); |
| 236 | + } |
| 237 | + |
| 238 | + public Integer extractMinute(java.sql.Date value) { |
| 239 | + return 0; |
| 240 | + } |
| 241 | + |
| 242 | + public Integer extractMinute(java.sql.Timestamp value) { |
| 243 | + return value == null ? 0 : value.toLocalDateTime().getMinute(); |
| 244 | + } |
| 245 | + |
| 246 | + public Integer extractMinute(java.sql.Time value) { |
| 247 | + return value == null ? 0 : value.toLocalTime().getMinute(); |
| 248 | + } |
| 249 | + |
| 250 | + public Integer extractSecond(java.sql.Date value) { |
| 251 | + return 0; |
| 252 | + } |
| 253 | + |
| 254 | + public Integer extractSecond(java.sql.Timestamp value) { |
| 255 | + return value == null ? 0 : value.toLocalDateTime().getSecond(); |
| 256 | + } |
| 257 | + |
| 258 | + public Integer extractSecond(java.sql.Time value) { |
| 259 | + return value == null ? 0 : value.toLocalTime().getSecond(); |
| 260 | + } |
| 261 | + |
| 262 | + public Integer extractMillisecond(java.sql.Date value) { |
| 263 | + return 0; |
| 264 | + } |
| 265 | + |
| 266 | + public Integer extractMillisecond(java.sql.Timestamp value) { |
| 267 | + if (value == null) return 0; |
| 268 | + return value.toLocalDateTime().getNano() / 1_000_000; |
| 269 | + } |
| 270 | + |
| 271 | + // ------------------------------------------------------------------------- |
| 272 | + // Generic extraction methods (original, for Object/String inputs) |
| 273 | + // ------------------------------------------------------------------------- |
| 274 | + |
162 | 275 | public Integer extractYear(Object input) { |
163 | 276 | ExtractionOperations.ExtractFieldOperation operation = ExtractionOperations.year(); |
164 | 277 | DateTimeType inputType = inferInputType(input); |
|
0 commit comments