java - 如何使用Java中的新API替换sun.util.calendar.ZoneInfo

标签 java api junit timezone internals

我在我的一个测试用例中找到了这个Api Sun.util.calendar.zoneInfo,当我对其进行编译时,我得到了警告消息,上面指出sun.util.calender.ZoneInfo是内部专有API,在以后的发行版中可能会删除

@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);
            }
        }


我确实需要替换此sun.util.calendar.ZoneInfo并添加另一个API而不破坏其功能,请为此提供帮助。

最佳答案

tl; dr

请改用现代的java.time类。


java.time.ZoneId替代TimeZone
java.time.zone.ZoneRules替代sun.util.calender.ZoneInfo


循环所有已知区域,询问该区域的规则集,指定时间,然后询问所需的信息。

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是实现支持TimeZone(均已淘汰)

根据this class JavaDoc,这只是支持Sun提供的JVM TimeZone类的具体实现。


  ZoneInfo是TimeZone的实现子类,它表示GMT偏移量和时区的夏时制转换。


TimeZoneZoneInfo都已过时。您应该改为使用现代的java.time类。

在构建Java Platform Module System时,Oracle开始逐步淘汰对其Java实现中已过时或从未打算供公众使用的部分的访问。这是一个持续的过程。调用来自各种com.sun.*包的类的任何代码都应重写为使用其他类。

java.time

TimeZone是与最早的Java版本捆绑在一起的可怕的日期时间类之一。这些现在已成为遗留问题,几年前被JSR 310中定义的现代行业领先的java.time类所取代。

ZoneId =时区

现在用ZoneId类表示时区,代替TimeZoneoffset-from-UTC类可跟踪区域中每个区域使用的ZoneRules的过去,现在和将来的更改历史。

数据

请注意,世界各地的政客经常更改时区。这种情况发生的频率超出您的想象。这些更改由tzdata data file跟踪。每当您关心的区域发生更改时,都应该在Java安装,操作系统,数据库(例如Postgres)和其他管理自己的时区列表的库中更新此时区定义列表。

区域规则

Continent/Region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,例如ESTIST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

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


获取该区域的规则。

ZoneRules rules = z.getRules() ;


Instant的区域规则

Instant表示UTC中的时刻,即offset-from-UTC为零小时-分钟-秒的时刻。通过指定时间,您可以询问当时有效的规则。

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


循环区

您可以通过调用ZoneId.getAvailableZoneIds方法获取嵌入式tzdata已知的所有时区来重新实现代码。您可以循环返回的Set

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


您无需解释代码,例如这意味着什么:

DMessageFactory.getTimeZoneFromTimeZoneDifferential("110")


…所以我能为您做的事不多了。

您的代码似乎正在寻找与其offset-from-UTC(小时-分钟-秒)相匹配的时区以及是否与Daylight Saving Time (DST)相匹配。如上所述,您可以查询此信息的ZoneRules



关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

现在位于Joda-Time中的maintenance mode项目建议迁移到java.time类。

您可以直接与数据库交换java.time对象。使用与JDBC driver或更高版本兼容的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?


Java SE 8Java SE 9Java SE 10Java SE 11和更高版本-具有捆绑实现的标准Java API的一部分。


Java 9添加了一些次要功能和修复。

Java SE 6Java SE 7


大多数java.time功能都被反向移植到ThreeTen-Backport中的Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于较早的Android(<26),ThreeTenABP项目改编为ThreeTen-Backport(如上所述)。请参见How to use ThreeTenABP…



ThreeTen-Extra项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

关于java - 如何使用Java中的新API替换sun.util.calendar.ZoneInfo,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55149139/

相关文章:

api - 通过 Firefox 访问 RESTful API

.net - Web 服务器上禁用 header

javascript - 使用 Team CIty 的 REST API 在构建数组中提取每个构建的更多信息

java - 正确实现乒乓球游戏

java - ActiveMQ 代理如何结束连接?

java - Mockito 和单元测试 - 如何控制新对象的创建

java - JUnit 测试具有多个(不同)参数的预期异常

java - Powermock 框架如何创建模拟对象?

java - 为什么我的 LinkedList 充满了相同的对象?

java - SpringJDBC ClassPathXmlApplicationContext 无法从资源中的 xml 加载 getbean