Java,存储时区对象

Java,存储时区对象,java,timezone,Java,Timezone,我需要存储一个hashmap,key是字符串,val是标准Java时区。 在(1)存储时区的Id字符串和(2)存储对象本身之间,哪种方式可以节省更多内存。直觉上我认为是1,但一个朋友告诉我TimeZone是一个工厂类,所以(2)更有效。你的意见?tks 1: 2: 加载后,每个时区信息都将被缓存(在sun.util.calendar.zoneInfo文件中),因此这并不重要。如果在访问该值之后,您仍然需要TimeZone对象,我将存储TimeZone对象 也就是说,正如评论中提到的,我不确定你是

我需要存储一个hashmap,key是字符串,val是标准Java时区。 在(1)存储时区的Id字符串和(2)存储对象本身之间,哪种方式可以节省更多内存。直觉上我认为是1,但一个朋友告诉我TimeZone是一个工厂类,所以(2)更有效。你的意见?tks

1:

2:


加载后,每个时区信息都将被缓存(在sun.util.calendar.zoneInfo文件中),因此这并不重要。如果在访问该值之后,您仍然需要TimeZone对象,我将存储TimeZone对象

也就是说,正如评论中提到的,我不确定你是否应该对此过于担心。据我所知,你会有24+(比如说50来覆盖x+30分钟类型的偏移量)的条目。时区信息存储在磁盘上的jre/lib/zi下。大多数都在1公里以下。内存中的对象不会太大,所以我们讨论的是50k。除非你的记忆力真的很差,否则这几乎是无关紧要的

最后,所有这些实际上都依赖于一个jre实现,我不确定您是否希望将设计基于此。

tl;博士 你的意见?tks

您所要求的偏移量到分区的映射是毫无意义的。时区在不同的时间点使用不同的偏移量——这就是时区的定义

另外:不需要映射。只要求每个区域的偏移量

ZoneId                       // Represent a time zone.
.of( "Australia/Sydney" )    // Get a time zone by its proper name `Continent/Region`. Never use 2-4 letter pseudo-codes such as `CST`. 
.getRules()                  // Get the past, present, and changes to the offset used by the people of this region (this time zone).
.getOffset(                  // Get the offset in use at a particular moment in this time zone.
    Instant.now()            // Capture the current moment.
)                            // Returns a `ZoneOffset` object.
看这个

+11:00

哎呀!目前,
澳大利亚/悉尼
比UTC提前11小时,而不是您预期的10小时

将偏移量映射到区域不符合逻辑 在任何时区,偏移量都随日期而变化。虽然澳大利亚/悉尼的时区在一个日期可能提前10小时,但在另一个日期可能不会提前10小时。世界各地的政治家都表现出了频繁更改其管辖范围内使用的UTC偏移量的倾向。有时他们在观察的时候一年改变两次。有时,他们出于外交、政治或军事原因而改变它。因此,没有日期背景的区域偏移图毫无意义

您可以使用和
ZoneRules
获取特定时区在任何时刻使用的偏移量,以生成
ZoneOffset

ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
ZoneRules rules = z.getRules() ;
ZoneOffset offset = rules.getOffset( Instant.now() ) ;  // Get the offset currently in use at this moment.
请理解,与UTC的偏移量仅为小时分秒数。时区更重要。时区是特定地区人民使用的偏移量的过去、现在和未来变化的历史

Map
在任何给定时刻,任何数量的时区都可能同时具有相同的偏移量(本初子午线前/后相同的时分秒数)

所以,创建一个地图,在特定时刻,对于每个可能的
ZoneOffset
,我们使用该偏移量收集一组时区(
ZoneId
)。这将是一个集合,其中键为
ZoneOffset
,值为
ZoneId
对象的
set

这称为a,其中键映射到值的集合,而不是单个值。在现代Java中,我们可以通过使用lambda语法来获得多重映射的效果

跑步的时候

在:2020-01-28:00:07:36.146290Z,不同时区使用的偏移量的multimap.toString()

