This question already has answers here:
`uuuu` versus `yyyy` in `DateTimeFormatter` formatting pattern codes in Java?
(4 answers)
Issue with DateTimeParseException when using STRICT resolver style
(2 answers)
Closed 2 years ago.
I tried DateTimeFormatter to parse input date to dd/MM/yyyy. I have used below code
java.time.format.DateTimeFormatter is failing to parse the date
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy").withResolverStyle(ResolverStyle.STRICT);
try {
LocalDate.parse(dateField, dateFormatter);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
Input: 30/04/2018
Error:Caused by: java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {MonthOfYear=4, YearOfEra=2018, DayOfMonth=30},ISO of type java.time.format.Parsed
It is also failing for leap years.
The issue is using .withResolverStyle(ResolverStyle.STRICT) requires to use year pattern uuuu instead of yyyy (i.e. "year" instead of "year-of-era")
You basically have two options (here, where one is using the ResolverStyle you are showing in your code example):
use a ResolverStyle.STRICT explicitly ⇒ parses year u only
use a default ResolverStyle ⇒ year-of-era y or year u will be parsed
The following example shows the differences in code:
public static void main(String[] args) {
String date = "30/04/2018";
// first formatter with year-of-era but no resolver style
DateTimeFormatter dtfY = DateTimeFormatter.ofPattern("dd/MM/yyyy");
// second one with year and a strict resolver style
DateTimeFormatter dtfU = DateTimeFormatter.ofPattern("dd/MM/uuuu")
.withResolverStyle(ResolverStyle.STRICT);
// parse
LocalDate localDateU = LocalDate.parse(date, dtfU);
LocalDate localDateY = LocalDate.parse(date, dtfY);
// print results
System.out.println(localDateU);
System.out.println(localDateY);
}
The output is
2018-04-30
2018-04-30
so both DateTimeFormatters parse the very same String, but the one without a ResolverStyle explicitly attached will use ResolverStyle.SMART by default according to the JavaDocs of DateTimeFormatter.
Of course, a pattern with year (u) will be parsed by ResolverStyle.SMART, too, so
DateTimeFormatter.ofPattern("dd/MM/uuuu");
would be an option as well.
A good explanation of the difference between year-of-era and year can be found in this post.
Related
This question already has answers here:
how to parse OffsetTime for format HHmmssZ
(2 answers)
Closed 1 year ago.
I am getting an parse error while parsing a date
java.text.ParseException: Unparseable date: "2021-06-17T05:49:41.174Z"
Unparseable date: "2021-06-17T05:49:41.174Z"
my code looks like this
private static String generateAndValidate(int count) {
Clock clock = Clock.systemUTC();
String clockTime=clock.instant().toString();
String result=clockTime;
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ",Locale.ENGLISH);
try {
output.parse(clockTime);
} catch (ParseException e) {
System.out.println("process date parse error. Going for retry.");
}
return result;
}
Also tried hard coding the value here
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ",Locale.ENGLISH);
try {
output.parse("2021-06-17T05:49:41.174Z");
} catch (ParseException e) {
System.out.println("process date parse error. Going for retry.");
}
What could be the problem?
EDIT: The reason for the failing of your code is in the answer given by #GS3!
My answer provides alternatives that are generally considered mroe up-to-date:
I would not recommend to use a java.text.SimpleDateFormat here because you are involving a very old and practically outdated API while you are receiving the time by the modern API utilizing a java.time.Clock.
A good move would be to use java.time.format.DateTimeFormatters for parsing, but I think you could even skip the clock and use OffsetDateTime.now(ZoneOffset.UTC).
However, this code definitely parses the String produced by your first lines:
public static void main(String[] args) {
// your first two lines
Clock clock = Clock.systemUTC();
String clockTime = clock.instant().toString();
// a hint to the problem
System.out.println(clockTime + " <--- 6 fractions of second");
// how to parse a String like that in plain java.time
OffsetDateTime odt = OffsetDateTime.parse(clockTime);
System.out.println(odt.format(
DateTimeFormatter.ISO_OFFSET_DATE_TIME
)
);
}
The output of that will look like the following (obviously having different values):
2021-06-17T06:34:55.490370Z <--- 6 fractions of second
2021-06-17T06:34:55.49037Z
The output that uses a DateTimeFormatter.ISO_OFFSET_DATE_TIME is just one option, you can still define your own pattern using a DateTimeFormatter.ofPattern(yourPatternString), a DateTimeFormatterBuilder in order to handle optional parts or one of the other built-in formatters.
If you just want to get the current moment and store it in a some datetime class, you can use the now() method the datetime classes in java.time have:
OffsetDateTime now = OffsetDateTime.now(ZoneOffset.UTC);
looks suitable here, but there's a ZonedDateTime, too.
Just have a look at java.time...
In SimpleDateFormat, Z represents a restricted subset of the RFC-822 time zone syntax. Instant::toString() provides a timestamp in the ISO-8601 format. You can fix this by using X instead of Z.
SimpleDateFormat output = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX",Locale.ENGLISH);
This question already has answers here:
12:xx shown as 00:xx in SimpleDateFormat.format("hh:mm:ss")
(1 answer)
Comparing two times in android
(4 answers)
Closed 2 years ago.
After some debugging, I found that it was because 12:00 was being set to 0:00, but surely if this was a 24-hour clock only 24:00 would be set to 0:00
SimpleDateFormat time_format = new SimpleDateFormat ("hh:mm");
String start_time = "11:00"
String end_time = "12:00"
try { //parses both times to the date data type
start_time_format = time_format.parse(start_time);
end_time_format = time_format.parse(end_time);
} catch (ParseException e) {
e.printStackTrace();
}
if (end_time_format.after(start_time_format)){
}else{
//how come this is always true
}
This is because those old Date and SimpleDateFormat are troublesome.
What happens here is that, because hh is used, the number 12 'overflows' to 0 here. The code which actually does this is found in the SimpleDateFormat source code, in the subParse method.
You should use HH. And while you're at it – you should use modern Java Date and Time API from the java.time package:
String startTimeStr = "11:00";
String endTimeStr = "12:00";
LocalTime startTime = LocalTime.parse(startTimeStr);
LocalTime endTime = LocalTime.parse(endTimeStr);
// No need for a explicit formatting string, because the default is used here,
// which is HH:mm[:ss[.nnnnnnnnn]]
if (endTime.isAfter(startTime)) {
System.out.println("If");
}
else {
System.out.println("Else");
}
But even if you used an explicit DateTimeFormatter with the pattern string hh:mm, then a DateTimeException would have been thrown because the value to be parsed were ambiguous. 11:00 and 12:00 in a twelve-hour clock could mean two things: either AM or PM. The parser by default doesn't like ambiguous values, so instead of just choosing one and moving on, causing confusion to everyone, the authors decided to immediately stop the parsing process and throw an exception. The following code shows this:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm");
String startTimeStr = "11:00";
LocalTime startTime = LocalTime.parse(startTimeStr, formatter);
Date class of java set 12:00 to 00:00 of the day.therefore new date with 12:00 convert to Jan 01 11:00:00 1970.To avoid this effect you can use "HH:mm" format string.
This question already has answers here:
Android: Compare time in this format `yyyy-mm-dd hh:mm:ss` to the current moment
(5 answers)
Conversion of a date to epoch Java [duplicate]
(4 answers)
How to get the current time in YYYY-MM-DD HH:MI:Sec.Millisecond format in Java?
(16 answers)
Closed 2 years ago.
The following code gave me Datetimestamp as [ 2020-07-183 17:07:55.551 ]. The issue is with "Day" in Datetimestamp, which has three digits. How to format currentTimeMillis into the right format for day of month?
public String Datetimesetter(long currentTimeMillis, SimpleDateFormat dateFormat) {
dateFormat = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS.SSS");
// Create a calendar object that will convert the date and time value in milliseconds to date.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(currentTimeMillis);
return dateFormat.format(calendar.getTime());
}
SOLUTION WHICH WORKED FOR ME:
Please visit this link.
This is for the case you are supporting Apps from API level 26 (native support of java.time) or you are willing / allowed to use a backport library of the same functionality.
Then you can use a correct / matching pattern (one that considers three-digit days) like this:
public static void main(String[] args) {
// mock / receive the datetime string
String timestamp = "2020-07-183 17:07:55.551";
// create a formatter using a suitable pattern (NOTE the 3 Ds)
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-DDD HH:mm:ss.SSS");
// parse the String to a LocalDateTime using the formatter defined before
LocalDateTime ldt = LocalDateTime.parse(timestamp, dtf);
// and print its default String representation
System.out.println(ldt);
}
which outputs
2020-07-01T17:07:55.551
So I guess the day of year no. 183 was actually July 1st.
your date format is incorrect
dateFormat = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS.SSS");
change to this
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:MM:SS.SSS");
This question already has answers here:
Can’t rid of 'T' in LocalDateTime
(3 answers)
How to prevent auto-generated 'T' letter when parsing String to LocalDateTime using DateTimeFormatterBuilder [duplicate]
(1 answer)
Closed 2 years ago.
I'm trying to format Threeten datetime, from yyyy-MM-dd'T'HH:mm:ss to yyyy-MM-dd HH:mm:ss. Below is the code, I'm using to achieve the task.
public void testChangeFormat() {
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime date1 = LocalDateTime.parse("2020-03-10T15:14:05", inputFormatter);
System.out.println(date1); // prints 2020-03-10T15:14:05
String formattedDate = outputFormatter.format(date1);
System.out.println(formattedDate); // prints 2020-03-10 15:14:05
LocalDateTime newFormattedDateTime = LocalDateTime.parse(formattedDate);
System.out.println(newFormattedDateTime);
}
Everything seems to work as expected until I try to parse the formattedDate to LocalDateTime, at LocalDateTime newFormattedDateTime = LocalDateTime.parse(formattedDate);
I even get the datetime formatted as 2020-03-10 15:14:05 using outputFormatter, but when I try to parse that to LocalDateTime, it gives me the following exception:
org.threeten.bp.format.DateTimeParseException: Text '2020-03-10 15:14:05' could not be parsed at index 10
Can somebody help me with this?
LocalDateTime.parse(formattedDate) are using DateTimeFormatter.ISO_LOCAL_DATE_TIME (that is format yyyy-MM-dd'T'HH:mm:ss). That's why you get the exception when trying to parse string that has format yyyy-MM-dd HH:mm:ss. You should use:
LocalDateTime.parse(formattedDate, outputFormatter) if you wnat to do the parse to LocalDateTime again for some reason.
Note:
You have the printed format you at line: outputFormatter.format(date1) right?
You seem to be confused between LocalDateTime and format (which is a string representation).
A LocalDateTime always has T in it when you print its object using System.out.println (which implicitly calls toString as you most likely already know) e.g.
System.out.println(LocalDateTime.now());
will output 2020-04-14T09:36:04.723994.
See below how the toString of LocalDateTime has been implemented:
#Override
public String toString() {
return date.toString() + 'T' + time.toString();
}
and therefore your following statement will always show 'T' in it:
System.out.println(newFormattedDateTime);
It's up to you to format a LocalDateTime into the String representation of your choice. As I have mentioned in the first line, formats are strings i.e. you format a LocalDateTime into a String representation where you can apply all the options provided by DateTimeFormatter.
The correct way of converting the formattedDate to LocalDateTime is by applying the corresponding format which is specified in outputFormatter.
LocalDateTime newFormattedDateTime = LocalDateTime.parse(formattedDate,outputFormatter);
How date and time are stored in a LocalDateTime object shouldn't be a concern. We can always create the string in the required format from it.
This question already has answers here:
Java SimpleDateFormat Timezone offset with minute separated by colon
(2 answers)
Closed 5 years ago.
I have a problem formatting a date. I want the following output:
yyyy-MM-ddTHH:mm:ss+02:00
Where +02:00 depends on the timezone where you are, in my case Europe/Amsterdam
I have this function:
public String marshal(Date d) throws Exception
{
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
String s = formatter.format(d);
return s;
}
But it gives me:
2017-05-10T14:56:46+0200
How can I have the timezone hour/minute with an extra colon in between?
It's right there in the documentation:
The number of pattern letters designates the format for both formatting and parsing as follows [...]
And from the examples:
"yyyy-MM-dd'T'HH:mm:ss.SSSXXX" 2001-07-04T12:08:56.235-07:00
Meaning that the colon-separated version of the timezone can be expressed using "XXX" in the pattern.
TL;DR: use
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");