2012-10-24 17 views
14

मैं किसी एप्लिकेशन में नोडाटाइम का उपयोग कर रहा हूं, और मुझे उपयोगकर्ता को ड्रॉपडाउन सूची से अपना टाइमज़ोन चुनने की आवश्यकता है। मेरे पास निम्नलिखित मुलायम आवश्यकताएं हैं:मुझे नोडा टाइम से आईएएनए/ओल्सन समय क्षेत्र की सूची कैसे पॉप्युलेट करनी चाहिए?

1) सूची में केवल वे विकल्प होते हैं जो वास्तविक स्थानों के लिए वर्तमान और निकट भविष्य के लिए उचित रूप से मान्य हैं। ऐतिहासिक, अस्पष्ट, और सामान्य समय क्षेत्र को फ़िल्टर किया जाना चाहिए।

2) सूची को पहले यूटीसी ऑफसेट द्वारा क्रमबद्ध किया जाना चाहिए, और फिर टाइमज़ोन नाम से। यह उम्मीद है कि उन्हें एक क्रम में रखता है जो उपयोगकर्ता के लिए सार्थक है।

मैंने निम्नलिखित कोड लिखा है, जो वास्तव में काम करता है, लेकिन मेरे पास ठीक वही नहीं है जो मैं कर रहा हूं। फ़िल्टर को शायद समायोजित करने की आवश्यकता है, और मैं ऑफसेट को वर्तमान ऑफसेट की बजाय आधार (गैर-डीएसटी) ऑफसेट का प्रतिनिधित्व करना चाहता हूं।

सुझाव? सिफारिशें?

var now = Instant.FromDateTimeUtc(DateTime.UtcNow); 
var tzdb = DateTimeZoneProviders.Tzdb; 
var list = from id in tzdb.Ids 
      where id.Contains("/") && !id.StartsWith("etc", StringComparison.OrdinalIgnoreCase) 
      let tz = tzdb[id] 
      let offset = tz.GetOffsetFromUtc(now) 
      orderby offset, id 
      select new 
      { 
       Id = id, 
       DisplayValue = string.Format("({0}) {1}", offset.ToString("+HH:mm", null), id) 
      }; 

// ultimately we build a dropdown list, but for demo purposes you can just dump the results 
foreach (var item in list) 
    Console.WriteLine(item.DisplayValue); 

उत्तर

26

Noda समय 1.1 the zone.tab data है, इसलिए अब आप निम्न कर सकते हैं:

/// <summary> 
/// Returns a list of valid timezones as a dictionary, where the key is 
/// the timezone id, and the value can be used for display. 
/// </summary> 
/// <param name="countryCode"> 
/// The two-letter country code to get timezones for. 
/// Returns all timezones if null or empty. 
/// </param> 
public IDictionary<string, string> GetTimeZones(string countryCode) 
{ 
    var now = SystemClock.Instance.Now; 
    var tzdb = DateTimeZoneProviders.Tzdb; 

    var list = 
     from location in TzdbDateTimeZoneSource.Default.ZoneLocations 
     where string.IsNullOrEmpty(countryCode) || 
       location.CountryCode.Equals(countryCode, 
              StringComparison.OrdinalIgnoreCase) 
     let zoneId = location.ZoneId 
     let tz = tzdb[zoneId] 
     let offset = tz.GetZoneInterval(now).StandardOffset 
     orderby offset, zoneId 
     select new 
     { 
      Id = zoneId, 
      DisplayValue = string.Format("({0:+HH:mm}) {1}", offset, zoneId) 
     }; 

    return list.ToDictionary(x => x.Id, x => x.DisplayValue); 
} 

वैकल्पिक दृष्टिकोण

के बजाय नीचे सब पर एक बूंद को उपलब्ध कराने के लिए, आप एक map-based timezone picker उपयोग कर सकते हैं।

enter image description here

3

मानक ऑफसेट प्राप्त करना आसान है - tz.GetZoneInterval(now).StandardOffset। इससे आपको "वर्तमान" मानक ऑफ़सेट मिलेगा (ज़ोन के समय के साथ बदलना संभव है)।

फ़िल्टरिंग आपके लिए उपयुक्त हो सकता है - मैं निश्चित रूप से कहना नहीं चाहूंगा। यह निश्चित रूप से आदर्श नहीं है कि आईडी वास्तव में प्रदर्शन के लिए डिज़ाइन नहीं किए गए हैं। आदर्श रूप में आप यूनिकोड सीएलडीआर "उदाहरण" स्थानों का उपयोग करेंगे, लेकिन इस समय हमारे सामने उस सीएलडीआर एकीकरण नहीं है।

+0

वहाँ ऐतिहासिक समय-क्षेत्रों को फ़िल्टर करने के कुछ साफ रास्ता नहीं है? TZ डेटाबेस में से और तारीखें हैं जो टाइमज़ोन मान्य हैं। क्या नोडा किसी भी तरह से इसका खुलासा करता है? –

+0

@ मैट जॉनसन: नहीं - टीजेडीबीबी का कौन सा हिस्सा उसको उजागर करता है? मुझे कबूल करना चाहिए कि मैंने कभी प्रारूप को पूरी तरह से समझ नहीं लिया है, लेकिन अगर ऐसा कुछ है जिसे हम जोड़ सकते हैं, तो हम ऐसा कर सकते हैं (हालांकि शायद 1.0 के लिए नहीं)। (आमतौर पर समय क्षेत्र के भीतर विशेष नियमों के लिए होते हैं, और मैंने सोचा कि अंतिम नियम हमेशा "अधिकतम" था।) –

+0

मैंने इस पृष्ठ पर ठोकर खाई http://69.36.11.139/tzdb/tz-how- to.html जो चीजों को काफी अच्छी तरह से समझाता है। प्रतीत होता है कि नियम प्रविष्टियों में मुझे आवश्यक डेटा होना प्रतीत होता है। –