android problem with SimpleDateFormat TimeZone - android

Let's consider this code sample:
DateFormat sdf = SimpleDateFormat.getTimeInstance(SimpleDateFormat.LONG,
new Locale("ru", "RU"));
Date date = sdf.parse("8:13:05 PDT");
When I run this code on my desktop(java 1.6) all passes well, however on android devices I get exception, I think this is due to locale TimeZone:
java.text.ParseException: Unparseable date: 8:13:05 PDT
Why?

I don't believe UNIX can parse the PDT timezone. I'm having the same issue. It can handle PST & PST8PDT, but not PDT. I believe the recommended solution is to use PST8PDT instead.

Related

SimpleDateFormat Unparseable date only on phone

I need to parse a string from my database which has "Mon Jul 18 12:58:05 2022" string as value. Weirdly it only works with emulator. But, if i try to uses my app in my phone it throws Unparseable date error. My phone is using android 9 which use sdk 28, so i think it should be fine. I alread tried to remove the timezone which in many cases could cause the problem. But, after i remove it and the error still happen. It took me sometime to figure this out, but in the end i still got no answer. I just wanted to know what causing such problem and how to fix it?
Here is my code :
ref.child(currentData.id.toString()).child("onwork_start").get().addOnSuccessListener {
val sdf = SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy")
val time = sdf.parse(it.value.toString())
val date = SimpleDateFormat("dd MMM HH:mm")
val show_time = date.format(time)
holder.tv_konfirmasi_bill.text = show_time.toString()

how to format date string from input could be of multiple string formats

Having input date string could be possible as
"2020-01-25T21:59:27Z"
or
"Sat Jan 25 20:06:07 +0000 2020"
or a Long
and expect one to display is like
Jan 25, 2020
how to get the desired formatted date string?
update:
#Ole V.V provided a very good suggestion, it's just cannt apply it with android lib case.
but I guess there is no single format for all these three cases, so have to try out one by one. such as for the ISO8601 one to do something like:
return try {
val dateStr = "Sat Jan 25 20:06:07 +0000 2020". //ISO8601
val format = SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.getDefault())
val dsipFormat = SimpleDateFormat("MMM dd yyyy", Locale.getDefault()) // for display result
val date = format.parse(dateStr) // parse it to date
dsipFormat.format(date) // returning the display result
} catch (e: Exception) {
Log.e("+++", "+++ error: $e")
""
}
If there is better approach?
java.time and ThreeTenABP
My solution is to build three formatters for the three possible input formats and then for each input try the formatters in turn. For a simple demomstration of the idea:
DateTimeFormatter[] inputFormatters = {
DateTimeFormatter.ISO_INSTANT,
DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss xx yyyy", Locale.ROOT),
new DateTimeFormatterBuilder()
.appendValue(ChronoField.INSTANT_SECONDS)
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
.toFormatter()
};
DateTimeFormatter displayFormatter
= DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.US);
for (String inputString : new String[] {
"2020-01-25T21:59:27Z",
"Sat Jan 25 20:06:07 +0000 2020",
"1566777888999"
}) {
// try the formatters in turn and see which one works
for (DateTimeFormatter formatter : inputFormatters) {
try {
ZonedDateTime dateTime = formatter.parse(inputString, Instant.FROM)
.atZone(ZoneId.systemDefault());
System.out.format("%-30s was parsed to %s%n",
inputString, dateTime.format(displayFormatter));
break;
} catch (DateTimeParseException ignore) {
// Ignore, try next format
}
}
}
In my time zone (Europe/Copenhagen) output from this snippet is:
2020-01-25T21:59:27Z was parsed to Jan 25, 2020
Sat Jan 25 20:06:07 +0000 2020 was parsed to Jan 25, 2020
1566777888999 was parsed to Aug 26, 2019
Since it is never the same date in all time zones, output will vary with time zone.
I am recommending java.time, the modern Java date and time API. I saw that you tagged the question simpledateformat, but the SimpleDateFormat class is notoriously troublesome and long outdated, so I recommend against using it. And I am exploiting the fact that your first format is standard ISO 8601 and that java.time has a built-in formatter for it, DateTimeFormatter.ISO_INSTANT.
My third input formatter, the one for the long value, regards the last three characters as milliseconds of the second and everything before it as seconds since the epoch. The net result is that it parses milliseconds since the epoch. A DateTimeFormatterBuilder was required to build this formatter.
A no-lib solution
I admit that I hate to write this. I would really have hoped that you could avoid the notoriously troublesome SimpleDateFormat class and its long outdated cronies like Date. Since I understand that yours is a no-lib app, both of Joda-Time and ThreeTenABP seem out of the question. Sorry. In this case since there is no way that SimpleDateFormat can parse a long, my approach is to take a taste of the string to determine the format and choose my way of parsing based on that.
DateFormat inputIso = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
// This format resembles the output from Date.toString
DateFormat inputDatelike
= new SimpleDateFormat("EEE MMM dd HH:mm:ss ZZZ yyyy", Locale.ROOT);
DateFormat displayFormat
= DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US);
displayFormat.setTimeZone(TimeZone.getDefault());
for (String inputString : new String[] {
"2020-01-25T21:59:27Z",
"Sat Jan 25 20:06:07 +0000 2020",
"1566777888999"
}) {
Date parsedDate;
if (Character.isDigit(inputString.charAt(0))) {
if (inputString.contains("-")) {
parsedDate = inputIso.parse(inputString);
} else {
// long number of millis
parsedDate = new Date(Long.parseLong(inputString));
}
} else {
parsedDate = inputDatelike.parse(inputString);
}
System.out.format("%-30s was parsed to %s%n",
inputString, displayFormat.format(parsedDate));
}
Output is exactly the same as before:
2020-01-25T21:59:27Z was parsed to Jan 25, 2020
Sat Jan 25 20:06:07 +0000 2020 was parsed to Jan 25, 2020
1566777888999 was parsed to Aug 26, 2019
Please be aware that here invalid input may cause either a NumberFormatException or a ParseException, so catch both. And only resort to this solution if there is no way that you can avoid it.
The line displayFormat.setTimeZone(TimeZone.getDefault()); is technically superfluous, but it makes explicit that the output depends on the time zone, and maybe more importantly, it tells you where you need to modify the code if you want output in a different time zone.
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. Only in this case use the method reference Instant::from instead of the constant Instant.FROM.
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.

