Reputation: 5565
I am trying to format a calendar string to indicate a time zone offset other than my local one. I am aware I could create a simple formatting string and use the Calendar.get(int)
method to fill in all the values, but this does not feel like the right way to do this.
Java has a DateFormat
, specifically I am trying to use the SimpleDateFormat
. The problem is that the format()
method of these classes expects a Date
object.
I am primarily working with Calendar
objects since I believe those are the recommended structure in Java. So, when I go to format my result time, I call Calendar.getTime()
which returns a Date
object which can be passed into the SimpleDateFormat
object.
Until now, I thought this was perfectly simple, but here is where the problem comes in.
Whenever one calls the Calendar.getTime()
method, the Date
returned is always in the local time zone, regardless of the time zone of the Calendar
.
So, I always get the time printed in the local time zone when I pass it to my SimpleDateFormat
, which is not what I want. All the research I have done so far says it can't be done and all the examples I have seen simply use the Calendar.get(int)
method to fill in some blanks. This seems terrible, why have a DateFormat class if it is going to be so useless?
Here is some example code so you can see what I mean, paste this into your favourite test class:
private static final SimpleDateFormat parser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
private static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
public static void main(String[] args)
{
try
{
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
cal.setTimeInMillis(parser.parse("2012-10-09T22:01:49.108-0700").getTime());
System.out.println(formatter.format(cal.getTime()));
}
catch(ParseException e)
{
e.printStackTrace();
}
}
Output produced (because I am running in Central Time Zone): 2012-10-10T00:01:49-0500
Output expected (should not matter what time zone it is run from): 2012-10-10T01:01:49-0400
To summarize question: Is there a way to make the DateFormat in java accept a Calendar, or a way to get a Date that is not in the local timezone, or is there another class I should be using altogether for this formatting?
Upvotes: 1
Views: 3183
Reputation: 735
Date is not having any TimeZone, its just the number of milliseconds since Epoch time, represented in a human readable format. We can use "DateFormat" class.
TimeZone tz = TimeZone.getTimeZone("America/Buenos_Aires");
Calendar cal = Calendar.getInstance(tz);
Date d = cal.getTime();
DateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm aaa");
df.setTimeZone(tz);
String s = df.format(cal.getTime());
System.out.println(s);
Upvotes: 0
Reputation: 122364
I would give up on the built in java date and time classes for this and use joda time instead. It is designed to handle ISO8601 format strings properly and does the right thing with timezones.
Upvotes: 0
Reputation: 1499750
Whenever one calls the Calendar.getTime() method, the Date returned is always in the local time zone, regardless of the time zone of the Calendar.
No, it's not. Date
doesn't have a time zone. It's just the number of milliseconds since the Unix epoch. Its toString()
method does convert it to the local time zone, but that's not part of the information in the Date
object.
All you need to do is set the time zone of the formatter to be the same as the time zone of the calendar.
formatter.setTimeZone(calendar.getTimeZone());
... or just set the calendar to be used entirely:
formatter.setCalendar(calendar);
(It's not immediately clear to me whether the latter approach will mean that the calendar can lose its value... basically the Java classes mix "calendar system", "time zone" and "value within the calendar" in a single type, which is very unfortunate.)
I agree with Ian though, in terms of Joda Time being a far more pleasant API to use.
Upvotes: 3