String has to be converted to type LocalDateTime - "yyyy-MM-dd'T'HH:mm:ss".
Just ignore anything after seconds.
tried this code but errors out for anything that comes after seconds.
String testDate = "2019-09-17T23:38:47";
LocalDateTime lDate = null;
if (!StringUtils.isEmpty(testDate) && !"".equals(testDate)) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
try {
sqlDate = LocalDateTime.parse(testDate, formatter);
log.info("Converted SQL date=" + lDate );
} catch (Exception ex) {
log.error("Error in parsing lDate " +ex);
}
}
Try this: (+ exception handling)
String testDate = "2019-09-17T23:38:47.342";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
java.util.Date date = format.parse(testDate);
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(localDateTime);
System.out.println(localDateTime.getNano());
Output:
2019-09-17T23:38:47
0
As you can see, the fractional seconds are eliminated.
Edit:
Here's a solution with more recent date-time classes:
DateTimeFormatter format = new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss")
.appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
.toFormatter();
LocalDateTime date1 = LocalDateTime.parse("2019-09-17T23:38:47", format).withNano(0);
LocalDateTime date2 = LocalDateTime.parse("2019-09-17T23:38:47.342", format).withNano(0);
System.out.println(date1);
System.out.println(date2);
Output:
2019-09-17T23:38:47
2019-09-17T23:38:47
Edit 2:
I've constructed an example for how you might deal with different types of inputs using regular expressions and format strings:
InputDatePattern.java
public enum InputDatePattern
{
WITH_TIMESTAMP("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{0,9})?", Optional.of("yyyy-MM-dd'T'HH:mm:ss")),
WITHOUT_TIMESTAMP("\\d{4}-\\d{2}-\\d{2}", Optional.of("yyyy-MM-dd")),
TIMESTAMP_ONLY("\\d{2}:\\d{2}:\\d{2}(\\.\\d{0,9})?", Optional.of("HH:mm:ss")),
UNKNOWN(".*", Optional.empty()); // must come last, since elements are matched in order
private final Pattern pattern;
private final Optional<DateTimeFormatter> formatter;
private static final LocalDate DEFAULT_DATE = LocalDate.EPOCH;
private static final LocalTime DEFAULT_TIME = LocalTime.MIDNIGHT;
private static final Logger log = Logger.getLogger(Logger.class.getName());
private InputDatePattern(String regex, Optional<String> format)
{
pattern = Pattern.compile(regex);
var formatter = Optional.of(new DateTimeFormatterBuilder());
formatter.ifPresent(f -> format.ifPresent(f::appendPattern));
formatter.ifPresent(f -> f.appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true));
this.formatter = formatter.map(DateTimeFormatterBuilder::toFormatter);
}
public boolean matches(String type)
{
return pattern.matcher(type).matches();
}
public Optional<LocalDateTime> toLocalDateTime(String dateString)
{
try
{
switch(this)
{
case WITH_TIMESTAMP:
return formatter.map(f -> LocalDateTime.parse(dateString, f).withNano(0));
case WITHOUT_TIMESTAMP:
return toLocalDate(dateString).map(date -> date.atTime(DEFAULT_TIME).withNano(0));
case TIMESTAMP_ONLY:
return toLocalTime(dateString).map(date -> date.atDate(DEFAULT_DATE).withNano(0));
case UNKNOWN:
return Optional.empty();
default:
throw new IllegalStateException("Attempting conversion with unknown InputDatePattern!");
}
}
catch(DateTimeParseException e)
{
log.info(e.getMessage());
return Optional.empty();
}
}
public Optional<LocalDate> toLocalDate(String dateString)
{
try
{
switch(this)
{
case WITH_TIMESTAMP:
case WITHOUT_TIMESTAMP:
return formatter.map(f -> LocalDate.parse(dateString, f));
case TIMESTAMP_ONLY:
case UNKNOWN:
return Optional.empty();
default:
throw new IllegalStateException("Attempting conversion with unknown InputDatePattern!");
}
}
catch(DateTimeParseException e)
{
log.info(e.getMessage());
return Optional.empty();
}
}
public Optional<LocalTime> toLocalTime(String dateString)
{
try
{
switch(this)
{
case WITH_TIMESTAMP:
case TIMESTAMP_ONLY:
return formatter.map(f -> LocalTime.parse(dateString, f));
case WITHOUT_TIMESTAMP:
case UNKNOWN:
return Optional.empty();
default:
throw new IllegalStateException("Attempting conversion with unknown InputDatePattern!");
}
}
catch(DateTimeParseException e)
{
log.info(e.getMessage());
return Optional.empty();
}
}
public static InputDatePattern forDateString(String dateString)
{
for(InputDatePattern pattern : InputDatePattern.values())
{
if(pattern.matches(dateString))
return pattern;
}
return InputDatePattern.UNKNOWN;
}
}
Demo.java
public class Demo
{
public static void main(String[] args)
{
String[] trying = {"2019-09-17T23:38:00", "2019-09-17T23:38:00.123",
"2019-09-17", "bad input", "09:12:13.45"};
for(String str : trying)
{
InputDatePattern pattern = InputDatePattern.forDateString(str);
System.out.format("Input pattern type for %s is %s%n", str, pattern);
Optional<LocalDateTime> localDateTime = pattern.toLocalDateTime(str);
if(localDateTime.isPresent())
{
System.out.println("The corresponding LocalDateTime is: "+localDateTime.get());
}
else
{
System.out.format("Unknown type of LocalDateTime! Bad input=\"%s\"%n",str);
}
}
}
}
Output:
Input pattern type for 2019-09-17T23:38:00 is WITH_TIMESTAMP
The corresponding LocalDateTime is: 2019-09-17T23:38
Input pattern type for 2019-09-17T23:38:00.123 is WITH_TIMESTAMP
The corresponding LocalDateTime is: 2019-09-17T23:38
Input pattern type for 2019-09-17 is WITHOUT_TIMESTAMP
The corresponding LocalDateTime is: 2019-09-17T00:00
Input pattern type for bad input is UNKNOWN
Unknown type of LocalDateTime! Bad input="bad input"
Input pattern type for 09:12:13.45 is TIMESTAMP_ONLY
The corresponding LocalDateTime is: 1970-01-01T09:12:13