Skip to content

Instantly share code, notes, and snippets.

@dblevins
Last active March 14, 2022 15:40
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dblevins/03df3cd5eb12f2da05997eef80ac4eca to your computer and use it in GitHub Desktop.
Save dblevins/03df3cd5eb12f2da05997eef80ac4eca to your computer and use it in GitHub Desktop.
Legacy Java 7 version. See recommended Java 8 version https://gist.github.com/dblevins/47f7508e241d775fd7007a4639d6565a
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
/**
* This pattern has the following benefits:
*
* - Date formats are referenced as a strong type
* - Thread-safety handled
* - Parse exception is not a checked exception
* - Code completion on patterns
* - Patterns can be javadoc'ed
*/
public enum Dates {
/**
* <p>Format: yyyy-MM-dd</p>
* <p>Example: 2022-03-30</p>
*/
yyyy_MM_dd("yyyy-MM-dd"),
/**
* <p>Format: MMM dd, yyyy</p>
* <p>Example: Mar 30, 2022</p>
*/
MMM_dd_yyyy("MMM dd, yyyy");
private final ThreadLocal<SimpleDateFormat> instance = new ThreadLocal<>();
private final String formatString;
Dates(final String formatString) {
this.formatString = formatString;
}
public Date parse(final String string) {
try {
return instance().parse(string);
} catch (ParseException e) {
throw new DateParseException(formatString, string);
}
}
public LocalDate parseLocalDate(final String string) {
return parse(string).toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
}
public String format(final Date date) {
return instance().format(date);
}
public String format(final LocalDate date) {
return instance().format(Date.from(date.atStartOfDay()
.atZone(ZoneId.systemDefault())
.toInstant()));
}
private SimpleDateFormat instance() {
{
final SimpleDateFormat format = instance.get();
if (format != null) return format;
}
{
final SimpleDateFormat format = new SimpleDateFormat(formatString);
instance.set(format);
return format;
}
}
private static class DateParseException extends RuntimeException {
public DateParseException(final String formatString, final String string) {
super(String.format("Unable to parse date string '%s' using format '%s'", string, formatString));
}
}
}
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.time.LocalDate;
import java.util.stream.Stream;
import static org.junit.jupiter.params.provider.Arguments.arguments;
public class DatesTest {
private static Stream<Arguments> data() {
return Stream.of(
arguments(Dates.yyyy_MM_dd, "2022-03-30"),
arguments(Dates.MMM_dd_yyyy, "Mar 30, 2022")
);
}
@ParameterizedTest
@MethodSource("data")
public void parse(final Dates dateEnum, final String dateString) {
final LocalDate expected = LocalDate.of(2022, 3, 30);
final LocalDate actual = dateEnum.parse(dateString);
Assertions.assertEquals(expected, actual);
}
@ParameterizedTest
@MethodSource("data")
public void format(final Dates dateEnum, final String expected) {
final LocalDate date = LocalDate.of(2022, 3, 30);
final String actual = dateEnum.format(date);
Assertions.assertEquals(expected, actual);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment