7

I was looking for the simplest way to convert a date an time from GMT to my local time. Of course, having the proper DST dates considered and as standard as possible.

The most straight forward code I could come up with was:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String inpt = "2011-23-03 16:40:44";
Date inptdate = null;
try {
    inptdate = sdf.parse(inpt);
} catch (ParseException e) {e.printStackTrace();}   
Calendar tgmt = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
tgmt.setTime(inptdate);

Calendar tmad = new GregorianCalendar(TimeZone.getTimeZone("Europe/Madrid"));
tmad.setTime(inptdate);

System.out.println("GMT:\t\t" + sdf.format(tgmt.getTime()));
System.out.println("Europe/Madrid:\t" + sdf.format(tmad.getTime()));

But I think I didn't get the right concept for what getTime will return.

pb2q
  • 58,613
  • 19
  • 146
  • 147
filippo
  • 5,583
  • 13
  • 50
  • 72
  • How are you getting `TimeZone.getTimeZone("Europe/Madrid")` to work?Im getting the error `The method getTimeZone(String) is undefined for the type TimeZone` – johnvdenley Aug 15 '12 at 23:39
  • Nothing fancy... This is a snippet the actual working code: http://pastebin.com/5u79mBMW Runs on Java 1.5 several times a day. – filippo Aug 17 '12 at 16:26
  • 1
    Ah apologies since writing this I have discovered that I am using the GWT version of TimeZone, and in that it doesn't allow a string as an argument! – johnvdenley Aug 17 '12 at 23:06
  • 1
    possible duplicate of [Timezone conversion](http://stackoverflow.com/questions/6567923/timezone-conversion) – Zsolt Botykai Sep 30 '12 at 06:06
  • So your date is the 3rd day of the 23rd month of 2011?? Did you intend `2011-03-23 16:40:44`? – Ole V.V. Aug 29 '17 at 09:27

5 Answers5

14

The catch here is that the DateFormat class has a timezone. Try this example instead:

    SimpleDateFormat sdfgmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdfgmt.setTimeZone(TimeZone.getTimeZone("GMT"));

    SimpleDateFormat sdfmad = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sdfmad.setTimeZone(TimeZone.getTimeZone("Europe/Madrid"));

    String inpt = "2011-23-03 16:40:44";
    Date inptdate = null;
    try {
        inptdate = sdfgmt.parse(inpt);
    } catch (ParseException e) {e.printStackTrace();}

    System.out.println("GMT:\t\t" + sdfgmt.format(inptdate));
    System.out.println("Europe/Madrid:\t" + sdfmad.format(inptdate));
Sebastiaan van den Broek
  • 5,818
  • 7
  • 40
  • 73
  • 1
    Didn't realise the DateFormat classes have their own timezone. Dates in Java are messy. – CodeClimber Dec 07 '12 at 12:08
  • Sorry for the late reply ;) but it kinda makes sense that DateFormat classes have a timezone, without knowing a timezone a string that represents some form of date isn't really meaningful (at least not without timezone information contained in the string) so in order to convert to a date from a simple datetime string you need to specify a timezone. – Sebastiaan van den Broek Oct 02 '14 at 11:58
4

Here is the 2017 answer.

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    String inpt = "2011-03-23 16:40:44";

    ZonedDateTime madridTime = LocalDateTime.parse(inpt, dtf)
            .atOffset(ZoneOffset.UTC)
            .atZoneSameInstant(ZoneId.of("Europe/Madrid"));

    System.out.println("GMT:\t\t" + inpt);
    System.out.println("Europe/Madrid:\t" + madridTime.format(dtf));

Please enjoy how much more naturally this code expresses the intent.

The code prints

GMT:        2011-03-23 16:40:44
Europe/Madrid:  2011-03-23 17:40:44

(with tab size of 8 it aligns nicely, but StackOverflow seems to apply a tab size of 4).

I swapped 23 and 03 in your input string, I believe you intended this. BTW, it wasn’t me catching your mistake, it was LocalDateTime.parse() throwing an exception because there is no 23rd month. Also in this respect the modern classes are more helpful than the outdated ones.

Joda-Time? Basil Bourque’s answer mentions and recommends both java.time, which I am using, and Joda-Time. While Joda-Time is already a sizeable improvement over the outdated classes used in the question (SimpleDateFormat, Calendar, GregorianCalendar), it is by now in maintenance mode; no greater further development is expected. java.time is hugely inspired by Joda-Time. For new code, I see no reason why you shouldn’t prefer java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

The simplest way is to use a decent date-time library rather than the notoriously troublesome java.util.Date and .Calendar classes. Instead use either Joda-Time or the java.time package found in Java 8.

Joda-Time

String input = input.replace( " ", "T" ).concat( "Z" ) ; // proper ISO 8601 format for a date-time in UTC.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Madrid" );
DateTime dateTime = new DateTime( input, timeZone );
String output = dateTime.toString();
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

For the input, you can simply add the Timezone to the String (note the 'z' in the format):

new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss z").parse ("2011-23-03 16:40:44 GMT");
user unknown
  • 35,537
  • 11
  • 75
  • 121
0

You need to set the TimeZone on the SimpleDateFormat, using DateFormat.setTimeZone().

Bombe
  • 81,643
  • 20
  • 123
  • 127