multimap={+14:00=[太平洋/阿皮亚,太平洋/基里蒂马蒂等/GMT-14],+13:45=[太平洋/查塔姆,新西兰查特],+13:00=[南极洲/麦克默多,太平洋/汤加塔普,太平洋/恩德伯里,太平洋/法考福,新西兰,南极洲/南极,太平洋/奥克兰等/GMT-13],+12:00=[Asia/Anadyr,Pacific/Wake,Pacific/Majuro,Pacific/Funafuti,Pacific/Nauru等/GMT-12,Pacific/Fiji,Pacific/Tarawa,Asia/Kamchatka,Kwajalein,Pacific/Wallis,Pacific/Kwajalein],+11:00=[澳大利亚/悉尼、太平洋/埃法特、澳大利亚/LHI、亚洲/马加丹、太平洋/诺福克、南极洲/麦格理、澳大利亚/洛德豪、澳大利亚/维多利亚等/GMT-11、太平洋/布干维尔、澳大利亚/塔斯马尼亚、亚洲/斯雷德纳科利姆斯克、澳大利亚/柯里、太平洋/波恩培、澳大利亚/墨尔本、太平洋/努美阿、澳大利亚/霍巴特、太平洋/波纳佩、太平洋/瓜达尔卡纳尔、澳大利亚]alia/ACT,澳大利亚/堪培拉,澳大利亚/新南威尔士,太平洋/科斯雷,亚洲/萨哈林],+10:30=[澳大利亚/阿德莱德,澳大利亚/南部,澳大利亚/布罗克希尔,澳大利亚/扬科维纳],+10:00=[Pacific/Port_Moresby,Asia/Vladivostok,Pacific/Saipan,Asia/Ust Nera,南极洲/DumontDUrville等/GMT-10,Pacific/Truk,Australia/Lindeman,Pacific/Chuk,Australia/Brisbane,Pacific/Guam,Pacific/Yap,Australia/Queensland],+09:30=[Australia/North,Australia/Darwin],+09:00=[亚洲/平壤、亚洲/雅库茨克、亚洲/东京、亚洲/贾亚普拉、亚洲/帝力、日本、亚洲/坎迪加、太平洋/帕劳等/GMT-9、亚洲/赤塔、韩国、亚洲/首尔],+08:45=[澳大利亚/欧克拉],+08:00=[中国、新加坡、香港、亚洲/台北、亚洲/香港、亚洲/乌兰巴托、亚洲/马尼拉、亚洲/乌戎巴当、亚洲/伊尔库茨克、亚洲/哈尔滨、亚洲/古晋、亚洲/重庆、澳大利亚/珀斯、亚洲/乌兰巴托、亚洲/吉隆坡、亚洲/重庆、亚洲/澳门、亚洲/上海、南极洲/凯西、亚洲/文莱、亚洲/澳门、亚洲/乔巴尔山、澳大利亚/西部、亚洲/新加坡]e、 Etc/GMT-8,亚洲/马卡萨],+07:00=[亚洲/万象,亚洲/胡志明,亚洲/托木斯克,亚洲/金边,亚洲/雅加达,亚洲/霍华德,亚洲/巴诺,亚洲/克拉斯诺亚尔斯克,亚洲/蓬提亚克,亚洲/曼谷,亚洲/西贡,亚洲/新西伯利亚,亚洲/新库兹涅茨克,印度/圣诞节等/GMT-7,南极洲/戴维斯],+06:30=[亚洲/仰光,印度/科科斯,亚洲/仰光],+06:00=[Asia/Dacca、Asia/Thimbu、Asia/Omsk、Asia/Qostanay、Asia/Almaty、Asia/Dhaka、Indian/Chagos、Asia/Kashgar、Asia/Urumqi、南极洲/Vostok、Asia/Bishkek、Asia/Thimphu等/GMT-6]、+05:45=[Asia/Katmandu、Asia/Katmandu]、+05:30=[Asia/加尔各答、Asia/Kolkata、Asia/Colombo]、+05:00]=[亚洲/阿克托贝、亚洲/撒马尔罕、印度/克格伦、亚洲/奥勒、亚洲/阿什哈巴德、亚洲/杜尚别、亚洲/阿克套、亚洲/阿什哈巴德、亚洲/塔什干、南极洲/马森、亚洲/卡拉奇等/GMT-5、亚洲/叶卡捷林
ZoneId                       // Represent a time zone.
.of( "Australia/Sydney" )    // Get a time zone by its proper name `Continent/Region`. Never use 2-4 letter pseudo-codes such as `CST`. 
.getRules()                  // Get the past, present, and changes to the offset used by the people of this region (this time zone).
.getOffset(                  // Get the offset in use at a particular moment in this time zone.
    Instant.now()            // Capture the current moment.
)                            // Returns a `ZoneOffset` object.
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
ZoneRules rules = z.getRules() ;
ZoneOffset offset = rules.getOffset( Instant.now() ) ;  // Get the offset currently in use at this moment.
Map < ZoneOffset, Set < ZoneId > > multimap = new TreeMap <>(); // Use `TreeMap` to keep the keys (the offsets) in ascending order.

Instant instant = Instant.now();
Set < String > zoneNames = ZoneId.getAvailableZoneIds();
for ( String zoneName : zoneNames )
{
    ZoneId zoneId = ZoneId.of( zoneName );
    ZoneOffset offset = zoneId.getRules().getOffset( instant );
    multimap.computeIfAbsent( offset , ( ZoneOffset key ) -> new HashSet <>() ).add( zoneId );  // Or change `HashSet` to `TreeSet` to keep the `ZoneId` objects in sorted order.
}
System.out.println( "multimap.toString() of the offset in use by various time zones at: " + instant );
System.out.println( "multimap = " + multimap );