How To See If One Date Is Newer Than Another

Hello I think I have a very simple question but i'm having trouble figuring it out.
I Got the Date and Time In Android using this code
String currentDateTimeString = DateFormat.getDateInstance().format(new Date());
It gave me back this value
Apr 21, 2016 9:30:16 PM
how do I compare using to dates with that value so if I want to see if
Apr 21, 2016 9:30:16 PM
is newer or older than
Apr 21, 2016 9:35:16 PM
How would I check that Thanks
Attempt One
I Tried This
DateFormat format = new SimpleDateFormat("MM-dd-yyyy", Locale.ENGLISH);
Date fileDate = format.parse(date1);
DateFormat format2 = new SimpleDateFormat("MM-dd-yyyy", Locale.ENGLISH);
Date metaDate = format.parse(date2);
this the value for date 1 and 2 being
Apr 21, 2016 9:35:16 PM
But it threw a parse exception. I must use that value above so What do I Need to do so it doesn't break the code when it tries to parse the date
The easiest way is to use Date.before(), rather than comparing the strings. In fact its easier to convert the string back into a date than use the strings.

joda-time can't read Parse dateTime string

I'm having an issue with joda-time formatting a date time string that Parse (parse.com) has stored in an sqlite table.
Sqlite creation string: "createdDate date time"
Storing parse date into table: "insert... parseObject.getCreatedAt()"
If i then use a SQLite browser to inspect the table, I see the date stored like this:
Sat Jun 15 15:44:52 PDT 2013
So going along with that, I wrote the following to convert it back into a DateTime object to give to parse as part of a query to get items that are newer than the last inserted in my table:
DateTimeFormatter format = DatetimeFormat.forPattern("yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSS'Z'");
DateTime dt = formatter.parseDateTime(datahelper.getLastInsertDate(..));
The formatter is this way, because in Parse's databrowser, I can see dateTimes being stored like this:
2013-06-24T08:11:45.280Z
I get an ANR though, so I tried using the following formatter:
DateTimeFormatter format = DatetimeFormat.forPattern("EEE' 'MMM' 'dd' 'HH':'mm':'ss 'z'' 'YYYY");
DateTime dt = formatter.parseDateTime(datahelper.getLastInsertDate(..));
and I still get an ANR. The trace in eclipse shows the following:
Caused by: java.lang.IllegalArgumentException: invalid format: "Tue Jun 25 00:13:29 PDT 2013"
at org.joda.time.format.DateTimeFormatter.parseDateTime"
The second ANR trace shows:
Invalid format: "Tue Jun 25 00:13:29 PDT 2013" is malformed at "PDT
2013"
I've tried getting around that, as joda time does not parse "z" to PDT/PST, so I've put 'PDT' in my formatter to hopefully get it to work, but nothing seems to work.
Any ideas?
Edit 1: Using the accepted answer, I have a timezone formatting issue)
DateFormat originalFormat = new SimpleDateFormat("EEE MMM DDD HH:mm:ss z yyyy");
Date originaldate = originalFormat.parse(datahelper.getLastInsertdate);
Log.i("converted date: ", String.valueOf(originalDate);
Log.i("a real date: ", "String.valueOf(new Date(new Date().getTime)));
I get two outputs:
Fri Jan 25 15:14:11 PST 2013
Tue Jun 25 17:11:44 PDT 2013
why does the converted date show PST, and a standard Date shows PDT?
It seems to be a known problem Joda cannot parse Timezone names sadly. In the documentation before all the pattern syntaxes you will see this line:
The pattern syntax is mostly compatible with java.text.SimpleDateFormat - time zone names cannot be parsed and a few more symbols are supported. All ASCII letters are reserved as pattern letters, which are defined as follows:
You can see that in the documentation link here
Now the solution to your answer can be found in this answer by #BalusC located here
Hope this helps.
I think that with SQLite, because the date type is somewhat broken, the best thing to do is to store the long that you get from Date.getTime() or related Joda methods.
When you get the long from the database, re-construct your date object (e.g. new Date(long)), and then format that.
Above all, remember that (IMHO) the only sensible way to store a date is in reference to UTC, which is what you get with Date.getTime() and new Date(long) : milliseconds since Jan 1, 1970 UTC.
Once you retrieve your date, format it with whatever timezone is appropriate.

How do I get the time in this format in android?

I am trying to get the present time in this format in an android app. time= "05:09pm 08/02/2011" Right now I am using Calendar c=Calendar.getInstance() and c.getTime() to get the time and its coming out as Tue Aug 23 02:34:25 PDT 2011.
Thanks
You need to use the DateFormat Class
Something like this will get you the current time in the format you desire.
DateFormat.format("hh:mmaa dd/MM/yyyy", System.currentTimeMillis());
Use a SimpleDateFormat.
Format should be like
SimpleDateFormat sdf = new SimpleDateFormat( "HH:mma dd/MM/yyyy" );
sdf.format( yourDate );
Regards,
Stéphane
There are many ways to do that in Android. You can use the SimpleDateFormat wich is a class for formatting and parsing dates. Formatting turns a Date into a String, and parsing turns a String into a Date. Or you can the class Formatter wich is low level but managing the localization is your responsibility.
You may find source code example on the Android javadoc on those classes

Categories

Resources