10

In the UK, I'd like to get the current offset from UTC/GMT. Currently the offset is 1 hour, but there seems to be no way of finding this.

Code

    TimeZone timeZone = TimeZone.getDefault();
    logger.debug("Timezone ID is '" + timeZone.getID() + "'");
    if (timeZone.getID().equals("GMT")) {
        timeZone = TimeZone.getTimeZone("Europe/London");
        logger.debug("New timezone is '" + timeZone.getID() + "'");
    }
    Long eventDateMillis = Long.parseLong(eventDateValue.getKeyValue());
    int timezoneOffset = timeZone.getOffset(eventDateMillis);
    logger.debug("Offset for " + eventDateValue + "(" + eventDateMillis + ") using timezone " + timeZone.getDisplayName() + " is " + timezoneOffset);

returns debug output

Wed 2012/09/19 16:38:19.503|Debug|DataManagement|Timezone ID is 'GMT'
Wed 2012/09/19 16:38:19.503|Debug|DataManagement|New timezone is 'GMT'
Wed 2012/09/19 16:38:19.557|Debug|DataManagement|Offset for 18 Sep 2012 09:00(1347958800000) using timezone Greenwich Mean Time is 0

In other words, timezone 'GMT' is returning an offset of zero and I can't find how to set it to something that does return the correct offset.

If someone can provide a working code sample for JodaTime, that would do but I'd really like to avoid having to install a separate library just for what should be a one-liner.

The Java version is 7.

Oliver Kohll
  • 772
  • 2
  • 7
  • 19
  • You say "correct offset". What would the correct offset be for GMT? – km1 Sep 19 '12 at 16:55
  • GMT/UTC should be 0, what I want is BST, which should be 1 hour's worth of ms currently: http://www.timeanddate.com/worldclock/city.html?n=136 – Oliver Kohll Sep 19 '12 at 16:57
  • Here is the output I get for the following code: `TimeZone timeZone = TimeZone.getTimeZone("Europe/London"); int timezoneOffset = timeZone.getOffset(System.currentTimeMillis()); System.out.println("Offset for timezone " + timeZone.getID() + " is " + timezoneOffset);` => `Offset for timezone Europe/London is 3600000` which is pretty much what you expect no ? – aymeric Sep 19 '12 at 17:20

5 Answers5

14

In other words, timezone 'GMT' is returning an offset of zero and I can't find how to set it to something that does return the correct offset.

0 is the correct offset for GMT, permanently.

You want "Europe/London", which is the time zone which switches between GMT and BST.

EDIT: I hadn't originally noticed that you're trying to get Europe/London. It looks like the time zone database your JVM is using is basically messed up. You could either try fixing that, or simply use Joda Time which comes with its own copy of tzdb. Sample code:

DateTimeZone zone = DateTimeZone.forID("Europe/London");
long offset = zone.getOffset(new Instant());
System.out.println(offset); // 3600000
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
2

I just encountered this myself.

I tried TimeZone.getTimeZone("London"); and it worked.

No I have no idea why - 'London' isn't one of the IDs TimeZone returns...

user1016765
  • 2,935
  • 2
  • 32
  • 48
1

Use timezone.getOffset( 0 ), instead of timezone.getOffset( eventDateMillis ).

This will give you the offset as of January 1st, 1970 GMT time, which in the case of Europe/London is 3600000, NOT zero due to historical issues with Wales and Northern Ireland.

Jesse Barnum
  • 6,507
  • 6
  • 40
  • 69
1

java.time

java.time.ZonedDateTime has been designed to adjust the timezone offset automatically.

Demo:

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        LocalTime time = LocalTime.of(10, 20);
        ZoneId zoneId = ZoneId.of("Europe/London");

        // A winter date-time
        ZonedDateTime zdtWinter = ZonedDateTime.of(LocalDate.of(2020, 11, 22), time, zoneId);
        System.out.println(zdtWinter);

        // A summer date-time
        ZonedDateTime zdtSummer = ZonedDateTime.of(LocalDate.of(2021, 07, 22), time, zoneId);
        System.out.println(zdtSummer);
    }
}

Output:

2020-11-22T10:20Z[Europe/London]
2021-07-22T10:20+01:00[Europe/London]

ONLINE DEMO

The Z in the output is the timezone designator for zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*. However, for any reason, if you need to convert an object of ZonedDateTime to an object of java.util.Date, you can do so as follows:

Date date = Date.from(zdtSummer.toInstant());

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
0

This made me the trick:

String zone = "Europe/London";
int plusHoursGMT = TimeZone.getTimeZone(zone).getRawOffset() / 3600000;
assertThat(plusHoursGMT, is(0));
4lberto
  • 505
  • 6
  • 14