1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. The Android Open Source 9 * Project designates this particular file as subject to the "Classpath" 10 * exception as provided by The Android Open Source Project in the LICENSE 11 * file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 */ 23 24 package java.time.zone; 25 26 27 import android.icu.util.TimeZone; 28 29 import com.android.icu.util.ExtendedTimeZone; 30 31 import java.util.Collections; 32 import java.util.HashSet; 33 import java.util.NavigableMap; 34 import java.util.Set; 35 import java.util.TreeMap; 36 import libcore.util.BasicLruCache; 37 38 /** 39 * A ZoneRulesProvider that generates rules from ICU4J TimeZones. 40 * This provider ensures that classes in {@link java.time} use the same time zone information 41 * as ICU4J. 42 */ 43 public class IcuZoneRulesProvider extends ZoneRulesProvider { 44 45 private final BasicLruCache<String, ZoneRules> cache = new ZoneRulesCache(8); 46 47 @Override provideZoneIds()48 protected Set<String> provideZoneIds() { 49 Set<String> zoneIds = TimeZone.getAvailableIDs(TimeZone.SystemTimeZoneType.ANY, null, null); 50 zoneIds = new HashSet<>(zoneIds); 51 // java.time assumes ZoneId that start with "GMT" fit the pattern "GMT+HH:mm:ss" which these 52 // do not. Since they are equivalent to GMT, just remove these aliases. 53 zoneIds.remove("GMT+0"); 54 zoneIds.remove("GMT-0"); 55 return zoneIds; 56 } 57 58 @Override provideRules(String zoneId, boolean forCaching)59 protected ZoneRules provideRules(String zoneId, boolean forCaching) { 60 // Ignore forCaching, as this is a static provider. 61 return cache.get(zoneId); 62 } 63 64 @Override provideVersions(String zoneId)65 protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) { 66 return new TreeMap<>( 67 Collections.singletonMap(TimeZone.getTZDataVersion(), 68 provideRules(zoneId, /* forCaching */ false))); 69 } 70 generateZoneRules(String zoneId)71 static ZoneRules generateZoneRules(String zoneId) { 72 return ExtendedTimeZone.getInstance(zoneId).createZoneRules(); 73 } 74 75 private static class ZoneRulesCache extends BasicLruCache<String, ZoneRules> { 76 ZoneRulesCache(int maxSize)77 ZoneRulesCache(int maxSize) { 78 super(maxSize); 79 } 80 81 @Override create(String zoneId)82 protected ZoneRules create(String zoneId) { 83 String canonicalId = TimeZone.getCanonicalID(zoneId); 84 if (!canonicalId.equals(zoneId)) { 85 // Return the same object as the canonical one, to avoid wasting space, but cache 86 // it under the non-cannonical name as well, to avoid future getCanonicalID calls. 87 return get(canonicalId); 88 } 89 return generateZoneRules(zoneId); 90 } 91 } 92 } 93