Oliver Kohll
Oliver Kohll

Reputation: 790

How do I get British Summertime offset (BST) in Java

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.

Upvotes: 11

Views: 22089

Answers (5)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79395

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.

Upvotes: 1

4lberto
4lberto

Reputation: 555

This made me the trick:

String zone = "Europe/London";
int plusHoursGMT = TimeZone.getTimeZone(zone).getRawOffset() / 3600000;
assertThat(plusHoursGMT, is(0));

Upvotes: 0

Jesse Barnum
Jesse Barnum

Reputation: 6846

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.

Upvotes: 1

user1016765
user1016765

Reputation: 3063

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...

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1502076

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

Upvotes: 15

Related Questions