As an input I have a string which is a String in ISO 8601 to represent date. For example:
"2017-04-04T09:00:00-08:00"
The last part of String
, which is "-08:00" denotes TimeZone Offset. I convert this string into a Calendar
instance as shown below:
Calendar calendar = GregorianCalendar.getInstance();
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).parse(iso8601Date);
calendar.setTime(date);
iso8601Date is "2017-04-04T09:00:00-08:00"
But this does not pick timezone and if I get timezone from Calendar
instance, it gives currently set instance of the laptop and does not pick up timestamp from ISO 8601 String. I check for timezone via calendar instance as:
calendar.getTimeZone().getDisplayName()
Can someone show how to pick timezone also in the Calendar
instance?
When you create a
Calendar
, it takes the JVM's default timezone. And when you parse aString
to aDate
, it just sets one value: the number of milliseconds since epoch (1970-01-01T00:00Z
). ADate
doesn't have any timezone information, just this milliseconds value. So you need to set the timezone in the calendar.In your formatter, you're treating
Z
as a literal, because it's inside quotes ('Z'
). This ignores the offset and gets the date in the JVM default timezone (which will have a different value if the corresponding offset is not -08:00).In JDK >= 7, you can use the
X
pattern to parse the offset:But this doesn't set the timezone in the calendar (it will still use the JVM's default). So, a "better" way is to strip the offset from the input and handle it separately:
With this, the calendar will have the offset
-08:00
set. As @BasilBourque's answer already said,-08:00
is an offset, not a timezone (theTimeZone
class treats offsets just like they were timezones, which is a workaround/bad design choice).Java new Date/Time API
The old classes (
Date
,Calendar
andSimpleDateFormat
) have lots of problems and design issues, and they're being replaced by the new APIs.In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. You'll also need the ThreeTenABP to make it work (more on how to use it here).
@BasilBourque's answer already tells you about
OffsetDateTime
. But to convert to aCalendar
, you can use aorg.threeten.bp.ZonedDateTime
and convert it using theorg.threeten.bp.DateTimeUtils
class:The calendar will be already set with the
-08:00
offset.If you want to get the timezone from the offset, I'm afraid it's not that simple. More than one timezone can use the same offset, so you can't know for sure which timezone to use (the best you can do is to get a list of possible candidates).
java.util.Date
Just a more detailed note about
java.util.Date
. This link explains a lot about it, so I really recommend you to read it.As already said above, a
Date
has no timezone information. It just keeps the number of milliseconds since epoch (which is1970-01-01T00:00Z
, or January 1st 1970 at midnight in UTC).This value is the same everywhere in the world. Example: at the moment I'm writing this, the millis value for the current time is
1504632865935
. This number is the same for anyone in the world who gets the current time at the same instant I did, regardless of what timezone they're using.What is different is the local date and time that corresponds to this millis value. In UTC, it corresponds to
2017-09-05T17:34:25.935Z
, in New York, the date is the same (September 5th 2017) but the time is different (13:34), and in Tokyo is September 6th 2017 at 02:34 AM.Although the
Date
object is the same (because its millis value is1504632865935
for everyone), the corresponding date and time changes according to the timezone used.People tend to think that a
Date
has a timezone because when printing it (withSystem.out.println
or by loggging) or when inspecting in a debugger, it implicity uses thetoString()
method, and this converts the date to the JVM's default timezone (and it also prints the zone name). This gives the impression that aDate
has a format and a timezone set to it, but it doesn't.