0

I am trying to evaluate zone offset value as int (like -3, 0 or 3) by giving zoneId value, but I cannot do this by following several approaches on SO.

private int convertToZoneOffset(final int zoneId) {
    Instant instant = Instant.ofEpochSecond(epochSecondNow);
    ZonedDateTime atZone = instant.atZone(ZoneId.of("Asia/Kolkata"));
    return ... ?

}

What is a proper way for Java 11?

  • 1
    At present Asia/Kolkata is at offset +05:30. Do you then want 5 or 6 or a message saying the the offset cannot be represented as an `int`? – Ole V.V. Aug 27 '21 at 15:34
  • 2
    A time zone identified by a `ZoneId` encompasses the historic, present and known future offsets from UTC. They are often many. Very many time zones observe summer time (DST) and have a difference of 30 minutes or an hour between the offset in summer and in winter. Do you want the offset used at the current moment? – Ole V.V. Aug 27 '21 at 15:56
  • 1
    If you're dealing with time zones, I'd recommend this instructional (and funny) video: "The Problem with Time & Timezones - Computerphile" https://youtu.be/-5wpm-gesOY – Modus Tollens Aug 28 '21 at 07:30

1 Answers1

1

I suggest you use ZoneId#getRules to get the ZoneOffset, from which you can get the hours and minutes if required.

Demo:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        // Test
        ZoneOffset offset = convertToZoneOffset(ZoneId.of("Asia/Kolkata"));
        System.out.println(offset);

        long seconds = offset.getTotalSeconds();
        long hours = TimeUnit.HOURS.convert(seconds, TimeUnit.SECONDS);
        long minutes = TimeUnit.MINUTES.convert(seconds, TimeUnit.SECONDS) % 60;
        System.out.println(hours);
        System.out.println(minutes);
    }

    private static ZoneOffset convertToZoneOffset(final ZoneId zoneId) {
        return zoneId.getRules().getOffset(Instant.now());
    }
}

Output:

+05:30
5
30

ONLINE DEMO

The variant using a specific Unix epoch:

private static ZoneOffset convertToZoneOffset(final ZoneId zoneId, long epochSecond) {
    return zoneId.getRules().getOffset(Instant.ofEpochSecond(epochSecond));
}

Also, if you need the hours to be rounded off, you can use the following statement in the code:

long hours = Math.round(seconds / 3600.0);

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