Skip to content

Commit 6efe590

Browse files
committed
some javadoc; some new methods in packers
1 parent dca0882 commit 6efe590

9 files changed

Lines changed: 322 additions & 55 deletions

File tree

src/main/java/org/tools4j/time/pack/DatePacker.java

Lines changed: 94 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,85 @@
3232
import java.util.Objects;
3333

3434
import static org.tools4j.time.base.Allocation.Type.RESULT;
35+
import static org.tools4j.time.validate.DateValidator.isValidDate;
3536

3637
/**
3738
* Packs a date (year, month, day) into an integer. Packing and unpacking can be done with or without date validation
38-
* using different {@link #validationMethod() validation methods}. A {@link #DECIMAL} and a {@link #BINARY} packing is
39-
* supported and both packings preserve the natural date ordering, that is, if the packed integers are sorted then the
40-
* corresponding dates are also sorted. Packing and unpacking of null values is supported via {@link #packNull()} and
41-
* {@link #unpackNull(int)}.
39+
* using different {@linkplain #validationMethod() validation methods}. A {@linkplain #DECIMAL} and a
40+
* {@linkplain #BINARY} packing is supported and both packings preserve the natural date ordering, that is, if the
41+
* packed integers are sorted then the corresponding dates are also sorted. Packing and unpacking of null values is
42+
* supported via {@link #packNull()} and {@link #unpackNull(int)}.
4243
* <p>
4344
* <i>Examples:</i>
4445
* <ul>
45-
* <li>{@link #DECIMAL} packing for a date 21-Jan-2017 is 20170121</li>
46-
* <li>{@link #BINARY} packing uses shifts to pack the date parts which is more efficient but the result is not
46+
* <li>{@linkplain #DECIMAL} packing for a date 21-Jan-2017 is 20170121</li>
47+
* <li>{@linkplain #BINARY} packing uses shifts to pack the date parts which is more efficient but the result is not
4748
* easily human-readable</li>
4849
* </ul>
4950
* @see #valueOf(Packing, ValidationMethod)
5051
* @see #BINARY
5152
* @see #DECIMAL
5253
*/
5354
public interface DatePacker {
55+
/**
56+
* Value returned from pack methods for invalid date inputs if
57+
* {@linkplain ValidationMethod#INVALIDATE_RESULT INVALIDATE_RESULT}
58+
* {@linkplain #validationMethod() validation method} is in use.
59+
*/
5460
int INVALID = -1;
61+
/** Value returned by {@link #packNull()} and from {@link #pack(LocalDate)} for null values. */
5562
int NULL = 0;
5663

64+
/**
65+
* Returns {@linkplain Packing#DECIMAL DECIMAL} or {@linkplain Packing#BINARY BINARY} packing type.
66+
*
67+
* @return the packing type
68+
*/
5769
Packing packing();
70+
71+
/**
72+
* Returns {@linkplain ValidationMethod validation method} used by this packer instance.
73+
*
74+
* @return the method used to validate dates
75+
*/
5876
ValidationMethod validationMethod();
77+
78+
/**
79+
* Returns the packer instance with the same {@linkplain #packing() packing} type as {@code this} packer but using
80+
* the specified {@linkplain ValidationMethod validation method} to validate dates.
81+
*
82+
* @param validationMethod the validation method used by the returned packer to validate dates
83+
* @return the instance with packing type inherited from this packer and validation method as specified
84+
*/
5985
DatePacker forValidationMethod(ValidationMethod validationMethod);
86+
87+
/**
88+
* Packs the given year, month and day value into an int and returns it.
89+
* @param year the four digit year such as 2017
90+
* @param month the month value from 1 to 12
91+
* @param day the day of the month from 1 to no more than 31
92+
* @return the packed date value, or {@linkplain #INVALID} if the date is invalid and
93+
* {@linkplain ValidationMethod#INVALIDATE_RESULT INVALIDATE_RESULT}
94+
* {@linkplain #validationMethod() validation method} is in use
95+
* @throws java.time.DateTimeException if the specified date is invalid and
96+
* {@linkplain ValidationMethod#THROW_EXCEPTION THROW_EXCEPTION}
97+
* {@linkplain #validationMethod() validation method} is in use
98+
*/
6099
int pack(int year, int month, int day);
61-
int pack(long packedDateTime, Packing packing);
100+
101+
/**
102+
* Re-packs the date from specified packed date/time value and returns it.
103+
* @param packedDateTime the packed date/time value
104+
* @param packing the packing type of the date/time value
105+
* @return the packed date value, or {@linkplain #INVALID} if the date is invalid and
106+
* {@linkplain ValidationMethod#INVALIDATE_RESULT INVALIDATE_RESULT}
107+
* {@linkplain #validationMethod() validation method} is in use
108+
* @throws java.time.DateTimeException if the specified date is invalid and
109+
* {@linkplain ValidationMethod#THROW_EXCEPTION THROW_EXCEPTION}
110+
* {@linkplain #validationMethod() validation method} is in use
111+
*/
112+
int packFromDateTime(long packedDateTime, Packing packing);
113+
int packFromDate(int packedDate, Packing packing);
62114
int unpackYear(int packed);
63115
int unpackMonth(int packed);
64116
int unpackDay(int packed);
@@ -72,6 +124,10 @@ public interface DatePacker {
72124
int packEpochMilli(long millisSinceEpoch);
73125
long unpackEpochMilli(int packed);
74126

127+
boolean isValid(int packed);
128+
int validate(int packed);
129+
int validate(int packed, ValidationMethod validationMethod);
130+
75131
/**
76132
* Returns a date packer that performs no validation.
77133
* @param packing the packing type for the returned packer
@@ -113,7 +169,7 @@ default int pack(final LocalDate localDate) {
113169
}
114170

115171
@Override
116-
default int pack(final long packedDateTime, final Packing packing) {
172+
default int packFromDateTime(final long packedDateTime, final Packing packing) {
117173
final DateTimePacker unpacker = DateTimePacker.valueOf(packing, validationMethod());
118174
return pack(
119175
unpacker.unpackYear(packedDateTime),
@@ -122,6 +178,15 @@ default int pack(final long packedDateTime, final Packing packing) {
122178
);
123179
}
124180

181+
@Override
182+
default int packFromDate(final int packedDate, final Packing packing) {
183+
if (packing == packing() && validationMethod() == ValidationMethod.UNVALIDATED) {
184+
return packedDate;
185+
}
186+
final DatePacker dp = DatePacker.valueOf(packing, validationMethod());
187+
return pack(dp.unpackYear(packedDate), dp.unpackMonth(packedDate), dp.unpackMonth(packedDate));
188+
}
189+
125190
@Override
126191
@Allocation(RESULT)
127192
default LocalDate unpackLocalDate(final int packed) {
@@ -150,6 +215,27 @@ default long unpackEpochMilli(final int packed) {
150215
return Epoch.valueOf(validationMethod()).toEpochMilli(packed, this);
151216
}
152217

218+
@Override
219+
default boolean isValid(final int packed) {
220+
return packed != INVALID && (packed == NULL || isValidDate(unpackDay(packed), unpackMonth(packed), unpackDay(packed)));
221+
}
222+
223+
@Override
224+
default int validate(final int packed) {
225+
return validate(packed, validationMethod());
226+
}
227+
228+
@Override
229+
default int validate(final int packed, final ValidationMethod validationMethod) {
230+
if (packed == NULL || packed == INVALID || validationMethod == ValidationMethod.UNVALIDATED) {
231+
return packed;
232+
}
233+
final DateValidator dateValidator = validationMethod.dateValidator();
234+
return dateValidator.validateDay(
235+
unpackYear(packed), unpackMonth(packed), unpackDay(packed)
236+
) != DateValidator.INVALID ? packed : INVALID;
237+
}
238+
153239
@Override
154240
default DatePacker forValidationMethod(final ValidationMethod validationMethod) {
155241
return valueOf(packing(), validationMethod);

src/main/java/org/tools4j/time/pack/DateTimePacker.java

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,21 @@
3737
import static org.tools4j.time.base.Allocation.Type.RESULT;
3838
import static org.tools4j.time.base.TimeFactors.MILLIS_PER_SECOND;
3939
import 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

Comments
 (0)