问题
I'm using the SimpleDateFormat
object with the Date
object as shown below. The problem lis that the Date
object shows the wrong date, which is a few minutes off from the original string. The Date
object appears to store the time in total milliseconds in the debugger.
Any ideas on the problem?
import java.text.SimpleDateFormat;
import java.util.Date;
Date played_at_local;
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSSZ");
played_at_local = dateFormat.parse("2011-04-11T22:27:18.491726-05:00");
//played_at_local shows "Mon Apr 11 22:35:29 America/Chicago 2011" in debugger
回答1:
Try removing the fractional seconds from the format string. I just ran into the same issue, but with a slightly different format. My input format wasn't in ISO format (no "T", and no "Z"), but the symptom was the same -- time was off by some random number of minutes and seconds, but everything else was fine. This is what my log results looked like:
When using the fractional second format:
SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS");
# Parsed date: 2011-05-27 17:11:15.271816 => Fri May 27 17:15:46 EDT 2011
# Parsed date: 2011-05-27 17:09:37.750343 => Fri May 27 17:22:07 EDT 2011
# Parsed date: 2011-05-27 17:05:55.182921 => Fri May 27 17:08:57 EDT 2011
# Parsed date: 2011-05-27 16:55:05.69092 => Fri May 27 16:56:14 EDT 2011
# Parsed date: 2011-05-27 16:38:35.50348 => Fri May 27 16:39:25 EDT 2011
I fixed it by removing the fractional seconds from the format.
SimpleDateFormat dateFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
# Parsed date: 2011-05-27 17:11:15.271816 => Fri May 27 17:11:15 EDT 2011
# Parsed date: 2011-05-27 17:09:37.750343 => Fri May 27 17:09:37 EDT 2011
# Parsed date: 2011-05-27 17:05:55.182921 => Fri May 27 17:05:55 EDT 2011
# Parsed date: 2011-05-27 16:55:05.69092 => Fri May 27 16:55:05 EDT 2011
# Parsed date: 2011-05-27 16:38:35.50348 => Fri May 27 16:38:35 EDT 2011
What I think is happening is that my "fractional seconds" part of the input string is too long (the same is true in the OP example). It appears to be expecting only three decimal places. If you do the math (take the first example):
- fractional seconds = 0.271816 seconds
- What DateFormat sees is
271816 / 1000
of a second - 271816 / 1000 == 271 seconds
- 271 / 60 = 4 minutes
- 271 % 60 = 31 seconds
- 17:11:15 to 17:15:46 is exactly 4 minutes, 31 seconds off
回答2:
Try this, working for me Z should be useed in date, or rmove from Format String
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z'");
played_at_local = dateFormat.parse("2011-04-11T22:27:18.491726Z-05:00");
回答3:
05:00 -->> 0500
and
hh --> HH // error not because of this ,but date is in 24hr format.
played_at_local = dateFormat.parse("2011-04-11T22:27:18.491726-05:00");
should be
played_at_local = dateFormat.parse("2011-04-11T22:27:18.491726-0500");
回答4:
You could try this method: http://docs.oracle.com/javase/6/docs/api/java/sql/Timestamp.html#valueOf(java.lang.String)
The key thing is that fractional digits are optional and you can use a variable number of them. However, this does not seem to account for the time zone.
From the docs:
valueOf
public static Timestamp valueOf(String s)
Converts a String object in JDBC timestamp escape format to a Timestamp value.
Parameters:
s - timestamp in format yyyy-mm-dd hh:mm:ss[.f...]. The fractional seconds may be omitted.
Returns:
corresponding Timestamp value
Throws:
IllegalArgumentException - if the given argument does not have the format yyyy-mm-dd hh:mm:ss[.f...]
回答5:
Try this :
dTime = new SimpleDateFormat("HH:mm:ss:SS");
String sTime = (dTime.format(new java.util.Date())).toString();
Hope this help
回答6:
java.time and ThreeTenABP
There is no way that SimpleDateFormat
can parse your datetime string correctly. On the other hand java.time, the modern Java date and time API, supports your format out of the box.
import org.threeten.bp.OffsetDateTime;
String dateTimeString = "2011-04-11T22:27:18.491726-05:00";
OffsetDateTime playedAtLocal = OffsetDateTime.parse(dateTimeString);
System.out.println("Parsed into " + playedAtLocal);
Output is:
Parsed into 2011-04-11T22:27:18.491726-05:00
SimpleDateFormat
only supports milliseconds, exactly three decimals on the seconds, not two, not four, not six (admittedly I’m unsure whether some Android versions have a version of SimpleDateFormat
that can do better, but your question shows that your version cannot). SimpleDateFormat
is also notoriously troublesome and long outdated, so you wouldn’t want to use it anyway.
java.time is so much nicer to work with. You notice that we didn’t even need an explicit formatter and thus didn’t need to write a format pattern string, which is always an error-prone task. Your date time string is in ISO 8601 format, and java.time classes parse ISO 8601 as their default.
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
来源:https://stackoverflow.com/questions/5636491/date-object-simpledateformat-not-parsing-timestamp-string-correctly-in-java-and