I am trying to parse a date string returned to me from DB to LocalDate using DateTimeFormatter. I am receiving the below exception.
String date = "2018-05-16 03:39:13.0";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
LocalDateTime localDate= LocalDateTime.parse(date , formatter);
java.time.format.DateTimeParseException: Text '2018-05-16 03:39:13.0' could not be parsed at index 20
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) [rt.jar:1.8.0_171]
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851) [rt.jar:1.8.0_171]
at java.time.LocalDateTime.parse(LocalDateTime.java:492) [rt.jar:1.8.0_171]
However the below code is working.
String date = "2018-05-16 03:39:13.0";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Date newDate= formatter.parse(date);
Since you are using the fraction-of-seconds with fixed length of 3, it cannot be parsed with only one digit. Better use a DateTimeFormatterBuilder and implement variable fraction-of-second.
String date = "2018-05-16 03:39:13.0";
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
DateTimeFormatter formatter = builder.appendPattern("yyyy-MM-dd HH:mm:ss")
.appendFraction(ChronoField.MILLI_OF_SECOND, 0, 3, true)
.toFormatter();
LocalDateTime localDate = LocalDateTime.parse(date, formatter);
System.out.println(formatter.format(localDate));
It could also be done by using optional fields to get variable fraction-of-second length:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS][.SS][.S]");
If your intent is just to parse the String to LocalDateTime, this will work fine.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
Well this might do your job.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateFormateer {
public static void main(String[] args) throws ParseException{
String date = "2018-05-16 03:39:13.0";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.a", Locale.US);
Date newDate= formatter.parse(date);
String date1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.a", Locale. getDefault()). format(newDate);
Date t=ft.parse(date1);
ft.applyPattern("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(date);
System.out.println(ft.format(t));
}
}
Related
I received a String field in a topic with date and offset and I need to convert this String to a LocalDateTime by adding the offset. For example, if I received:
2021-07-20T19:00:00.000+02:00
I want to convert in LocalDateTime:
2021-07-20T21:00:00.000
And I have a Bean with custom object mapper for this purpose:
#Configuration
public class MyConfiguration {
#Bean
public MyCustomObjectMapper configure() {
final ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX");
final LocalDateTimeDeserializer dateTimeDeserializer = new LocalDateTimeDeserializer(formatter);
final LocalDateTimeSerializer dateTimeSerializer = new LocalDateTimeSerializer(formatter);
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class, dateTimeDeserializer);
javaTimeModule.addSerializer(LocalDateTime.class, dateTimeSerializer);
mapper.registerModule(javaTimeModule);
return new MyCustomObjectMapper (mapper);
}
}
But it doesn't work as I expect, since the resulting LocalDateTime offset disappears and is not added:
2021-07-20T19:00:00.000
How can I achieve this goal?
The LocalDateTime class is a date-time representation which is unaware of time zones and it's only logical that the LocalDateTimeDeserializer ignores any time zone information in the source data.
To account for the time zone you could use the InstantDeserializer.OFFSET_DATE_TIME deserializer (DateTimeFormatter.ISO_OFFSET_DATE_TIME is actually the format of the source date time you have) and have its result converted to LocalDateTime within a desired zone. This can be wrapped in a custom deserializer for ease of use, e.g.
class SmartLocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
private final InstantDeserializer<OffsetDateTime> delegate = InstantDeserializer.OFFSET_DATE_TIME;
public SmartLocalDateTimeDeserializer() {
super(LocalDateTime.class);
}
#Override
public LocalDateTime deserialize(JsonParser p,
DeserializationContext ctxt) throws IOException, JsonProcessingException {
final OffsetDateTime result = delegate.deserialize(p, ctxt);
return result.atZoneSameInstant(ZoneId.systemDefault()).toLocalDateTime();
}
}
...
javaTimeModule.addDeserializer(LocalDateTime.class, new SmartLocalDateTimeDeserializer());
I write a controller like this and it just return the current timestamp
#GetMapping(value = "/i/testTime")
Timestamp testTime(HttpServletRequest req) throws IOException {
return new Timestamp(System.currentTimeMillis());
}
I access the url and it returns:
"2022-02-25T08:23:32.690+00:00"
Is there a way to configure this format?
Any answer will be helpful
I would suggest using java.time package's LocalDateTime class.
LocalDateTime now = LocalDateTime.now();
// LocalDateTime cvDate = Instant.ofEpochMilli(milliseconds).atZone(ZoneId.systemDefault()).toLocalDateTime();
// LocalDateTime utcDate = Instant.ofEpochMilli(milliseconds).atZone(ZoneId.of("UTC")).toLocalDateTime();
System.out.println("Before Formatting: " + now);
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
String formatDateTime = now.format(format);
Output
Before Formatting: 2017-01-13T17:09:42.411
After Formatting: 13-01-2017 17:09:42
SO in your case, it would be something like this:
#GetMapping(value = "/i/testTime")
String testTime(HttpServletRequest req) throws IOException {
LocalDateTime currentDateTime = LocalDateTime.now();
DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
return currentDateTime.format(format);
}
You can even do it with annotations without having logic in your controller.
public class DateDto {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private LocalDateTime date;
public DateDto(LocalDateTime date){
this.date = date;
}
public LocalDateTime getDate(){
return this.date;
}
}
And your controller like:
#GetMapping(value = "/i/testTime")
DateDto testTime(HttpServletRequest req) throws IOException {
return new DateDto(LocalDateTime.now());
}
java.time.format.DateTimeParseException: Text '06/2018' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {Year=2018, MonthOfYear=6},ISO of type java.time.format.Parsed
after formatting Date to string and finally want to convert it to LocalDate field getting above exception.
String date1 = "14-Jun-18";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("d-MMM-yy");
LocalDate localDate1 = LocalDate.parse(date1,dateTimeFormatter);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/yyyy");
String s= localDate1.format(formatter);
LocalDate localDate4 = LocalDate.parse(s,formatter);
The JavaDoc on LocalDate says:
LocalDate is an immutable date-time object that represents a date, often viewed as year-month-day.
You'll need to either provide with a day, or build a DateTimeFormatter using DateTimeFormatterBuilder that defaults to a day:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.format.SignStyle;
public class TestDate {
public static void main(String args[]) {
String date1 = "14-Jun-18";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("d-MMM-yy");
LocalDate localDate1 = LocalDate.parse(date1,dateTimeFormatter);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/yyyy");
String s = localDate1.format(formatter);
System.out.println(s);
DateTimeFormatter formatterWithDefaultDay = new DateTimeFormatterBuilder()
.appendValue(ChronoField.MONTH_OF_YEAR, 2, 2, SignStyle.NEVER)
.appendPattern("/")
.appendValue(ChronoField.YEAR, 4, 4, SignStyle.NEVER)
.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
.toFormatter();
LocalDate localDateBasedOns = LocalDate.parse(s, formatterWithDefaultDay);
System.out.println(localDateBasedOns);
}
}
This prints:
06/2018
2018-06-01
I try to Spring mvc date formater with binder like this
#InitBinder
public void binder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(true);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
But I need format "dd-MM-YYYY". If I use this format mysql save wrong date
Form Data: 07-12-1980
MySql Data: 0013-05-02
In your POJO try adding this onto your date object.
#DateTimeFormat(pattern = "dd/MM/yyyy")
private Date dob;
Source: here
#RequestMapping(value = "/getSettlements", method = RequestMethod.GET, headers = "Accept=application/json")
public #ResponseBody
Collection<Settlement> getSettlements
(#RequestParam(value = "startDate") String startDate,
#RequestParam(value = "endDate") String endDate,
#RequestParam(value = "merchantIds", defaultValue = "null") String merchantIds)
How to give today's date in defaultValue ? It only takes constant.
#InitBinder
public void initBinder(WebDataBinder binder) throws Exception {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
final CustomDateEditor dateEditor = new CustomDateEditor(df, true) {
#Override
public void setAsText(String text) throws IllegalArgumentException {
if ("today".equals(text)) {
setValue(new Date());
} else {
super.setAsText(text);
}
}
};
binder.registerCustomEditor(Date.class, dateEditor);
}
#RequestParam(required = false, defaultValue = "today") Date startDate
If you are using LocalDate, you can create a default value like this:
#RequestParam(name = "d", defaultValue = "#{T(java.time.LocalDate).now()}", required = true) LocalDate d)
I tried pretty much every option, even using interceptors. But from far the easiest solution was to use SpEL. For Example: defaultValue = "#{new java.util.Date()}"
Since you receive a string you can any date format you want and later on use formatting to extract the date