SimpleDateFormat parse loses timezone
All I needed was this :
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat sdfLocal = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
try {
String d = sdf.format(new Date());
System.out.println(d);
System.out.println(sdfLocal.parse(d));
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
Output : slightly dubious, but I want only the date to be consistent
2013.08.08 11:01:08
Thu Aug 08 11:01:08 GMT+08:00 2013
Java DateFormat parse() doesn't respect the timezone
You're printing the result of calling Date.toString()
, which always uses the default time zone. Basically, you shouldn't use Date.toString()
for anything other than debugging.
Don't forget that a Date
doesn't have a time zone - it represents an instant in time, measured as milliseconds since the Unix epoch (midnight on January 1st 1970 UTC).
If you format the date using your formatter again, that should come up with the same answer as before.
As an aside, I would recommend the use of Joda Time instead of Date
/Calendar
if you're doing any significant amount of date/time work in Java; it's a much nicer API.
SimpleDateFormat.parse() ignoring timezone?
Note: -06:00
is an offset, not a timezone - those 2 concepts are related, but they are different things (more on that below).
The problem with SimpleDateFormat
and Calendar
is that they use the system's default timezone, so even though you parse a date with a different offset (like -06:00
), the resulting Calendar
will have the default timezone (you can check what zone is by calling TimeZone.getDefault()
).
That's just one of the many problems and design issues of this old API.
Fortunately, there's a better alternative, if you don't mind adding a dependency to your project (in this case, I think it's totally worth it). In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP to make it work (more on how to use it here).
To work with offsets, you can use the org.threeten.bp.OffsetDateTime
class:
// parse the String
OffsetDateTime odt = OffsetDateTime.parse("2017-07-26T06:00-06:00");
This will parse all the fields correctly (date/time and offset). To get the offset value, similar to calendar.getTimeZone().getRawOffset()
, you can do:
// get offset in milliseconds
int totalSeconds = odt.getOffset().getTotalSeconds() * 1000;
I had to multiply by 1000 because calendar
returns the value in milliseconds, but ZoneOffset
returns in seconds.
To convert this to another offset (+09:00
), it's straightforward:
// convert to +09:00 offset
OffsetDateTime other = odt.withOffsetSameInstant(ZoneOffset.ofHours(9));
As I said, timezone and offset are different things:
- offset is the difference from UTC:
-06:00
means "6 hours behind UTC" and+09:00
means "9 hours ahead UTC" - timezone is a set of all the different offsets that a region had, has and will have during its history (and also when those changes occur). The most common cases are Daylight Saving Time shifts, when clocks change 1 hour back or forward in a certain region. All these rules about when to change (and what's the offset before and after the change) are encapsulated by the timezone concept.
So, the code above works fine if you're working with offsets and wants to convert to a different one. But if you want to work with a timezone, you must convert the OffsetDateTime
to a ZonedDateTime
:
// convert to a timezone
ZonedDateTime zdt = odt.atZoneSameInstant(ZoneId.of("Asia/Tokyo"));
// get the offset
totalSeconds = zdt.getOffset().getTotalSeconds() * 1000;
The getOffset()
method above will check the history of the specified timezone and get the offset that was active in that corresponding instant (so, if you take a date during DST, for example, the offset (and also date and time) will be adjusted accordingly).
The API uses IANA timezones names (always in the format Region/City
, like America/Sao_Paulo
or Europe/Berlin
).
Avoid using the 3-letter abbreviations (like CST
or PST
) because they are ambiguous and not standard.
You can get a list of available timezones (and choose the one that fits best your system) by calling ZoneId.getAvailableZoneIds()
.
You can also use the system's default timezone with ZoneId.systemDefault()
, but this can be changed without notice, even at runtime, so it's better to explicity use a specific one.
SimpleDateFormat with timezone displaying dates in my timezone, how do I fix this?
You can use the modern java.time package instead and specially ZonedDateTime
that handles time zones.
String str = "2019-12-20T00:00:00.000-05:00";
ZonedDateTime zonedDateTime = ZonedDateTime.parse(str);
And when showing it in the UI use DateTimeFormatter
to convert it to a formatted string
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
or with some custom format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
which will give you for the 2 formats
System.out.println(formatter.format(zonedDateTime));
2019-12-20T00:00-05:00
2019-12-20 00:00
SimpleDateFormat not parsing IST date
Don't use Date or SimpleDateTime. Use the classes in the java.time package.
String date = "Mon, 05 Jul 2021 23:19:58 IST";
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern(
"EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
ZonedDateTime zdt = ZonedDateTime.parse(date,dateFormat);
System.out.println(zdt.format(dateFormat));
prints
Mon, 05 Jul 2021 23:19:58 GMT
EDIT
After perusing the java.time
package I found that ZoneId.SHORT_IDS
contained IST=Asia/Kolkata
. So if one does the following:
ZonedDateTime zdt = ZonedDateTime.parse(date,dateFormat)
.withZoneSameLocal(ZoneId.of("Asia/Kolkata"));
System.out.println(zdt.format(dateFormat));
It prints
Mon, 05 Jul 2021 23:19:58 IST
SimpleDateFormat issue when parsing a String in ISO 8601 format
The date format passed to your SimpleDateFormat
is "dd/MM/yy"
, while the date you are trying to parse is of the format "yyyy-MM-dd"
. Try this instead:
Date login = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ").parse("2017-05-16 06:24:36-0700");
As a side note, depending on which version of Java you are using, I would recommend using the new java.time
package (JDK 1.8+) or the back port of that package (JDK 1.6+) instead of the outdated (no pun intended) Date
and/or Calendar
classes.
Instant login = Instant.from(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssZ").parse("2017-05-16 06:24:36-0700"));
SimpleDateFormat parse is changing time according to timezone
Java's java.util.Date
and java.sql.Timestamp
do not store timezone.
They always track time in UTC.
When parsing a date string that includes a timezone, the string is correctly parsed and adjusted from the given timezone to UTC.
When parsing a date string without timezone, the string is parsed in the JVM's default timezoneand converted to UTC, unless another timezone has been explicitly given to the date parser (commonly SimpleDateFormat
).
When displaying (aka formatting) a Date
/Timestamp
, it will be shown in the JVM's default timezone, unless otherwise specified.
The Date
/Timestamp
objects cannot store a timezone, so they cannot remember what the original timezone was.
If you need that, use Java 8's ZonedDateTime
.
java date parse exception while conveting UTC to local time zone
You have two mistakes in your code.
- As others already mentioned you have additional
'
in your pattern aroundZ
. - You specify the pattern as
dd-MM-yyyy
but try to parse the date asyyyy-MM-dd
.
Correct version:
DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = utcFormat.parse("2015-03-17 06:00:00 +0000");
utcFormat.setTimeZone(TimeZone.getDefault());
System.out.println(utcFormat.format(date));
Related Topics
Java Fileoutputstream Create File If Not Exists
Java - Swing Listen an Action in a Text Field of a Form
How to Read Request.Getinputstream() Multiple Times
Java Http Client Request with Defined Timeout
Difference Between Shutdown and Shutdownnow of Executor Service
Spring MVC + JSON = 406 Not Acceptable
Java Regex for Support Unicode
What Is the Best Way Get the Symmetric Difference Between Two Sets in Java
Javafx Launch Another Application
How to Get Just the Parent Directory Name of a Specific File
Loading Raw 64-Byte Long Ecdsa Public Key in Java
How to Set Auto-Scrolling of Jtextarea in Java Gui
How Is Length Implemented in Java Arrays
Change Text Field Data Color (Foreground Color) Based on Condition in Jasperreports
Comparing Arrays in Junit Assertions, Concise Built-In Way
Test for Floating Point Equality. (Fe_Floating_Point_Equality)