5

I am pretty new to Java and I am a little stuck with using SimpleDateFormat and Calendar. I have a Date-Object and want to extract a GMT datestring like yyyy-MM-dd HH:mm:ss. I live in Germany and at the moment we are GMT +0200. My Date-Object's time is for example 2011-07-18 13:00:00. What I need now is 2011-07-18 11:00:00. The offset for my timezone should be calculated automatically.

I tried something like this, but I guess there is a fault somewhere:

private String toGmtString(Date date){
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    TimeZone timeZone = TimeZone.getDefault();
    Calendar cal = Calendar.getInstance(new SimpleTimeZone(timeZone.getOffset(date.getTime()), "GMT"));
    sd.setCalendar(cal);
    return sd.format(date);
}

On some devices the datestring is returned like I want it to. On other devices the offset isn't calculated right and I receive the date and time from the input date-object. Can you give me some tips or advices? I guess my way off getting the default timezone does not work?

Marco
  • 960
  • 2
  • 7
  • 26

3 Answers3

5
private String toGmtString(Date date){
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sd.setTimeZone(TimeZone.getTimeZone("GMT"));
    return sd.format(date);
}

You don't need to create a new SimpleTimeZone, because you aren't inventing a new timezone - there are 2 existing timezones that come into play in your program, GMT and your default one.

You also don't need to modify your existing date object, because you don't want to represent a different point in time - you only want a different way to display the same point in time.

All you need to do is tell the SimpleDateFormat which timezone to use in formatting.

Eli Acherkan
  • 6,401
  • 2
  • 27
  • 34
  • I can't believe that it is that easy, but of course I will try that too. Give me some minutes please... – Marco Jul 18 '11 at 11:30
  • Ok.. Tested.. I used a date-object which represents `2011-07-18 13:34:27`. Using the default date function `.toGMTString()` I receive `18 Jul 2011 11:43:27 GMT` which is the exact point in time that I need.Using my own function I still receive `2011-07-18 13:43:27` which was my problem. Using Jigar Joshin's function I receive `2011-07-18 12:43:27` which is missing 1 hour (european summertime). Using Eli Acherkans function I receive `2011-07-18 11:43:27` which is exactly what I wanted to (Offset including european summertime). – Marco Jul 18 '11 at 11:53
  • You're a live saver @EliAcherkan! – Doug Ayers Aug 13 '15 at 21:25
2
private String toGmtString(Date date){
    //date formatter
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //getting default timeZone
    TimeZone timeZone = TimeZone.getDefault();
    //getting current time
    Calendar cal = Calendar.getInstance()
    cal.setTime(date) ;
    //adding / substracting curren't timezone's offset
    cal.add(Calendar.MILLISECOND, -1 * timeZone.getRawOffset());    
    //formatting and returning string of date
    return sd.format(cal.getTime());
}
jmj
  • 237,923
  • 42
  • 401
  • 438
  • Ok this is looking good. I will give it a try in a few minutes. One question. Where and how did you use the date-parameter from the function call?! Should I use `cal.setTime(date);` after getting the instance? – Marco Jul 18 '11 at 09:40
  • Nice! Works! Thank you very much! – Marco Jul 18 '11 at 09:46
  • 1
    @Jigar Joshi: you're modifying the point in time instead of modifying the way it's displayed. Your `cal` object doesn't represent the point in time that is {13:00 in Germany, 11:00 in Greenwich} - it rather represents {11:00 in Germany, 09:00 in Greenwich}. I don't think that this was the intention. – Eli Acherkan Jul 18 '11 at 10:48
  • 1
    I think this is what OP wanted – jmj Jul 18 '11 at 10:50
  • @JigarJoshi, Hi, do you know how to convert UTC time to GMT time ? – Lucifer Sep 18 '12 at 05:33
0

java.time

Using java.time, the modern date-time API, there are many ways to do it:

  1. Parse to LocalDateTime ➡️ Combine it with your timezone to get ZonedDateTime ➡️ Convert to Instant ➡️ Convert to ZonedDateTime using Instant#atZone and UTC timezone.
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-07-18 13:00:00";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);

        LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);

        // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
        // ZoneId.systemDefault()
        Instant instant = ldt.atZone(ZoneId.of("Europe/Berlin")).toInstant();

        ZonedDateTime zdtUtc = instant.atZone(ZoneId.of("Etc/UTC"));

        System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
    }
}
  1. Parse to LocalDateTime ➡️ Combine it with your timezone to get ZonedDateTime ➡️ Convert to Instant ➡️ Convert to ZonedDateTime using ZonedDateTime#ofInstant and UTC timezone.
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-07-18 13:00:00";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);

        LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);

        // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
        // ZoneId.systemDefault()
        Instant instant = ldt.atZone(ZoneId.of("Europe/Berlin")).toInstant();

        ZonedDateTime zdtUtc = ZonedDateTime.ofInstant(instant, ZoneId.of("Etc/UTC"));

        System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
    }
}
  1. Using ZonedDateTime#withZoneSameInstant:
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-07-18 13:00:00";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);

        LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);

        // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
        // ZoneId.systemDefault()
        ZonedDateTime zdtPak = ldt.atZone(ZoneId.of("Europe/Berlin"));

        ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));

        System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
    }
}
  1. Using DateTimeFormatter#withZone and ZonedDateTime#withZoneSameInstant:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-07-18 13:00:00";

        // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
        // ZoneId.systemDefault()
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
                                        .withZone(ZoneId.of("Europe/Berlin"));

        ZonedDateTime zdtPak = ZonedDateTime.parse(strDateTime, dtfInput);

        ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));

        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
        System.out.println(zdtUtc.format(dtfOutput)); // 2011-07-18 11:00:00
    }
}

Learn more about the modern date-time API* from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110