2017-12-14 132 views
5

कोई बता सकता है कि ऐसा क्यों है? उस समय के लिए 24 मिनट का ऑफसेट क्यों है और इससे निपटने का तरीका क्यों है?java.sql.Timestamp गलत समय पार्सिंग

स्काला 2.12 और जावा 8.

scala> java.sql.Timestamp.valueOf("1900-01-01 00:59:00") 
res22: java.sql.Timestamp = 1900-01-01 00:59:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:00:00") 
res23: java.sql.Timestamp = 1900-01-01 01:24:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:14:00") 
res24: java.sql.Timestamp = 1900-01-01 01:38:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:20:00") 
res25: java.sql.Timestamp = 1900-01-01 01:44:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:23:00") 
res26: java.sql.Timestamp = 1900-01-01 01:47:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:24:00") 
res27: java.sql.Timestamp = 1900-01-01 01:24:00.0 

scala> java.sql.Timestamp.valueOf("1900-01-01 01:30:00") 
res28: java.sql.Timestamp = 1900-01-01 01:30:00.0 
+0

आपका लोकेल क्या है? केवल जावा 8 के माध्यम से जा रहा है, कोई स्कैला नहीं, मैं इसे अपने लोकेल (en_US) में पुन: उत्पन्न नहीं कर सकता। – rgettman

+1

@rgettman 'zoneId.systemDefault' रिटर्न 'यूरोप/वारसॉ' –

+0

मैंने इस समस्या को' System.setProperty (" user.timezone "," यूरोप/वारसॉ ") के साथ पुन: उत्पन्न किया;' ... मुझे एक बग की तरह दिखता है, और ... अतीत में टाइमज़ोन कीड़े रहे हैं। लाइब्रेरी कोड के माध्यम से कदम यह ऐसा लगता है कि उस अवधि के लिए जोनिनोफ़ डेटाबेस में एक फर्जी संक्रमण हो सकता है। यह सत्यापित करने के लिए कुछ काम करेगा, और मेरे पास अभी समय नहीं है, दुर्भाग्यवश। –

उत्तर

4

IANA समय क्षेत्र डेटाबेस में समय क्षेत्र परिभाषा में देखो:

# Zone NAME   GMTOFF RULES FORMAT [UNTIL] 
Zone Europe/Warsaw 1:24:00 -  LMT  1880 
         1:24:00 -  WMT  1915 Aug 5 # Warsaw Mean Time 
         1:00 C-Eur CE%sT 1918 Sep 16 3:00 
         2:00 Poland EE%sT 1922 Jun 
         1:00 Poland CE%sT 1940 Jun 23 2:00 
         1:00 C-Eur CE%sT 1944 Oct 
         1:00 Poland CE%sT 1977 
         1:00 W-Eur CE%sT 1988 
         1:00 EU CE%sT 

1900 में, पोलैंड एक समय क्षेत्र में एक घंटे की भरपाई था और यूटीसी से 24 मिनट, यानी, वे स्थानीय औसत सौर समय का उपयोग कर रहे थे। 5 अगस्त, 1 9 15 को मानक समय क्षेत्र पेश किए जाने से पहले

यह होना चाहिए कि आप PostgreSQL को timestamp without time zone फ़ीड करें, जिसका अर्थ आपके स्थानीय समय क्षेत्र (1:24 के ऑफसेट के साथ) में किया गया है।

कोई (स्कैला?) फिर इस टाइमस्टैम्प को आपके स्थानीय समय क्षेत्र में एक टाइमस्टैम्प में परिवर्तित करता है, लेकिन गलती से एक घंटे का ऑफ़सेट उपयोग करता है।

मुझे लगता है कि कैसे वास्तव में ठीक करने के लिए, लेकिन या तो भर timestamp without time zone का उपयोग करें या घटक है कि पोलिश समय सोचता है कि ठीक पता नहीं है 1900

+0

सही: मेरा जावा 8 वर्ष 1 9 00 में किसी भी संक्रमण के बारे में नहीं जानता। सबसे पहले यह जानता है कि 1 9 15 में है: संक्रमण [1 915-08-05T00: 00 + 01: 24 से +01: 00] पर ओवरलैप। –

+0

धन्यवाद। ऐसा लगता है कि जावा समस्या तब है। तो एकमात्र शेष विकल्प 'समय क्षेत्र के साथ टाइमस्टैम्प' से बचने के लिए है। –

