Android Java SimpleDateFormat exception is not correct [duplicate] - java

This question already has answers here:
Java: Check the date format of current string is according to required format or not [duplicate]
(8 answers)
How to sanity check a date in Java
(24 answers)
Closed 4 years ago.
I am trying to ensure that user entered a correct date format 10/08/2015 for example.
try{
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
d = sdf.parse(date.getText().toString());
}catch(ParseException ex){
Toast.makeText(MainActivity.this,
"Date format is wrong.", Toast.LENGTH_LONG).show();
return;
}
But it still parses most of the wrong inputs like 111/10/2013 or 11/109/2013 or some input containing characters.
Another question is how do i convert dd/mm/yyyy type date to NameofMonth day,year string ?
so 01/04/2018 will be converted to Apr 1,2018

DateTimeFormatter enteredFormatter = DateTimeFormatter.ofPattern("dd/MM/uuuu");
DateTimeFormatter usDateFormatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.US);
LocalDate d;
try {
d = LocalDate.parse(date.getText(), enteredFormatter);
System.out.println(d.format(usDateFormatter));
} catch (DateTimeParseException dtpe) {
Toast.makeText(MainActivity.this,
"Date format is wrong.", Toast.LENGTH_LONG).show();
return;
}
Getting the incorrect dates from your question this code will catch a java.time.format.DateTimeParseException: Text '111/10/2013' could not be parsed at index 2 or java.time.format.DateTimeParseException: Text '11/109/2013' could not be parsed at index 5 and therefore give the error message to the user. Given a correct date string like 11/10/2013 it prints like:
Oct 11, 2013
A detail that I haven’t tested on Android: As I understand, EditText.getText will return an Editable, which implements CharSequence. Since LocalDate.parse accepts a CharSequence, you can pass date.getText() with no need for .toString().
When formatting a date for an audience, the first thing you should consider is using one of Java’s built-in formatters for that audience’s locale. Your requested format agrees with the MEDIUM format for US locale. I took this to be no coincidence. So do take advantage.
At the same time I am taking advantage of java.time, the modern Java date and time API. SimpleDateFormat is notoriously troublesome and long outmoded. I avoid it. The modern API is so much nicer to work with.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.

Related

Parse UTC time format into readable datetime in android

I have an UTC datetime in the format 2019-12-06T06:04:50.022461Z I want to convert into readable datetime in the format dd-mm-yyyy hh:mm:ss. I am not able to convert in the particular format. Any help will be highly appreciated. Thanks
java.time and ThreeTenABP
I am assuming that you want to display the time in your user’s time zone. As you said already, your string is in UTC, and very few users will be happy to read the time in UTC.
DateTimeFormatter readableFormatter = DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm:ss");
String originalString = "2019-12-06T06:04:50.022461Z";
String readableString = Instant.parse(originalString)
.atZone(ZoneId.systemDefault())
.format(readableFormatter);
System.out.println(readableString);
For the sake of the example I ran this code in America/Sitka time zone. Output was:
05-12-2019 21:04:50
If you did want to display the time in UTC as in the original string:
String readableString = OffsetDateTime.parse(originalString)
.format(readableFormatter);
06-12-2019 06:04:50
Don’t go with the classes SimpleDateFormat, TimeZone and Calendar used in the currently accepted answer. They are all poorly designed, SimpleDateFormat in particular is a notorious troublemaker and also cannot parse 6 decimals on the seconds as in your string. Those three classes are also all long outdated. Instead I am using java.time, the modern Java date and time API. It is so much nicer to work with. The code is not only shorter, I think that you will also find it clearer to read (either immediately or when you get used to the fluent style).
I am exploiting the fact that your original string is in ISO 8601 format. The classes of java.time parse ISO 8601 format as their default, that is, without any explicit formatter.
For the vast majority of purposes you shold not want to convert from one string format to another, though. Inside your program keep your date and time as an Instant or other proper date/time object. only convert to a string when a string is needed in the interface.
Question: Doesn’t java.time require Android API level 26?
java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Wikipedia article: ISO 8601
You can use SimpleDateFormat to format the date. Check below:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
Calendar calendar = Calendar.getInstance();
try {
calendar.setTime(sdf.parse("2019-12-06T06:04:50.022461Z"));
} catch (Exception ex) {
ex.printStackTrace();
}
SimpleDateFormat returnFormat = new SimpleDateFormat("dd-mm-yyyy hh:mm:ss");
returnFormat.format(calendar.getTime());
You can try this in java 8
String dateString = "2019-12-06T06:04:50.022461Z";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneOffset.UTC);
TemporalAccessor date = fmt.parse(dateString);
Instant time = Instant.from(date);
DateTimeFormatter fmtOut = DateTimeFormatter.ofPattern("dd-mm-yyyy hh:mm:ss").withZone(ZoneOffset.UTC);
String newDateString = fmtOut.format(time);

