java - इन दो बार(1 9 27 में)क्यों अजीब परिणाम दे रहा है?





date timezone (8)


जैसा कि दूसरों द्वारा समझाया गया है, वहां एक समय विघटन होता है। Asia/Shanghai 1927-12-31 23:54:08 लिए दो संभावित 1927-12-31 23:54:08 ऑफ़सेट हैं, लेकिन 1 1927-12-31 23:54:07 लिए केवल एक ऑफसेट है। तो, किस ऑफसेट का उपयोग किया जाता है, इस पर निर्भर करता है कि या तो एक दूसरा अंतर या 5 मिनट और 53 सेकंड का अंतर होता है।

सामान्य एक घंटे की डेलाइट बचत (ग्रीष्मकालीन समय) के बजाय ऑफ़सेट की यह मामूली बदलाव, हम समस्या का थोड़ा सा अस्पष्ट उपयोग करते हैं।

ध्यान दें कि टाइमज़ोन डेटाबेस के 2013a अद्यतन ने कुछ सेकंड पहले इस विघटन को स्थानांतरित कर दिया था, लेकिन प्रभाव अभी भी देखा जा सकता है।

जावा 8 पर नया java.time पैकेज इसे और अधिक स्पष्ट रूप से देखने दें, और इसे संभालने के लिए टूल प्रदान करें। दिया हुआ:

DateTimeFormatterBuilder dtfb = new DateTimeFormatterBuilder();
dtfb.append(DateTimeFormatter.ISO_LOCAL_DATE);
dtfb.appendLiteral(' ');
dtfb.append(DateTimeFormatter.ISO_LOCAL_TIME);
DateTimeFormatter dtf = dtfb.toFormatter();
ZoneId shanghai = ZoneId.of("Asia/Shanghai");

String str3 = "1927-12-31 23:54:07";  
String str4 = "1927-12-31 23:54:08";  

ZonedDateTime zdt3 = LocalDateTime.parse(str3, dtf).atZone(shanghai);
ZonedDateTime zdt4 = LocalDateTime.parse(str4, dtf).atZone(shanghai);

Duration durationAtEarlierOffset = Duration.between(zdt3.withEarlierOffsetAtOverlap(), zdt4.withEarlierOffsetAtOverlap());

Duration durationAtLaterOffset = Duration.between(zdt3.withLaterOffsetAtOverlap(), zdt4.withLaterOffsetAtOverlap());

फिर durationAtEarlierOffset एक सेकंड होगी, जबकि durationAtLaterOffset पांच मिनट और 53 सेकंड होगा।

इसके अलावा, ये दो ऑफसेट समान हैं:

// Both have offsets +08:05:52
ZoneOffset zo3Earlier = zdt3.withEarlierOffsetAtOverlap().getOffset();
ZoneOffset zo3Later = zdt3.withLaterOffsetAtOverlap().getOffset();

लेकिन ये दोनों अलग हैं:

// +08:05:52
ZoneOffset zo4Earlier = zdt4.withEarlierOffsetAtOverlap().getOffset();

// +08:00
ZoneOffset zo4Later = zdt4.withLaterOffsetAtOverlap().getOffset();

आप 1 1927-12-31 23:59:59 तुलना में 1 1927-12-31 23:59:59 तुलना में एक ही समस्या देख सकते हैं, हालांकि, इस मामले में, यह पहले ऑफसेट है जो लंबे विचलन का उत्पादन करता है, और यह है पहले की तारीख जिसमें दो संभावित ऑफसेट हैं।

इस तक पहुंचने का एक और तरीका यह जांचना है कि कोई संक्रमण चल रहा है या नहीं। हम ऐसा कर सकते हैं:

// Null
ZoneOffsetTransition zot3 = shanghai.getRules().getTransition(ld3.toLocalDateTime);

// An overlap transition
ZoneOffsetTransition zot4 = shanghai.getRules().getTransition(ld3.toLocalDateTime);

आप जांच सकते हैं कि संक्रमण एक ओवरलैप है - इस मामले में उस दिनांक / समय के लिए एक से अधिक वैध ऑफसेट हैं - या एक अंतर - जिस स्थिति में दिनांक / समय उस क्षेत्र आईडी के लिए मान्य नहीं है - isOverlap() का उपयोग करके और isGap() पर isGap() विधियों।

मुझे उम्मीद है कि जावा 8 व्यापक रूप से उपलब्ध होने के बाद या जेएसआर 310 बैकपोर्ट को अपनाने वाले जावा 7 का उपयोग करने वाले लोगों के लिए इस तरह के मुद्दे को संभालने में लोगों की मदद करता है।

यदि मैं निम्न प्रोग्राम चलाता हूं, जो दो दिनांक तारों को संदर्भित करता है तो 1 सेकंड अलग-अलग संदर्भ देता है और उनकी तुलना करता है:

