2011-12-22 8 views
12

मैं जेएसएफ 2.0 में एक वेबपैप लिख रहा हूं जो उपयोगकर्ता को जानकारी के हिस्से के रूप में टाइमस्टैम्प प्रदर्शित करता है। मैं उपयोगकर्ता को अपने स्थान (ब्राउज़र के लोकेल) में स्थानीयकृत टाइमस्टैम्प देखना चाहता हूं।जेएसएफ में - क्लाइंट का लोकेल प्राप्त करना (ब्राउज़र के टाइमज़ोन में समय प्रदर्शित करने के लिए)

अभी तक, मैंने जो कुछ भी किया है, टाइमस्टैम्प हमेशा सर्वर के टाइमज़ोन में स्थानांतरित दिखाई देंगे।

Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); 

या

Locale browserLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale(); 

दोनों सर्वर किसी भी स्थान लौटे:

मैं इन तरीकों के साथ स्थान प्राप्त करने की कोशिश की।

मैं टाइमस्टैम्प प्रिंट करने के लिए SimpleDateFormat के साथ लोकेल ऑब्जेक्ट का उपयोग करता हूं।

क्या मैं सही एपीआई का उपयोग कर रहा हूं?
मैंने कहीं पढ़ा है कि आपको ब्राउज़र का टाइमज़ोन प्राप्त करने के लिए क्लाइंट साइड कोड (जावास्क्रिप्ट) का उपयोग करना होगा। क्या वो सही है? आप वह कैसे करेंगें?

धन्यवाद 'एन' अग्रिम।

अद्यतनthis (jsTimezoneDetect) जावास्क्रिप्ट कोड मिला। लेकिन मुझे अभी भी यकीन नहीं है कि टाइमज़ोन को जावा Locale ऑब्जेक्ट

उत्तर

27

आपको शायद SimpleDateFormat के बजाय अंतर्निहित स्वरूपण टैग का उपयोग करना चाहिए। आपके प्रश्न का तात्पर्य है कि आप अंतर्राष्ट्रीय उपयोगकर्ता को दिनांक और समय दिखाना चाहते हैं, और इस मामले में आपको वास्तव में उपयोगकर्ता के स्थानीय प्रारूप का उपयोग करना चाहिए (वे अलग-अलग होते हैं, आपको पता है)।

समय क्षेत्र के मामले में, इसका अंतर्राष्ट्रीयकरण और स्थानीयकरण के साथ कुछ लेना देना नहीं है, यानी यूएसए में कई अलग-अलग समय क्षेत्र हैं। यहां दो दृष्टिकोण हैं जिनका आप यहां उपयोग कर सकते हैं:

  1. उपयोगकर्ता प्रोफ़ाइल में समय क्षेत्र जानकारी स्टोर करें (यदि आपके पास कोई है)। यह सबसे आसान तरीका है और आपको अंतर्निहित <f:convertDateTime> टैग का उपयोग करने की अनुमति देता है।

  2. वेब ब्राउज़र से समय क्षेत्र जानकारी प्राप्त करें। आप इसे बेन के उदाहरण की तरह अजाक्स अनुरोध के माध्यम से प्राप्त कर सकते हैं। तकनीकी रूप से आप यहां <f:convertDateTime> टैग का भी उपयोग कर सकते हैं।

  3. आप यूटीसी में कुछ सामान्य, लोकेल-स्वतंत्र (या यदि आप चाहें तो परिवर्तनीय) प्रारूप में टाइमस्टैम्प भेज सकते हैं, तो इसे Globalize के साथ लोकेल के लिए जावास्क्रिप्ट की दिनांक वस्तु और प्रारूप बनाने के लिए क्लाइंट पक्ष पर पार्स करें।

कुछ उदाहरणों का पालन करेंगे लेकिन मुझे पहले कुछ समझाने दें।

Locale browserLocale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); 

