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
String date_s = " 2011-01-18 00:00:00.0"; SimpleDateFormat dt = new SimpleDateFormat("yyyyy-mm-dd hh:mm:ss"); Date date = dt. parse(date_s); SimpleDateFormat dt1 = new SimpleDateFormat("yyyyy-mm-dd"); System. out. println(dt1.
String pattern = "MM-dd-yyyy"; SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern); String date = simpleDateFormat. format(new Date()); System. out. println(date);
Class SimpleDateFormat. Deprecated. A class for parsing and formatting dates with a given pattern, compatible with the Java 6 API.
DateTimeFormatter is a replacement for the old SimpleDateFormat that is thread-safe and provides additional functionality.
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");
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):
271816 / 1000
of a secondThere are three major problems in your code:
.SSSSSS
for the fraction of a second whereas the SimpleDateFormat
does not support a precision beyond milliseconds (.SSS
). It also means that you need to limit the digits in the fraction of a second to three.Z
to parse the timezone offset, -05:00
whereas the correct pattern for this is XXX
.hh
for a time in 24-Hour format whereas the correct pattern for this is HH
. The symbol, hh
is used for a time in 12-Hour (i.e. with am/pm) format.Apart from this, I recommend you always use Locale
with a date parsing/formatting API because parts of a date-time string are represented in different ways in different Locale
s.
Demo:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);
Date date = sdf.parse("2011-04-11T22:27:18.491-05:00");
// Print the default string i.e. Date#toString
System.out.println(date);
// Print the date-time in a custom format
sdf.setTimeZone(TimeZone.getTimeZone("GMT-05:00"));
System.out.println(sdf.format(date));
}
}
Output:
Tue Apr 12 04:27:18 BST 2011
2011-04-11T22:27:18.491-05:00
Some facts about legacy date-time API:
java.util.Date
object is not a real date-time object like the modern date-time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT
(or UTC). When you print an object of java.util.Date
, its toString
method returns the date-time in the JVM's timezone, calculated from this milliseconds value. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFormat
and obtain the formatted string from it.java.util
date-time API and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API* .Using modern date-time API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
OffsetDateTime odt = OffsetDateTime.parse("2011-04-11T22:27:18.491726-05:00");
// Print the default string i.e. OffsetDateTime#toString
System.out.println(odt);
// Print the date-time in a custom format. Note: OffsetDateTime#toString drops
// seconds if it is zero
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSSSSXXX");
System.out.println(dtf.format(odt));
}
}
Output:
2011-04-11T22:27:18.491726-05:00
2011-04-11T22:27:18.491726-05:00
Note: For DateTimeFormatter
, the symbol, u
means year whereas the symbol, y
means year-of-era. It doesn't make any difference for a year in the [AD][2] era, but it matters for a year in the BC era. Check this answer to learn more about it.
Learn more about the modern date-time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With