public static void main(String[] args) throws ParseException {
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String str3 = "1927-12-31 23:54:07";  
    String str4 = "1927-12-31 23:54:08";  
    Date sDt3 = sf.parse(str3);  
    Date sDt4 = sf.parse(str4);  
    long ld3 = sDt3.getTime() /1000;  
    long ld4 = sDt4.getTime() /1000;
    System.out.println(ld4-ld3);
}

आउटपुट है:

353

ld4-ld3 1 क्यों नहीं है (जैसा कि मैं समय में एक-दूसरे अंतर से अपेक्षा करता हूं), लेकिन 353 ?

यदि मैं दिनांक 1 बार बाद में बदलता हूं:

String str3 = "1927-12-31 23:54:08";  
String str4 = "1927-12-31 23:54:09";  

फिर ld4-ld3 1 होगा।

जावा संस्करण:

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)

Timezone(`TimeZone.getDefault()`):

sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]

Locale(Locale.getDefault()): zh_CN



प्रत्येक तिथि को बदलने के बजाय, आप निम्न कोड का उपयोग करते हैं

long difference = (sDt4.getTime() - sDt3.getTime()) / 1000;
System.out.println(difference);

और परिणाम देखें:

1



मुझे यह कहने में खेद है कि, लेकिन समय असंतुलन थोड़ा सा हो गया है

दो साल पहले जेडीके 6 , और हाल ही में अपडेट 25 में जेडीके 7 में।

सीखने के लिए सबक: प्रदर्शन के लिए, शायद, बिना किसी लागत के गैर-यूटीसी समय से बचें।




आपको स्थानीय समय की असंतोष का सामना करना पड़ा है:

जब स्थानीय मानक समय रविवार तक पहुंचने वाला था, 1. जनवरी 1 9 28, 00:00:00 घड़ियां पिछली बार 0:05:52 घंटे शनिवार, 31. दिसंबर 1 9 27, 23:54:08 स्थानीय मानक समय के बजाय

यह विशेष रूप से अजीब नहीं है और राजनीतिक या प्रशासनिक कार्यों के कारण समय-समय पर स्विच या बदल दिया गया है, क्योंकि एक समय या दूसरे में कहीं भी काफी कुछ हुआ है।




समय बढ़ने पर आपको यूटीसी में वापस परिवर्तित करना चाहिए और फिर जोड़ना या घटाना चाहिए। केवल प्रदर्शन के लिए स्थानीय समय का उपयोग करें।

इस तरह आप किसी भी अवधि के दौरान चलने में सक्षम होंगे जहां घंटों या मिनट दो बार होते हैं।

यदि आप यूटीसी में परिवर्तित हो जाते हैं, तो प्रत्येक सेकेंड जोड़ें, और डिस्प्ले के लिए स्थानीय समय में कनवर्ट करें। आप 11:54:08 बजे एलएमटी - 11:59:59 बजे एलएमटी और फिर 11:54:08 बजे CST - 11:59:59 बजे CST माध्यम से जाएंगे।




इस अजीबता का नैतिक है:

  • जहां भी संभव हो यूटीसी में तिथियां और समय का प्रयोग करें।
  • यदि आप यूटीसी में दिनांक या समय प्रदर्शित नहीं कर सकते हैं, तो हमेशा समय-क्षेत्र इंगित करें।
  • यदि आपको यूटीसी में इनपुट दिनांक / समय की आवश्यकता नहीं है, तो स्पष्ट रूप से संकेतित समय-क्षेत्र की आवश्यकता होती है।



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

  • निर्यात एलसी_ALL = सी टीजेड = यूटीसी
  • यूटीसी को अपनी सिस्टम घड़ी सेट करें
  • स्थानीयकृत कार्यान्वयन का कभी भी उपयोग न करें जब तक कि बिल्कुल जरूरी न हो (यानी केवल प्रदर्शन के लिए)

जावा सामुदायिक प्रक्रिया सदस्यों के लिए मैं अनुशंसा करता हूं:

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

मेरा मतलब है, चलो, वैश्विक स्थैतिक चर विरोधी एंटी-ओओ पैटर्न नहीं हैं? कुछ प्राथमिक पर्यावरण चर द्वारा दिए गए उन व्यापक दोषों को और कुछ नहीं .......




यदि आपकी कक्षा में @XmlRootElement एनोटेशन नहीं है तो आप इसे JAXBElement उदाहरण में लपेट सकते हैं। यदि आपने अपनी कक्षाओं को एक्सएमएल स्कीमा से जेनरेट किया है तो जेनरेट ObjectFactory आपके लिए सुविधा विधि हो सकती है।

मैंने अपने ब्लॉग पर इस उपयोग के मामले के बारे में और अधिक लिखा है:







java date timezone