यह आप (नहीं, बल्कि समय क्षेत्र के बाद से इस संबंधित नहीं स्थान है) वेब ब्राउज़र किसी भी स्थान दे देंगे। यह वास्तव में HTTP स्वीकृति-भाषा शीर्षलेख की सामग्री को पढ़ेगा और सर्वोत्तम संभव लोकेल चुनें। यदि यह आपके लिए काम नहीं कर रहा है, तो कृपया सुनिश्चित करें कि आपने अपने faces-config.xml में समर्थित लोकेशन सही ढंग से सेट किए हैं। सबसे अच्छा संभव लोकेल द्वारा, मैं समझता हूं कि यह उपयोगकर्ता के सबसे पसंदीदा लोकेल (यदि यह आपके एप्लिकेशन द्वारा समर्थित है) का उपयोग करने का प्रयास करेगा, तो दूसरा सबसे अच्छा और इसी तरह। यदि लोकेल में से कोई भी समर्थित नहीं है, तो यह आपके एप्लिकेशन के डिफ़ॉल्ट लोकेल में वापस आ जाएगा (फिर, faces-config.xml में यह सेटिंग होनी चाहिए) या सर्वर की डिफ़ॉल्ट लोकेल में यदि यह सेटिंग गुम है (या कम से कम मुझे ऐसा लगता है, तो यह बनाता है समझ)।

Locale browserLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale(); 

यह एक आप स्वीकार करें-भाषा हैडर से शीर्ष लोकेल दे देंगे। कृपया अपने वेब ब्राउजर की सेटिंग्स की जांच करें - लगभग कोई रास्ता नहीं है इसके लिए आपको सर्वर लोकेल देने के लिए, जब तक वे आपके वेब ब्राउज़र के समान नहीं होते हैं।यह आपको सर्वर के डिफ़ॉल्ट दे सकता है अगर और केवल तभी, वेब ब्राउज़र का कोई भी लोकेल JVM द्वारा समर्थित नहीं है (जो थोड़ा असंभव प्रतीत होता है)।

बीटीडब्ल्यू। FacesContext.getCurrentInstance().getExternalContext().getRequestLocales() आपको इटरेटर देगा ताकि आप स्वीकार्य-भाषा शीर्षलेख में लोकेल की सूची के माध्यम से मैन्युअल रूप से पुन: प्रयास कर सकें। यह सिर्फ आपको बताने के लिए है, आपको शायद इसका उपयोग नहीं करना चाहिए (UIViewRoot वास्तव में पर्याप्त है)।

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

<h:outputText value="#{someBean.timestamp}"> 
    <f:convertDateTime type="both" dateStyle="default" timeStyle="default" timeZone="#{userProfile.timeZone}" /> 
</h:outputtext> 

अब मुझे विशेषताओं की व्याख्या करते हैं:

  • प्रकार - क्या दिखाने के लिए , दोनों का अर्थ दिनांक और समय
  • दिनांक स्टाइल - तिथि की शैली (लघु, मध्यम, लंबी, पूर्ण, डिफ़ॉल्ट से बाहर)। आपको वास्तव में डिफ़ॉल्ट रूप से डिफ़ॉल्ट रूप से उपयोग करना चाहिए क्योंकि यह प्रत्येक लोकेल
  • टाइम स्टाइल - दिनांक शैली के समान है लेकिन समय के लिए
  • टाइमज़ोन - या तो यूटीसी ऑफसेट लेता है (इसलिए आपको कुछ भी बदलने की आवश्यकता नहीं है) या समय क्षेत्र का नाम (यानी अमेरिका/लॉस_एंजेलस)।

टैग वर्तमान दृश्य लोकेल का डिफ़ॉल्ट रूप से उपयोग करेगा, इसलिए आपको इस भाग के बारे में चिंता करने की ज़रूरत नहीं है, खासकर यदि आप लोकेल समर्थन को सही तरीके से सेट अप करते हैं।

अजाक्स के साथ संयोजन (बेन का जवाब देखें) काफी आसान होगा (मुझे लगता है)।

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

// you also have to assign the culture based on UIViewRoot locale and send it out with JavaScript 
Globalize.culture(theLocale); 
var formattedDateTime = Globalize.format(parsedDateTime, "f"); // this will use short date time format 

जावा के विपरीत, वैश्वीकृत केवल कम है ("च ") और लंबी (" एफ ") तिथि और समय प्रारूप। तो मैंने छोटे का उपयोग करने का फैसला किया।
कृपया ध्यान रखें, कि वैश्वीकरण संस्कृतियों को हाइफ़न के माध्यम से अलग किया जाता है, अंडरस्कोर नहीं, इसलिए आपको "fr-CA" की आवश्यकता होती है, उदाहरण के लिए "fr_CA" नहीं।
कृपया मुझे बताएं कि क्या आप उस विधि का उपयोग करना चाहते हैं और अधिक ठोस उदाहरण की आवश्यकता है।

