2017-08-09 12 views
5

मैं इस तरह ZoneId वर्ग के लिए मानों फ्रंट-एंड से आते हैं मैप करने के लिए कोशिश कर रहा हूँ के बारे में जानकारी नहीं है:जावा सभी IANA समय क्षेत्र

Optional.ofNullable(timeZone).map(ZoneId::of).orElse(null) 

सबसे समय क्षेत्रों के लिए यह ठीक काम करता है, हालांकि, कुछ मूल्यों के लिए जावा अपवाद फेंकता है:

java.time.zone.ZoneRulesException: Unknown time-zone ID: America/Punta_Arenas 

हालांकि, यह एक मान्य समय-क्षेत्र की IANA के अनुसार है: https://www.iana.org/time-zones

जोन अमेरिका/Punta_Arenas -4: 43: 40 - LMT 1890

के बारे में मैं ऐसे समय-क्षेत्र (सिर्फ मानों को हार्डकोड करने) के लिए ऑफसेट का उपयोग कर सोच रहा था, लेकिन मुझे लगता है कि करने के लिए अधिक सुविधाजनक तरीका होना चाहिए मुद्दे को हल करें। जावा जावा को संभालने का कोई तरीका है?

अन्य समय क्षेत्र है कि समर्थित नहीं हैं:

  • अमेरिका/Punta_Arenas
  • एशिया/Atyrau
  • एशिया/Famagusta
  • एशिया/यांगून
  • ईएसटी
  • यूरोप/सेराटोव
  • एचएसटी
  • MST
  • आरओसी

मेरे जावा संस्करण: "1.8.0_121" जावा (टीएम) एसई रनटाइम वातावरण (निर्माण 1.8.0_121-B13) जावा हॉटस्पॉट (टीएम) 64-बिट सर्वर वी एम (25.121- निर्माण बी 13, मिश्रित मोड)

+2

जावा का कौन सा संस्करण आप बिल्कुल उपयोग कर रहे हैं; जावा 8 का नवीनतम अपडेट? समय क्षेत्र की जानकारी को नए जावा अपडेट के साथ अक्सर अद्यतन किया जाता है, यह संभव है कि आप एक विशिष्ट जावा संस्करण का उपयोग कर रहे हों जिसमें आप संदर्भित कर रहे हैं। – Jesper

+0

मैंने जावा 8 अपडेट 144 (वर्तमान में नवीनतम संस्करण) के साथ इसे आजमाया और यह अपेक्षा के अनुसार काम करता है। – Jesper

+0

जावा संस्करण "1.8.0_121" जावा (टीएम) एसई रनटाइम पर्यावरण (निर्माण 1.8.0_121-बी 13) जावा हॉटस्पॉट (टीएम) 64-बिट सर्वर वीएम (25.121-बी 13, मिश्रित मोड का निर्माण) – dvelopp

उत्तर

7

मैंने जावा 1.8.0_121 के साथ परीक्षण किया है और कुछ जोन वास्तव में गायब हैं। कि नीचे के बारे में अधिक, 3 अक्षर के नाम (EST, HST, आदि) को छोड़कर - जावा 1.8.0_131 में उपरोक्त सभी क्षेत्र उपलब्ध होते हैं -

इसे ठीक करने के सबसे स्पष्ट रास्ता जावा के संस्करण को अद्यतन करने के लिए है।

लेकिन मुझे पता है कि उत्पादन वातावरण में अपडेट उतना आसान नहीं है जितना हम चाहते हैं। इस मामले में, आप TZUpdater tool का उपयोग कर सकते हैं, जो जावा के संस्करण को बदले बिना जेडीके के टाइमज़ोन डेटा को अपडेट कर सकता है।


केवल विस्तार है कि ZoneId 3 अक्षर का कोड (EST, HST और इसी तरह) के साथ काम नहीं करता है। ऐसा इसलिए है क्योंकि उन नाम ambiguous and not standard हैं।

यदि आप उनका उपयोग करना चाहते हैं, तो भी, आप कस्टम आईडी के मानचित्र का उपयोग कर सकते हैं। ZoneId निर्मित एक नक्शे के साथ आता है:

ZoneId.of("EST", ZoneId.SHORT_IDS); 

समस्या यह है कि choices used in the SHORT_IDS map होते हैं - जैसे किसी भी अन्य विकल्प - मनमाने ढंग से और यहां तक ​​कि विवादास्पद।आप प्रत्येक संक्षिप्त नाम के लिए अलग अलग क्षेत्रों का उपयोग करना चाहते हैं, तो बस अपने स्वयं के नक्शे बनाने के लिए:

