ZetCode

Java ZoneOffset Class

Last modified: April 16, 2025

The java.time.ZoneOffset class represents a fixed time zone offset from UTC/Greenwich. It is used to handle time zone differences in hours, minutes and seconds. ZoneOffset is immutable and thread-safe.

ZoneOffset is typically used with other date-time classes like OffsetDateTime. It supports offsets ranging from +18:00 to -18:00. The class provides constants for common offsets like UTC.

ZoneOffset Class Overview

ZoneOffset provides methods to create and manipulate fixed time zone offsets. Key operations include parsing strings, comparing offsets, and getting total offset seconds. The class handles daylight saving time transitions.

public final class ZoneOffset implements ZoneId, TemporalAccessor,
    TemporalAdjuster, Comparable<ZoneOffset>, Serializable {
    public static final ZoneOffset UTC;
    public static ZoneOffset of(String offsetId);
    public static ZoneOffset ofHours(int hours);
    public static ZoneOffset ofHoursMinutes(int hours, int minutes);
    public static ZoneOffset ofHoursMinutesSeconds(int hours, int minutes, int seconds);
    public static ZoneOffset ofTotalSeconds(int totalSeconds);
    public int getTotalSeconds();
    public String getId();
    public boolean equals(Object obj);
}

The code above shows key methods provided by ZoneOffset. These methods allow creating and working with fixed time zone offsets. The UTC constant represents the zero offset from Greenwich.

Creating ZoneOffset Objects

ZoneOffset objects can be created in several ways. The most common methods are of for string parsing and factory methods for specific offsets. The UTC constant is also available.

Main.java
package com.zetcode; 

import java.time.ZoneOffset;

public class Main {

    public static void main(String[] args) {
        
        // UTC constant
        ZoneOffset utc = ZoneOffset.UTC;
        System.out.println("UTC offset: " + utc);
        
        // From string
        ZoneOffset offset1 = ZoneOffset.of("+02:00");
        System.out.println("+02:00 offset: " + offset1);
        
        // From hours
        ZoneOffset offset2 = ZoneOffset.ofHours(5);
        System.out.println("+05:00 offset: " + offset2);
        
        // From hours and minutes
        ZoneOffset offset3 = ZoneOffset.ofHoursMinutes(5, 30);
        System.out.println("+05:30 offset: " + offset3);
        
        // From total seconds
        ZoneOffset offset4 = ZoneOffset.ofTotalSeconds(3600);
        System.out.println("+01:00 offset (from seconds): " + offset4);
    }
}

This example demonstrates different ways to create ZoneOffset objects. The output shows various time zone offsets. Note that string format must follow ISO-8601 time zone designator pattern.

Getting Offset Information

A ZoneOffset can provide its total offset in seconds and its string ID. These values are useful for calculations and display purposes. The methods provide access to the offset's fundamental properties.

Main.java
package com.zetcode; 

import java.time.ZoneOffset;

public class Main {

    public static void main(String[] args) {

        ZoneOffset offset = ZoneOffset.of("+05:30");
        
        // Get total offset in seconds
        int totalSeconds = offset.getTotalSeconds();
        System.out.println("Total seconds: " + totalSeconds);
        
        // Get ID string
        String id = offset.getId();
        System.out.println("ID: " + id);
        
        // Calculate hours and minutes
        int hours = totalSeconds / 3600;
        int minutes = (totalSeconds % 3600) / 60;
        System.out.printf("Human-readable: %+02d:%02d%n", hours, minutes);
    }
}

This example shows how to extract information from a ZoneOffset. The getTotalSeconds method returns the complete offset in seconds. The ID follows the ISO-8601 format for time zone offsets.

Comparing ZoneOffsets

ZoneOffsets can be compared to determine their relative positions from UTC. The class provides equals and compareTo methods. These comparisons are useful for sorting or grouping by time zone.

Main.java
package com.zetcode; 

import java.time.ZoneOffset;

public class Main {

    public static void main(String[] args) {

        ZoneOffset offset1 = ZoneOffset.of("+02:00");
        ZoneOffset offset2 = ZoneOffset.of("+05:30");
        ZoneOffset offset3 = ZoneOffset.of("-03:00");
        
        // Equality check
        ZoneOffset sameOffset = ZoneOffset.ofHours(2);
        System.out.println("Equals check: " + offset1.equals(sameOffset));
        
        // Comparison
        System.out.println("Compare +02:00 and +05:30: " + 
            offset1.compareTo(offset2));
        System.out.println("Compare +02:00 and -03:00: " + 
            offset1.compareTo(offset3));
        
        // Sorting example
        System.out.println("Is +02:00 before +05:30? " + 
            (offset1.compareTo(offset2) < 0));
    }
}

