Calendar object in Java, returns wrong time?

So I've been working on a simple little method which would return a String as Calendar object.

Here's what I have:

Calendar cal = Calendar.getInstance();

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.ENGLISH);

try {
    cal.setTime(sdf.parse(this.getCreated_at()));
}
catch (ParseException e) {
    e.printStackTrace();
}

return cal;

Now assuming that the String obtained from this.getCreated_at()) is always in the desired format, this should, theoretically, work perfectly.

There's only one little hiccup.

Assume that this.getCreated_at()) returns Mon Feb 10 18:52:54 +0000 2014. Shouldn't be a problem right? The format is correct, and everything.

However when I have my main method do as follows:

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy");

System.out.println(sdf.format(... ... ....stringToCalendar().getTime())); 

It gives me the following output:

ma feb 10 19:52:54 +0100 2014

My problem, as you may have noticed, is that firstly, the time is wrong. It's added an hour.

Secondly, it's translated the text fields Mon and Feb into ma and feb which are translations to Norwegian, the place from where I'm coding now.

I need the time returned to me as a Calendar object, in the exact manner which it was obtained from the this.getCreated_at())-string.

What am I doing wrong?

Can anyone help me out?

I'm from Norway, by the way. That's +01:00 Standard Offset.

Jon Skeet
people
quotationmark

My problem, as you may have noticed, is that firstly, the time is wrong. It's added an hour.

No it hasn't. Not really. It's displaying the exact same time, but in your local time zone. Unfortunately you can't easily determine the original time zone, because DateFormat.parse returns a Date, which doesn't contain any time zone information. (In this case you don't really know the full time zone anyway - you just know the UTC offset, which isn't quite the same thing.)

EDIT: As noted in Joni's answer, it appears that DateFormat.parse does retain the original information in the format's calendar; you wouldn't want the time zone, but you could use the offset stored in the Calendar object. Personally this seems to me to be an implementation detail which I wouldn't want to rely on (especially as you end up with an offset which isn't necessarily supported by the time zone in the same calendar object!) but you could mangle it if you really wanted.

Secondly, it's translated the text fields Mon and Feb into ma and feb which are translations to Norwegian, the place from where I'm coding now.

That's because your SimpleDateFormat is using your default locale.

You can fix this part very easily:

SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy",
    Locale.ENGLISH);

If you know what time zone you want to use, you can specify that on the SimpleDateFormat as well. Otherwise, you're going to have a slightly harder time.

I would recommend that instead, you start using Joda Time. That way you can parse the value as a DateTime, which "knows" which time zone it's in - so you can reformat it however you want, preserving the relevant time zone information.

Sample Joda Time code:

import java.util.*;
import org.joda.time.*;
import org.joda.time.format.*;

class Test {
    public static void main(String[] args) {        
        DateTimeFormatter format = DateTimeFormat
            .forPattern("EEE MMM dd HH:mm:ss Z yyyy")
            .withLocale(Locale.ENGLISH);

        String input = "Mon Feb 10 18:52:54 +0000 2014";

        DateTime value = format.parseDateTime(input);
        System.out.println(format.print(value));
    }
}

people

See more on this question at Stackoverflow