+0

मुझे लगता है कि आप अपने डेटाबेस में टाइमस्टैम्प-टाइम-टाइमज़ोन का उपयोग कर सकते हैं यदि आप केवल 'java.time.Instant' को सहेजने और पुनर्प्राप्त करने के लिए उपयोग कर सकते हैं (या' स्ट्रिंग' अगर सभी विफल हो जाते हैं, लेकिन आप 'तत्काल' पसंद करेंगे)। –

2

में यूटीसी से 1 घंटे ऑफसेट किया गया था जहाँ तक मेरा बता सकते हैं देखते हैं यहां शामिल दो बग। java.util.Date कक्षा में दोनों हैं (यदि मैं सही हूं) java.sql.Timestamp का सुपरक्लास।

सबसे पहले, 1 9 00 में वॉरसॉ में ऑफसेट संक्रमण का कोई समय नहीं है। 1 9 15 में मेरा जावा 8 जानता है कि सबसे पुराना संक्रमण 1 9 15 में है। इसलिए वॉरसॉ हर समय जीएमटी से 1:24 ऑफसेट पर था जब हम चिंतित थे साथ में।

मैंने कोशिश की:

TimeZone.setDefault(TimeZone.getTimeZone("Europe/Warsaw")); 
    ZoneOffset offset0124 = ZoneOffset.ofHoursMinutes(1, 24); 

    System.out.println("" + new Date(0, 0, 1, 0, 59) 
      + " -> " + new Date(0, 0, 1, 0, 59).toInstant().atOffset(offset0124)); 
    System.out.println("" + new Date(0, 0, 1, 1, 14) 
      + " -> " + new Date(0, 0, 1, 1, 14).toInstant().atOffset(offset0124)); 
    System.out.println("" + new Date(0, 0, 1, 1, 24) 
      + " -> " + new Date(0, 0, 1, 1, 24).toInstant().atOffset(offset0124)); 

यह प्रिंट:

Mon Jan 01 00:59:00 CET 1900 -> 1900-01-01T01:23+01:24 
Mon Jan 01 01:38:00 CET 1900 -> 1900-01-01T01:38+01:24 
Mon Jan 01 01:24:00 CET 1900 -> 1900-01-01T01:24+01:24 

विधि Timestamp.valueOf विधि आप परोक्ष रूप से एक पदावनत Date निर्माता का उपयोग करता है का उपयोग करते हैं, इसलिए तो मैं (नहीं ठीक उसी निर्माता हूँ, मैं सेकंड के बिना एक का उपयोग कर रहा हूँ, भरोसा यह कोई फर्क नहीं पड़ता)। मैं ऊपर तीन मामलों पिछड़े पर टिप्पणी करेंगे:

  • 1:24 सही ढंग से नियंत्रित किया जाता है, हम दोनों Date.toString() से और OffsetDateTime से संभावित समय मिलता है।
  • 1:14 को 1:38, 24 मिनट बाद माना जाता है। यह मेरे लिए एक बग की तरह दिखता है।
  • 0:59 को 24:23 के बाद भी 1:23 के रूप में माना जाता है। हम इसे OffsetDateTime से देख सकते हैं। एक ही बग हालांकि, Date.toString() अपेक्षित के रूप में 00:59 उत्पन्न करता है। ऐसा लगता है कि यह एक दूसरी बग है जो कि पहले किसी के लिए क्षतिपूर्ति करता है। मैंने जांच नहीं की है, लेकिन मुझे संदेह है कि इस बग का स्रोत भी Timestamp.toString() गलत तरीके से व्यवहार करने का कारण बनता है।

चेक के रूप में मैंने आपके Timestamp 0:59 और 1:24 की वस्तुओं के बीच अंतर की गणना की। वांछित परिणाम 25 मिनट या 1 500 000 मिलीसेकंड है।कोड है:

System.out.println(java.sql.Timestamp.valueOf("1900-01-01 01:24:00").getTime() 
      - java.sql.Timestamp.valueOf("1900-01-01 00:59:00").getTime()); 

यह

60000 

60 सेकंड, 1 मिनट के रूप में ही प्रिंट करता है। तो फिर भी उन दोनों टाइमस्टैम्प ने जिस तरह से उम्मीद की थी, उसमें मुद्रित किया गया, फिर भी इसमें एक बग शामिल है।

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