Map<String, String> map = new HashMap<>(); 
map.put("EST", "America/New_York"); 
... put how many names you want 
System.out.println(ZoneId.of("EST", map)); // creates America/New_York 

3-पत्र के नाम के लिए केवल अपवाद हैं, ज़ाहिर है, जीएमटी और यूटीसी, लेकिन इस मामले में यह है ZoneOffset.UTC स्थिरता का उपयोग करने के लिए बेहतर है।


यदि आप अपने जावा संस्करण को अपडेट नहीं कर सकते हैं और न ही TZUpdater टूल चला सकते हैं, तो एक और (अधिक कठिन) विकल्प है।

आप java.time.zone.ZoneRulesProvider कक्षा का विस्तार कर सकते हैं और एक प्रदाता बना सकते हैं जो अनुपलब्ध आईडी बना सकता है। कुछ ऐसा:

public class MissingZonesProvider extends ZoneRulesProvider { 

    private Set<String> missingIds = new HashSet<>(); 

    public MissingZonesProvider() { 
     missingIds.add("America/Punta_Arenas"); 
     missingIds.add("Europe/Saratov"); 
     // add all others 
    } 

    @Override 
    protected Set<String> provideZoneIds() { 
     return this.missingIds; 
    } 

    @Override 
    protected ZoneRules provideRules(String zoneId, boolean forCaching) { 
     ZoneRules rules = null; 
     if ("America/Punta_Arenas".equals(zoneId)) { 
      rules = // create rules for America/Punta_Arenas 
     } 
     if ("Europe/Saratov".equals(zoneId)) { 
      rules = // create rules for Europe/Saratov 
     } 
     // and so on 

     return rules; 
    } 

    // returns a map with the ZoneRules, check javadoc for more details 
    @Override 
    protected NavigableMap<String, ZoneRules> provideVersions(String zoneId) { 
     TreeMap<String, ZoneRules> map = new TreeMap<>(); 
     ZoneRules rules = provideRules(zoneId, false); 
     if (rules != null) { 
      map.put(zoneId, rules); 
     } 
     return map; 
    } 
} 

ZoneRules सबसे जटिल हिस्सा बनाएं।

नवीनतम तरीका IANA files प्राप्त करना और उन्हें पढ़ना है। आप JDK source code पर यह देखने के लिए देख सकते हैं कि यह ZoneRules से कैसे बनाता है (हालांकि मुझे यकीन नहीं है कि जेडीके के अंदर की फ़ाइल आईएएनए की फाइलों के समान प्रारूप में है)।

वैसे भी, बताता है कि आईएएनए की फाइलें कैसे पढ़ें। फिर जावा क्लास में आईएएनए जानकारी को मैप करने के तरीके के बारे में जानने के लिए आप ZoneRules javadoc पर एक नज़र डाल सकते हैं। this answer में मैं केवल 2 संक्रमण नियमों के साथ एक बहुत ही सरल ZoneRules बनाता हूं, ताकि आप इसे कैसे करें इसके बारे में एक बुनियादी विचार प्राप्त कर सकें।

ZoneRulesProvider.registerProvider(new MissingZonesProvider()); 

और अब नए क्षेत्रों में उपलब्ध हो जाएगा:

ZoneId.of("America/Punta_Arenas"); 
ZoneId.of("Europe/Saratov"); 
... and any other you added in the MissingZonesProvider class 

वहाँ प्रदाता (पंजीकरण की बजाय) का उपयोग करने के लिए अन्य तरीके हैं, check the javadoc

तो फिर तुम प्रदाता रजिस्टर करने की आवश्यकता अधिक जानकारी के लिए। उसी जावाडोक में ज़ोन नियम प्रदाता को सही तरीके से कार्यान्वित करने के तरीके के बारे में और भी जानकारी है (ऊपर मेरा संस्करण बहुत सरल है और शायद इसमें कुछ विवरण गुम हैं, जैसे provideVersions - इसे प्रदाता के संस्करण को कुंजी के रूप में उपयोग करना चाहिए, न कि जोन आईडी मैं कर रहा हूं, आदि)।

बेशक इस प्रदाता को जावा संस्करण को अपडेट करने के तुरंत बाद इसे छोड़ दिया जाना चाहिए (क्योंकि आपके पास 2 प्रदाता नहीं हैं जो एक ही आईडी के साथ जोन बनाते हैं: यदि नया प्रदाता एक आईडी बनाता है जो पहले से मौजूद है, तो यह एक फेंकता है जब आप इसे पंजीकृत करने का प्रयास करते हैं तो अपवाद)।

संबंधित मुद्दे