format sql datetime in java android studio

How can I format this DateTime form SQL 2019-02-18T06:30:38.9933333 to 2/18/19, 6:30 AM in the android studio using java
I already try Simpledatetime nothing happens.`
String startDate="2019-02-18T06:30:38.9933333"; // Input String
SimpleDateFormat sdf1 = new SimpleDateFormat("MM-dd-yyyy h:mm tt");
java.util.Date date = sdf1.parse(startDate);
java.sql.Date sqlStartDate = new java.sql.Date(date.getTime());
need help.. thannk you.
java.time, ThreeTenABP and a built-in localized format
DateTimeFormatter formatter
= DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
.withLocale(Locale.US);
String startDate = "2019-02-18T06:30:38.9933333"; // Input String
LocalDateTime dateTime = LocalDateTime.parse(startDate);
System.out.println(dateTime.format(formatter));
Output:
2/18/19 6:30 AM
Still better than the above, get a LocalDateTime from your database, or if this is not possible yet, then a Timestamp that you convert like this:
LocalDateTime dateTime = DateTimeUtils.toLocalDateTime(timestampFromDatabase);
Or if using Java 8 or later:
LocalDateTime dateTime = timestampFromDatabase.toLocalDateTime();
The formatting is as before.
As a rule Java knows the best format for a particular audience better than you do. Using the built-in format also saves you from the error-prone task of writing a format pattern string.
In the first snippet I am exploiting the fact that your input string conforms with ISO 8601, the international standard format that the java.time classes parse (and also print) as their default, that is, without any explicit formatter.
The classes SimpleDateFormat, java.util.Date and java.sql.Date are all poorly designed and long outdated. Instead I use java.time, the modern Java date and time API.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Wikipedia article: ISO 8601
Maybe you are use java.time.LocalDateTime if you are working with java8 or higher:
String startDate = "2019-02-18T06:30:38.9933333"; // Input String
LocalDateTime localDateTime = LocalDateTime.parse(startDate);
Use format:
yyyy-MM-dd'T'HH:mm:ss.SSSSSSS
For more Reference:
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

Instant.now equivalent to java.util.Date or Java 7

I have a system using Java 7 and I need to generate a date equivalente to Instant.now (Java 8).
For example, Instant.now().toString() generate a date like that:
"2018-12-19T12:32:46.816Z"
Using java.util.Date I have this date: "2018-12-19T10:38:13.892"
Date date = new Date(System.currentTimeMillis());
SimpleDateFormat sdf;
sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
String text = sdf.format(date);
System.out.println(text);
I don't know if I can simply concatenate a "Z" at the end of this date.
Without "Z" another system that parse this date using Instant.parse throws the error:
java.time.format.DateTimeParseException: Text
'2018-12-19T10:38:13.892' could not be parsed at index 23
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1988)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1890)
at java.base/java.time.Instant.parse(Instant.java:395)
Z means UTC time zone, you can set the time zone to UTC and append Z mannually:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
ThreeTen Backport
java.time, the modern Java date and time API, has been backported. So just do as you would in Java 8:
String text = Instant.now().toString();
Running just now I got:
2018-12-19T13:37:37.186Z
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
The outdated SimpleDateFormat
If you don’t want to rely on an external dependency just until you move to Java 8 or higher, the (most) correct solution is this combination of pieces from the two other answers (one of them now deleted):
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXX");
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String text = sdf.format(System.currentTimeMillis());
2018-12-19T13:37:37.285Z
It doesn’t always give the exact same string as Instant.toString, but it will give a string that Instant can parse in the other system. While Instant.toString() only prints as many decimals as necessary, the above SimpleDateFormat will print three decimals also when some of them are 0.
When the time zone of the formatter is UTC, format pattern letter (uppercase) X will print Z as “time zone” (really just an offset).
Links
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Oracle tutorial: Date Time explaining how to use java.time.

Convert a GMT+0 time into local time on Android and give Hours/Min as a string [duplicate]

This question already has answers here:
Converting ISO 8601-compliant String to java.util.Date
(31 answers)
How to parse "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" date format to simple in Android? [duplicate]
(3 answers)
How to Pick Timezone from ISO 8601 format String into a Calendar instace
(3 answers)
Change date format in a Java string
(22 answers)
Printing out datetime in a specific format in Java?
(4 answers)
Closed 4 years ago.
I used the search function but there was just too much information with too many different methods. I just want to solve this problem, after 1 hour of searching.
I get a string like this from Firestore: 2018-05-22T10:30:00+00:00 (can change if needed)
Now I want to change the time to the local timezone on the device. At the end I need 2 different strings like these:
hour: 10:30
date: Tuesday, May 22
java.time
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM d", Locale.ENGLISH);
String stringFromFirestore = "2018-05-22T10:30:00+00:00";
ZonedDateTime dateTime = OffsetDateTime.parse(stringFromFirestore)
.atZoneSameInstant(ZoneId.systemDefault());
System.out.println("hour: " + dateTime.toLocalTime());
System.out.println("date: " + dateTime.format(dateFormatter));
I ran the code in my time zone, Europe/Copenhagen, and got the following output since I am at offset +02:00 in May:
hour: 12:30
date: Tuesday, May 22
The string you got from Firestore is in ISO 8601 format, the international standard. OffsetDateTime and other java.time classes parse ISO 8601 as their default, that is, without any explicit formatter. I am also using LocalTime.toString() for producing the time of day in ISO 8601 format since this seems to agree with what you wanted.
Question: Can I use java.time on Android?
Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26, I’m told) the modern API comes built-in.
In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.timeto Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
Wikipedia article: ISO 8601

Java date string conversion to different format but with the same timezone

SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
SimpleDateFormat to = new SimpleDateFormat("MM/dd/yyyy Z");
Date date = from.parse("2017-08-10T00:00:00.000+0000");
String newDateStr = to.format(date);
The newDateStr is 08/09/2017 -0500. I expect that newDataStr can have the same timezone as the original date string(0000) -- 08/10/2017 -0000. What should I do to achieve this?
Preserving the offset from the original string is much easier with java.time, the modern Java date and time API:
DateTimeFormatter from = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSZ");
DateTimeFormatter to = DateTimeFormatter.ofPattern("MM/dd/yyyy Z");
String newDateStr = OffsetDateTime.parse("2017-08-10T00:00:00.000+0000", from)
.format(to);
System.out.println(newDateStr);
This prints
08/10/2017 +0000
This is not the only reason for recommending changing to the modern API. The Date class that you are using is long outdated, and SimpleDateFormat in particular is renowned for being troublesome to work with. I always recommend staying away from those classes in 2018. The modern API is generally much nicer. And since you are already using Java 8, there is absolutely no reason why you shouldn’t want it (for anyone reading along and using Java 6 or 7, the new API has been backported to those Java versions too).
What went wrong?
An old-fashioned Date object is just a point in time, it doesn’t hold a time zone or offset in it. So after you had parsed your string into a Date, the offset information was no longer there. So neither the Date nor to, the new formatter, had any way of knowing which offset or time zone had been in the original string. Instead, the new formatter used its own time zone. Since you had not explicitly set a time zone on the formatter, its time zone was that of your JVM, which apparently was a time zone that was on offset -5 from UTC on these days of September 2017.
There are tricky ways to solve the problem with the outdated classes, but as I have probably said already, I wouldn’t want to bother.
"Call requires API Level 26" for Android
#Ponomarenko Oleh in a comment writes:
Pay attention: "Call requires API Level 26" for Android.
However, java.time works nicely on both older and newer Android devices. It just requires at least Java 6.
In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in. This is also the intended meaning of the message quoted in the comment.
In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Java Specification Request (JSR) 310, where java.time was first described.
ThreeTen Backport project, the backport of java.time to Java 6 and 7 (ThreeTen for JSR-310).
ThreeTenABP, Android edition of ThreeTen Backport
Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
You could use the Java 8 Date API which provides a good set of functionality
to convert dates into strings (including timezone support).
An example:
ZonedDateTime dateTime = ZonedDateTime.parse("2017-08-10T00:00:00.000+0000", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
String newDateStr = dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy Z"));
For more information you can look at:
How to parse/format dates with LocalDateTime? (Java 8)
https://www.mscharhag.com/java/java-8-date-time-api

Categories