3737import static org .tools4j .time .base .Allocation .Type .RESULT ;
3838import static org .tools4j .time .base .TimeFactors .MILLIS_PER_SECOND ;
3939import static org .tools4j .time .base .TimeFactors .NANOS_PER_MILLI ;
40+ import static org .tools4j .time .validate .DateValidator .isValidDate ;
41+ import static org .tools4j .time .validate .TimeValidator .isValidTimeWithMillis ;
4042
4143/**
4244 * Packs a date/time value (year, month, day, hour, minute, second, millis) into a single long. Packing and unpacking
43- * can be done with or without date/time validation using different {@link #validationMethod() validation methods}.
44- * A {@link #DECIMAL} and a {@link #BINARY} packing is supported and both packings preserve the natural date ordering,
45- * that is, if the packed longs are sorted then the corresponding date/time values are also sorted. Packing and
46- * unpacking of null values is supported via {@link #packNull()} and {@link #unpackNull(long)}.
45+ * can be done with or without date/time validation using different {@linkplain #validationMethod() validation methods}.
46+ * A {@linkplain #DECIMAL} and a {@linkplain #BINARY} packing is supported and both packings preserve the natural date
47+ * ordering, that is, if the packed longs are sorted then the corresponding date/time values are also sorted. Packing
48+ * and unpacking of null values is supported via {@link #packNull()} and {@link #unpackNull(long)}.
4749 * <p>
4850 * <i>Examples:</i>
4951 * <ul>
50- * <li>{@link #DECIMAL} packing for a date/time value 21-Jan-2017 14:15:16.170 is 20170121141516170</li>
51- * <li>{@link #BINARY} packing uses shifts to pack the date/time parts which is more efficient but the result is not
52- * easily human-readable</li>
52+ * <li>{@linkplain #DECIMAL} packing for a date/time value 21-Jan-2017 14:15:16.170 is 20170121141516170</li>
53+ * <li>{@linkplain #BINARY} packing uses shifts to pack the date/time parts which is more efficient but the result
54+ * is not easily human-readable</li>
5355 * </ul>
5456 * @see #valueOf(Packing, ValidationMethod)
5557 * @see #BINARY
@@ -64,8 +66,9 @@ public interface DateTimePacker {
6466 long pack (int year , int month , int day );
6567 long pack (int year , int month , int day , int hour , int minute , int second );
6668 long pack (int year , int month , int day , int hour , int minute , int second , int milli );
67- long pack (int packedDate , Packing datePacking , int packedTime , TimePacker timePacker );
68- long pack (int packedDate , Packing datePacking , int packedMilliTime , MilliTimePacker milliTimePacker );
69+ long packFromDateAndTime (int packedDate , Packing datePacking , int packedTime , Packing timePacking );
70+ long packFromDateAndMilliTime (int packedDate , Packing datePacking , int packedMilliTime , Packing milliTimePacking );
71+ long packFromDateTime (long packedDateTime , Packing dateTimePacking );
6972 int unpackYear (long packed );
7073 int unpackMonth (long packed );
7174 int unpackDay (long packed );
@@ -82,6 +85,10 @@ public interface DateTimePacker {
8285 long packEpochMilli (long millisSinceEpoch );
8386 long unpackEpochMilli (long packed );
8487
88+ boolean isValid (long packed );
89+ long validate (long packed );
90+ long validate (long packed , ValidationMethod validationMethod );
91+
8592 /**
8693 * Returns a date/time packer that performs no validation.
8794 * @param packing the packing type for the returned packer
@@ -127,23 +134,38 @@ default long pack(final int year, final int month, final int day,
127134 }
128135
129136 @ Override
130- default long pack (final int packedDate , final Packing datePacking ,
131- final int packedTime , final TimePacker timePacker ) {
132- final DatePacker datePacker = DatePacker .valueOf (datePacking , validationMethod ());
137+ default long packFromDateAndTime (final int packedDate , final Packing datePacking ,
138+ final int packedTime , final Packing timePacking ) {
139+ final DatePacker dp = DatePacker .valueOf (datePacking , validationMethod ());
140+ final TimePacker tp = TimePacker .valueOf (timePacking , validationMethod ());
133141 return pack (
134- datePacker .unpackYear (packedDate ), datePacker .unpackMonth (packedDate ), datePacker .unpackDay (packedDate ),
135- timePacker .unpackHour (packedTime ), timePacker .unpackMinute (packedTime ), timePacker .unpackSecond (packedTime )
142+ dp .unpackYear (packedDate ), dp .unpackMonth (packedDate ), dp .unpackDay (packedDate ),
143+ tp .unpackHour (packedTime ), tp .unpackMinute (packedTime ), tp .unpackSecond (packedTime )
136144 );
137145 }
138146
139147 @ Override
140- default long pack (final int packedDate , final Packing datePacking ,
141- final int packedMilliTime , final MilliTimePacker milliTimePacker ) {
142- final DatePacker datePacker = DatePacker .valueOf (datePacking , validationMethod ());
148+ default long packFromDateAndMilliTime (final int packedDate , final Packing datePacking ,
149+ final int packedMilliTime , final Packing milliTimePacking ) {
150+ final DatePacker dp = DatePacker .valueOf (datePacking , validationMethod ());
151+ final MilliTimePacker mtp = MilliTimePacker .valueOf (milliTimePacking , validationMethod ());
143152 return pack (
144- datePacker .unpackYear (packedDate ), datePacker .unpackMonth (packedDate ), datePacker .unpackDay (packedDate ),
145- milliTimePacker .unpackHour (packedMilliTime ), milliTimePacker .unpackMinute (packedMilliTime ),
146- milliTimePacker .unpackSecond (packedMilliTime ), milliTimePacker .unpackMilli (packedMilliTime )
153+ dp .unpackYear (packedDate ), dp .unpackMonth (packedDate ), dp .unpackDay (packedDate ),
154+ mtp .unpackHour (packedMilliTime ), mtp .unpackMinute (packedMilliTime ),
155+ mtp .unpackSecond (packedMilliTime ), mtp .unpackMilli (packedMilliTime )
156+ );
157+ }
158+
159+ @ Override
160+ default long packFromDateTime (final long packedDateTime , final Packing dateTimePacking ) {
161+ if (dateTimePacking == packing () && validationMethod () == ValidationMethod .UNVALIDATED ) {
162+ return packedDateTime ;
163+ }
164+ final DateTimePacker dtp = DateTimePacker .valueOf (dateTimePacking , validationMethod ());
165+ return pack (
166+ dtp .unpackYear (packedDateTime ), dtp .unpackMonth (packedDateTime ), dtp .unpackDay (packedDateTime ),
167+ dtp .unpackHour (packedDateTime ), dtp .unpackMinute (packedDateTime ),
168+ dtp .unpackSecond (packedDateTime ), dtp .unpackMilli (packedDateTime )
147169 );
148170 }
149171
@@ -184,6 +206,33 @@ default long unpackEpochMilli(final long packed) {
184206 return Epoch .valueOf (validationMethod ()).toEpochMilli (packed , this );
185207 }
186208
209+ @ Override
210+ default boolean isValid (final long packed ) {
211+ return packed != INVALID && (packed == NULL || (
212+ isValidDate (unpackDay (packed ), unpackMonth (packed ), unpackDay (packed )) &&
213+ isValidTimeWithMillis (unpackHour (packed ), unpackMinute (packed ), unpackSecond (packed ), unpackMilli (packed )))
214+ );
215+ }
216+
217+ @ Override
218+ default long validate (final long packed ) {
219+ return validate (packed , validationMethod ());
220+ }
221+
222+ @ Override
223+ default long validate (final long packed , final ValidationMethod validationMethod ) {
224+ if (packed == NULL || packed == INVALID || validationMethod == ValidationMethod .UNVALIDATED ) {
225+ return packed ;
226+ }
227+ final DateValidator dv = validationMethod .dateValidator ();
228+ final TimeValidator tv = validationMethod .timeValidator ();
229+ return dv .validateDay (
230+ unpackYear (packed ), unpackMonth (packed ), unpackDay (packed )
231+ ) != DateValidator .INVALID && tv .validateTimeWithMillis (
232+ unpackHour (packed ), unpackMinute (packed ), unpackSecond (packed ), unpackMilli (packed )
233+ ) != TimeValidator .INVALID ? packed : INVALID ;
234+ }
235+
187236 @ Override
188237 default DateTimePacker forValidationMethod (final ValidationMethod validationMethod ) {
189238 return valueOf (packing (), validationMethod );
0 commit comments