This example demonstrates various ways to compare ZoneOffset objects. The comparison is based on total seconds from UTC. Note that equal offsets will always have the same string representation.

Using ZoneOffset with Other Classes

ZoneOffset is often used with other date-time classes like OffsetDateTime. These combinations allow representing date-time values with specific offsets. The integration is seamless in the Java Time API.

Main.java
package com.zetcode; 

import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.LocalDateTime;

public class Main {

    public static void main(String[] args) {

        ZoneOffset offset = ZoneOffset.of("+05:30");
        
        // Create OffsetDateTime with offset
        OffsetDateTime odt = OffsetDateTime.now(offset);
        System.out.println("Current date-time with offset: " + odt);
        
        // Convert LocalDateTime to OffsetDateTime
        LocalDateTime ldt = LocalDateTime.now();
        OffsetDateTime odt2 = ldt.atOffset(offset);
        System.out.println("Local date-time with offset: " + odt2);
        
        // Extract offset from OffsetDateTime
        ZoneOffset extractedOffset = odt.getOffset();
        System.out.println("Extracted offset: " + extractedOffset);
    }
}

This example shows how ZoneOffset works with other date-time classes. The atOffset method attaches an offset to a local date-time. All operations preserve the exact time being represented.

Handling Maximum and Minimum Offsets

ZoneOffset supports offsets from +18:00 to -18:00. Attempting to create offsets outside this range throws an exception. The class validates all input values.

Main.java
package com.zetcode; 

import java.time.ZoneOffset;

public class Main {

    public static void main(String[] args) {

        // Maximum offset
        ZoneOffset maxOffset = ZoneOffset.of("+18:00");
        System.out.println("Maximum offset: " + maxOffset);
        
        // Minimum offset
        ZoneOffset minOffset = ZoneOffset.of("-18:00");
        System.out.println("Minimum offset: " + minOffset);
        
        try {
            // Invalid offset (too large)
            ZoneOffset invalid = ZoneOffset.of("+19:00");
        } catch (Exception e) {
            System.out.println("Caught exception: " + e.getMessage());
        }
        
        // Edge case in seconds
        ZoneOffset edgeCase = ZoneOffset.ofTotalSeconds(18 * 3600);
        System.out.println("Edge case offset: " + edgeCase);
    }
}

This example demonstrates the valid range for ZoneOffset. The class enforces the +18:00 to -18:00 limit strictly. All factory methods perform this validation.

ZoneOffset vs ZoneId

ZoneOffset differs from ZoneId in representing fixed offsets versus full time zone rules. ZoneOffset is simpler but doesn't handle daylight saving time. ZoneId is more flexible but complex.

Main.java
package com.zetcode; 

import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {

    public static void main(String[] args) {

        // ZoneOffset example
        ZoneOffset offset = ZoneOffset.of("+02:00");
        System.out.println("Fixed offset: " + offset);
        
        // ZoneId example
        ZoneId zone = ZoneId.of("Europe/Paris");
        System.out.println("Full time zone: " + zone);
        
        // Both can be used with ZonedDateTime
        ZonedDateTime zdt1 = ZonedDateTime.now(offset);
        System.out.println("With offset: " + zdt1);
        
        ZonedDateTime zdt2 = ZonedDateTime.now(zone);
        System.out.println("With zone: " + zdt2);
        
        // ZoneOffset is a ZoneId
        System.out.println("Is ZoneOffset a ZoneId? " + 
            (offset instanceof ZoneId));
    }
}

This example compares ZoneOffset and ZoneId usage. While both can be used as ZoneIds, ZoneOffset provides fixed offsets only. ZoneId handles daylight saving and historical changes.

Source

Java ZoneOffset Class Documentation

In this article, we've covered the essential methods and features of the Java ZoneOffset class. Understanding these concepts is crucial for accurate time zone handling in Java applications.

Author

My name is Jan Bodnar, and I am a dedicated programmer with many years of experience in the field. I began writing programming articles in 2007 and have since authored over 1,400 articles and eight e-books. With more than eight years of teaching experience, I am committed to sharing my knowledge and helping others master programming concepts.

List all Java tutorials.