+0

धन्यवाद! महान, पूरी तरह से जवाब। (बीटीडब्ल्यू - ध्यान दें कि मैं बेन हूं, लेकिन आपका उत्तर निश्चित रूप से वी :-) का हकदार है) – Ben

+0

पहले उदाहरण में आपने लिखा था: "यदि यह आपके लिए काम नहीं कर रहा है, तो कृपया सुनिश्चित करें कि आपने सही ढंग से समर्थित लोकेशंस सेट किए हैं सामना कर रहा है-config.xml "। मुझे यकीन नहीं है कि उस समय कैसा था, लेकिन मैंने अभी जेएसएफ 2.2 के साथ परीक्षण किया है और चेहरे-config.xml की कोई आवश्यकता नहीं है यदि आप FacesContext का उपयोग करके लोकेशंस सेट अप करते हैं। Faces-config.xml का उपयोग ब्राउज़र को लोकेल चुनने के लिए किया जाता है। – karlihnos

2

क्लाइंट पक्ष पर टाइमज़ोन का पता लगाने और सर्वर को भेजने के लिए jsTimezoneDetect को आजमा सकते हैं।

अद्यतन: एक उपयोगकर्ता किसी भी स्थान प्राप्त करने के लिए, आप निम्न की कोशिश कर सकते हैं:

HttpServletRequest request = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest(); 
Locale locale = request.getLocale(); 

रिटर्न का संकेत लोकेल वस्तुओं का एक गणन घटते क्रम पसंदीदा स्थान के साथ शुरू में, स्थानों है कि स्वीकार्य-भाषा शीर्षलेख के आधार पर ग्राहक को स्वीकार्य हैं। यदि क्लाइंट अनुरोध एक स्वीकार्य-भाषा शीर्षलेख प्रदान नहीं करता है, तो यह विधि एक लोकेल युक्त एक गणना देता है, जो सर्वर के लिए डिफ़ॉल्ट लोकेल है।

+0

धन्यवाद, मुझे वास्तव में पहले से ही यह स्क्रिप्ट मिली है (यह अद्यतन में लिंक है)। मुझे यकीन नहीं है कि मैं इसे जावा लोकेल ऑब्जेक्ट में कैसे अनुवादित करता हूं। – Ben

0

आप सभी की जरूरत उन स्थानीय समय आप न लोकेल वस्तु की जरूरत के साथ समय टिकटों प्रदर्शित करने के लिए है, तो Y (आप उन घंटे GMT + 0-समय पर भरपाई जोड़ने की जरूरत है) आप मूल्य भेजने की जरूरत है timezone.offset() (लिंक में उदाहरण से) सर्वर पर (आप इसे पैरामीटर के साथ सर्वलेट पोस्ट का उपयोग करके कर सकते हैं)

और फिर इस ऑफ़सेट को अपने सर्वर पर बनाए गए दिनांक ऑब्जेक्ट में जोड़ें (अपना लोकेल सेट करें सर्वर पर जीएमटी + 00)

इस तरह आप अपने वेब ऐप में लॉग इन किए गए उपयोगकर्ता के सही समय के साथ टाइम टिकटें बनाएंगे

(यही वह है जो मैंने खुद किया ...)

7

सफल हुआ। यहाँ मैं क्या किया है:

जोड़ा गया JSF करने के लिए एक छिपी हुई इनपुट फ़ील्ड तो मैं सर्वर से JavaScript मानों भेज सकते हैं:

<h:form prependId="false"> 
    <h:inputText id="timezone_holder" value="#{bean.timezone}" styleClass="hide"> 
     <f:ajax listener="#{bean.timezoneChangedListener}"></f:ajax> 
    </h:inputText> 
</h:form> 

ऊपर प्लगइन का उपयोग करना, मैं JavaScript कोड की भरपाई को लिया गया भागा ब्राउज़र।

$(document).ready(function() { 
    var timezone = jstz.determine_timezone(); 

    $("#timezone_holder").val(timezone.offset()); 
    $("#timezone_holder").change(); 
}); 

जब समय क्षेत्र इनपुट बदल गया है (ऊपर जावास्क्रिप्ट कोड से शुरू) मैं eventListener में इस कोड को चलाएँ: जब भी मैं एक तारीख मैं दिनांक फ़ॉर्मेटर का उपयोग प्रारूप में तैयार करना, फिर

