How to replace sun.util.caldender.ZoneInfo with new API in java

I found this Api Sun.util.calendar.zoneInfo inside one of my Testcase and when I compile it I got the waring message it saying sun.util.calender.ZoneInfo is internal proprietary API and may be removed in a future release

@Test @Ignore("This test case was previously ignore, appears incomplete")
    public void test_getTimeZoneFromTimeZoneDifferential() throws Exception {
        TimeZone customCali = DMessageFactory.getTimeZoneFromTimeZoneDifferential("110");
        System.out.println("\ncustomCali: "+customCali+"\n");
        String[] ids = TimeZone.getAvailableIDs();
        for(int i = 0; i < ids.length; i++) {
            TimeZone tz = TimeZone.getTimeZone(ids[i]);

            if(tz instanceof sun.util.calendar.ZoneInfo) {
                TimeZone realZone = ((sun.util.calendar.ZoneInfo) tz).getLastRuleInstance();
                if(realZone == null) {
                    if(tz.useDaylightTime() == customCali.useDaylightTime() &&
                       tz.getOffset(0) == customCali.getOffset(0)) {
                        System.out.println("match2: "+tz+"   "+tz.getDisplayName(true, TimeZone.SHORT));
                    }
                    //System.out.println("no real zone: "+tz);
                    continue;
                }

                if(customCali.hasSameRules(realZone)) {
                    System.out.println("match: "+realZone.getDisplayName(true, TimeZone.SHORT));
                }
                else if(realZone.getOffset(0) == customCali.getOffset(0)) {
                    //System.out.println("semi-match: "+tz);
                }
                else {
                    //System.out.println("NO-match: "+tz);
                }
            } else {
                //System.out.println("no-match: "+tz);
            }
        }

I really need to replace this sun.util.calendar.ZoneInfo and add another API without breaking its function, please help me out with this.

1 answer

  • answered 2019-03-13 19:28 Basil Bourque

    tl;dr

    Use the modern java.time classes instead.

    Loop all known zones, ask for the set of rules for that zone, specify a moment, and interrogate for the info you need.

    Instant instant = Instant.now() ;
    for( ZoneId z : ZoneId.getAvailableZoneIds() )
    {
        String zoneName = z.getDisplayName( TextStyle.SHORT , Locale.US ) ;
    
        ZoneRules rules = z.getRules() ;
    
        ZoneOffset offset = rules.getOffset​( instant ) ;
        int secondsOfOffset = offset.getTotalSeconds() ;
    
        boolean currentlyInDST = rules.isDaylightSavings( instant ) ;
        Duration amountOfCurrentDstAdjustment = rules.getDaylightSavings( instant ) ;
    
        …
    }
    

    sun.util.calender.ZoneInfo is implementation backing TimeZone (both obsolete)

    According to this class JavaDoc, this is simply the concrete implementation backing the TimeZone class for JVMs provided by Sun.

    ZoneInfo is an implementation subclass of TimeZone that represents GMT offsets and daylight saving time transitions of a time zone.

    Both TimeZone and ZoneInfo are obsolete. You should be using the modern java.time classes instead.

    When building the Java Platform Module System, Oracle began phasing out access to parts of their Java implementation that have become obsolete or were never intended for public consumption. This is an ongoing process. Any of your code calling on classes from the various com.sun.* packages should be rewritten to use other classes.

    java.time

    TimeZone is one of the terrible date-time classes bundled with the earliest versions of Java. These are now legacy, supplanted years ago by the modern industry-leading java.time classes defined in JSR 310.

    ZoneId = a time zone

    A time zone is now represented with the ZoneId class, replacing TimeZone. The history of past, present, and future changes to the offset-from-UTC used by each region in a zone is tracked by the ZoneRules class.

    tzdata

    Be aware that time zones are frequently changed by politicians around the world. This happens more frequently than you might think. These changes are tracked by the the tzdata data file. Whenever changes occur in a zone you care about, you should update this time zone definition list in your installations of Java, your operating system, databases such as Postgres, and other libraries that manage their own time zone list.

    Zone rules

    Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

    ZoneId z = ZoneId.of( "America/Montreal" ) ;  
    

    Get the rules of that zone.

    ZoneRules rules = z.getRules() ;
    

    Zone rules for an Instant

    An Instant represents a moment in UTC, that is, a moment with an offset-from-UTC of zero hours-minutes-seconds. By specifying a moment, you can ask questions of the rules in effect at that time.

    Instant instant = Instant.now() ;
    boolean currentlyInDST = rules.isDaylightSavings( instant ) ;
    Duration amountOfCurrentDstAdjustment = rules.getDaylightSavings( instant ) ;
    

    Looping zones

    You can re-implement your code by getting all time zones known by the embedded tzdata by calling the ZoneId.getAvailableZoneIds method. You can loop the returned Set.

    Set< String > zones = ZoneId.getAvailableZoneIds() ;
    for( String z : zones )
    {
        ZoneRules rules = ZoneId.of( z ).getRules() ;
        …
    }
    

    You do not explain your code such as what this means:

    DMessageFactory.getTimeZoneFromTimeZoneDifferential("110")
    

    …so there is not much more I can do for you.

    Your code seems to be looking for a time zone that matches its offset-from-UTC (hours-minutes-seconds) and whether in Daylight Saving Time (DST) or not. As discussed above, you can interrogate the ZoneRules for this info.


    About java.time

    The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

    To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

    The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

    You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

    Where to obtain the java.time classes?

    The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.