String strFromJavaScript = getTimezone(); 
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext() 
       .getRequest(); 
Locale browserLocale = request.getLocale(); 
TimeZone tz = TimeZone.getTimeZone("GMT" + strFromJavaScript); 

// set time zone 
SimpleDateFormat formatter = new SimpleDateFormat("MMM d, yyyy, HH:mm", browserLocale); 
formatter.setTimeZone(tz); 

जो ऊपर बनाया गया था।

+1

[बाहरी कॉन्टेक्स्ट] के रूप में 'HTTPServletRequest' को डालने की कोई आवश्यकता नहीं है (http://myfaces.apache.org/core11/myfaces-api/apidocs/javax/faces/context/ExternalContext.html) पहले से ही उपयुक्त विधियां प्रदान करता है (वे वही काम करता है)। आपके उत्तर में एक और मुद्दा जो मैं देखता हूं वह है *** हार्डकोडेड दिनांक प्रारूप *** जो इसे [स्थानीयकरण] (http://stackoverflow.com/questions/tagged/localization) टैग के लिए थोड़ा अनुपयुक्त बनाता है। इसके अलावा, महान काम :) –

+0

@ PawełDyda टिप्पणियों के लिए धन्यवाद। विधिवत् नोट किया हुआ। – Ben

+0

क्या आपका बीन सत्र स्कॉप्ड है? क्या होता है यदि पृष्ठ पर पहला अनुरोध किया गया है जिसमें क्लाइंट टाइमज़ोन का उपयोग करके आप प्रारूप बनाना चाहते हैं? यह दूसरे अनुरोध तक उपलब्ध नहीं होगा, है ना? – Ghasfarost

0

तुम भी JSF कोड में यह प्रत्यक्ष की तरह उपयोग कर सकते हैं:

<script type="text/javascript"> 
     $(document).ready(function() { 
      var timezone = jstz.determine_timezone(); 
      $("#timezone_holder").val(timezone.name()); //use TimeZone name instead of offset 
      $("#timezone_holder").change(); 
     }); 
</script> 

तो फिर तुम एक JSF कनवर्टर में timezonename का पुन: उपयोग कर सकते हैं:

<f:convertDateTime pattern="dd.MM.yyyy HH:mm" timeZone="#{bean.timezone}" /> 
1

एक अन्य विकल्प पर एक कुकी बनाना होगा एक जावास्क्रिप्ट जो निष्पादित करता है जब होम पेज तैयार होता है।उसके बाद, कुकी प्रत्येक अनुवर्ती अनुरोध पर उपलब्ध नहीं होगा और होगा उपलब्ध

आपका जावास्क्रिप्ट jQuery का उपयोग करें और सकता है jsTimezoneDetect

$(document).ready(function() { 
     setTimezoneCookie(); 
    }); 

    function setTimezoneCookie() { 

     var timezone = jstz.determine().name(); 

     if (null == getCookie("timezoneCookie")) { 
     document.cookie = "timezoneCookie=" + timezone; 
     } 
    } 

    function getCookie(cookieName) { 
     var cookieValue = document.cookie; 
     var cookieStart = cookieValue.indexOf(" " + cookieName + "="); 
     if (cookieStart == -1) { 
      cookieStart = cookieValue.indexOf(cookieName + "="); 
     } 
     if (cookieStart == -1) { 
      cookieValue = null; 
     } else { 
      cookieStart = cookieValue.indexOf("=", cookieStart) + 1; 
      var cookieEnd = cookieValue.indexOf(";", cookieStart); 
      if (cookieEnd == -1) { 
       cookieEnd = cookieValue.length; 
      } 
      cookieValue = unescape(cookieValue.substring(cookieStart, cookieEnd)); 
     } 
     return cookieValue; 
    } 

आपका Facelet तो कुकी के मूल्य का प्रयोग करेंगे यदि वह मौजूद है:

<h:outputText value="#{bean.time}"> 
    <f:convertDateTime 
     dateStyle="full" 
     timeStyle="full" 
     type="both" 
     timeZone="#{cookie.timezoneCookie.value}"> 
    </f:convertDateTime> 
</h:outputText> 
+0

अच्छा है कि हमें किसी भी जावा पुनर्संरचना की आवश्यकता नहीं है –

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