2008-11-21 13 views
14

मैंने एक MySQL डीबी में फ़ील्ड भरने के लिए एक नई तिथि() ऑब्जेक्ट का उपयोग किया, लेकिन उस फ़ील्ड में संग्रहीत वास्तविक मान मेरे स्थानीय टाइमज़ोन में है।यूटीसी/जीएमटी टाइमज़ोन में एक jas.util.Date को एक MySQL टाइमस्टैम्प फ़ील्ड में कैसे स्टोर करें?

मैं इसे यूटीसी/जीएमटी टाइमज़ोन में संग्रहीत करने के लिए MySQL को कैसे कॉन्फ़िगर कर सकता हूं?

मुझे लगता है कि कनेक्शन स्ट्रिंग को कॉन्फ़िगर करने में मदद मिलेगी, लेकिन मुझे नहीं पता कि कैसे। useTimezone, serverTimzone, useGmtMillisForDatetimes, useLegacyDatetimeCode, जैसे कनेक्शन स्ट्रिंग में कई गुण हैं ...

+0

क्या आप हाइबरनेट का उपयोग कर रहे हैं या डेटाबेस के इंटरफ़ेस के समान हैं? –

उत्तर

13

संक्षिप्त उत्तर है:

  • ऐड "डिफ़ॉल्ट समय क्षेत्र = यूटीसी" यूटीसी, में अपने कोड में
  • my.cnf करने के लिए, हमेशा "लगता है कि" जब अपने उपयोगकर्ताओं के लिए दिनांक प्रदर्शित करने के सिवाय
  • /जब हो रही JDBC के साथ तारीखों या timestamps की स्थापना, हमेशा कैलेंडर पैरामीटर, यूटीसी करने के लिए सेट का उपयोग करें:

    resultset.getTimestamp ("my_date", Calendar.getInstance (TimeZone.getTimeZone ("यूटीसी"))) ;

  • या तो अपने सर्वर को एनटीपी के साथ सिंक्रनाइज़ करें, या डेटाबेस सर्वर पर भरोसा करें कि यह आपको बताए कि यह कितना समय है।

    1. कॉन्फ़िगर:

      जब किसी डेटाबेस में और किसी भी ग्राहक कोड के साथ दिनांक और समय-क्षेत्रों के साथ काम कर, मैं आमतौर पर निम्नलिखित नीति की सिफारिश:


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

  • ऐसा करने के लिए कैसे करें अपने डेटाबेस सर्वर पर निर्भर करता है। MySQL के लिए निर्देश यहां पाए जा सकते हैं: http://dev.mysql.com/doc/refman/5.0/en/time-zone-support.html। असल में आपको इसे my.cnf में लिखना होगा: डिफ़ॉल्ट-समय-क्षेत्र = utc

  • इस तरह आप कहीं भी अपने डेटाबेस सर्वर होस्ट कर सकते हैं, अपना होस्टिंग स्थान आसानी से बदल सकते हैं, और आमतौर पर बिना किसी अस्पष्टता के आपके सर्वर पर तिथियों का उपयोग कर सकते हैं ।

  • यदि आप वास्तव में स्थानीय टाइमज़ोन का उपयोग करना पसंद करते हैं, तो मैं कम से कम डेलाइट सेविंग टाइम को बंद करने की अनुशंसा करता हूं, क्योंकि आपके डेटाबेस में संदिग्ध तिथियां वास्तविक दुःस्वप्न हो सकती हैं।
    • उदाहरण के लिए, यदि आप एक टेलीफोनी सेवा का निर्माण कर रहे हैं और आप डेलाइट सेविंग टाइम का उपयोग कर रहे अपने डेटाबेस सर्वर पर तो आप मुसीबत के लिए पूछ रहे हैं कि: कोई रास्ता नहीं है कि क्या यह बताने के लिए किया जाएगा एक ग्राहक जो "2008- से कहा जाता है 10-26 02:30:00 "से" 2008-10-26 02:35:00 "वास्तव में 5 मिनट या 1 घंटे और 5 मिनट के लिए बुलाया जाता है (लगता है कि डेलाइट सेविंग 26 अक्टूबर को 3 बजे हुआ था)!
  • आपके आवेदन कोड के अंदर, हमेशा यूटीसी, तारीखें जब अपने उपयोगकर्ताओं के लिए दिनांक प्रदर्शित करने के सिवाय का उपयोग करें।

    • जावा में, जब डेटाबेस से पढ़ने, हमेशा का उपयोग करें:

    टाइमस्टैम्प myDate = resultSet.getTimestamp ("my_date", Calendar.getInstance (TimeZone.getTimeZone ("यूटीसी"))) ;

    • यदि आप ऐसा नहीं करते हैं, तो टाइमस्टैम्प यूटीसी के बजाय आपके स्थानीय टाइमज़ोन में माना जाएगा।
  • अपने सर्वर सिंक्रनाइज़ या केवल डेटाबेस सर्वर के समय

    • पर भरोसा करते हैं आप एक सर्वर (या अधिक) और कुछ अन्य सर्वर पर अपने डेटाबेस सर्वर पर आपके वेब सर्वर है, तो मैं दृढ़ता से अनुशंसा करता हूं कि आप अपने घड़ियों को एनटीपी के साथ सिंक्रनाइज़ करें।

    • या, केवल एक सर्वर पर भरोसा करें कि यह आपको बताए कि यह कितना समय है। आमतौर पर, समय के लिए पूछने के लिए डेटाबेस सर्वर सबसे अच्छा है। दूसरे शब्दों में, इस जैसे कोड से बचने:

    preparedStatement = connection.prepareStatement ("? अद्यतन My_table सेट my_time = जहां [...]");
    java.util.Date now = new java.util.Date(); // स्थानीय समय! :-(
    preparedStatement.setTimestamp (1, नई समय-चिह्न (now.getTime()));
    पूर्णांक परिणाम = preparedStatement.execute();

    • इसके बजाय, डेटाबेस सर्वर के समय पर निर्भर करते हैं:

    preparedStatement = connection.prepareStatement ("अद्यतन My_table सेट my_time = NOW() जहां [...]");
    पूर्णांक परिणाम = preparedStatement.execute();

  • उम्मीद है कि यह मदद करता है! :-)

    +0

    दो जोड़: 1. आपको "डिफ़ॉल्ट-समय-क्षेत्र = जीएमटी" (केस-संवेदी) का उपयोग करना चाहिए क्योंकि MySQL नहीं है "utc" को "जीएमटी" में मैप करने के लिए पर्याप्त स्मार्ट और जावा केवल बाद वाले को पहचानता है। 2. आपको इस बग को ठीक करने के लिए ड्राइवर "useLegacyDatetimeCode = false" पास करना होगा: http://bugs.mysql.com/bug.php?id=15604 – Gili

    +0

    बहुत अच्छे अंक! बग मेरे पास उठाने के लिए कुछ अन्य अंक हैं। आपने प्रत्येक कनेक्शन पर सत्र टाइमज़ोन को डीबी में सेट करने का विकल्प नहीं माना है, ऐसा करने के लिए आपको अपने MySQL को कौन सा टाइमज़ोन शुरू करने की आवश्यकता नहीं है। मुझे डीबी पर 'नया java.util.Date' संग्रहीत करते समय बहुत सारी समस्याएं आ रही हैं। त्वरित समाधान यूटीसी पर भी शुरू करने के लिए मेरा JVM सेट किया गया है (-Duser.timezone = UTC)। ये अंक आपकी पोस्ट में जोड़ने के लिए अच्छा होगा! –

    +0

    [time_zone] (http://dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_time_zone) सिस्टम चर पर MySQL दस्तावेज़ के अनुसार, my.cnf चर नाम है default_time_zone (आपकी पोस्ट में दिखाए गए डैश के विपरीत अंडरस्कोर)। –

    1

    ठीक है, अगर हम PreparedStatement रों उपयोग के बारे में बात कर रहे हैं, वहाँ एक form of setDate है जहाँ आप एक कैलेंडर एक विशेष करने के लिए सेट में पारित कर सकते हैं समय क्षेत्र।

    उदाहरण के लिए

    , आप एक PreparedStatement नामित stmt, एक तिथि नामित तिथि, और अगर तिथि मानते हुए दूसरा पैरामीटर है:

    stmt.setDate(2, date, Calendar.getInstance(TimeZone.getTimeZone("GMT"))); 
    

    सबसे अच्छी बात यह भले ही जीएमटी गलत समय क्षेत्र का नाम है, है , यह अभी भी GetTimeZone के डिफ़ॉल्ट व्यवहार की वजह से जीएमटी समय क्षेत्र लौटाता है।

    +0

    मैं हमेशा जीएमटी के बजाय यूटीसी का उपयोग करना पसंद करता हूं। –

    +1

    डिफ़ॉल्ट रूप से, कैलेंडर ऑब्जेक्ट पूरी तरह से अनदेखा नहीं किया जाता है जब तक आप कनेक्शन विकल्प का उपयोग नहीं करते हैं LegacyDatetimeCode = false – nogridbag

    1

    एक जावा तिथि टाइमज़ोन अज्ञेयवादी है। यह हमेशा एपोक से मिलीसेकंड में जीएमडी (यूटीसी) में एक तिथि का प्रतिनिधित्व करता है।

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

    2

    MiniQuark सामान्य रूप में डेटाबेस के लिए कुछ अच्छा जवाब दे दिया है, लेकिन वहाँ पर विचार करने के कुछ MySql विशिष्ट quirks ...

    UTC समयज़ोन उपयोग करने के लिए

    अपने डेटाबेस को कॉन्फ़िगर कर रहे हैं यही कारण है कि वास्तव में नहीं होगा समस्या को ठीक करने के लिए पर्याप्त हो। यदि आप java.util.Date को MySQL पर भेजते हैं, ओपी पूछ रहा था, तो MySQL ड्राइवर डेटाबेस 0 के समय क्षेत्र में उसी स्थानीय समय की तरह दिखने के लिए मान को बदल देगा।

    उदाहरण: यूटीसी में कॉन्फ़िगर किया गया आपका डेटाबेस। आपका आवेदन ईएसटी है। आप 5:00 (ईएसटी) के लिए java.util.Date ऑब्जेक्ट पास करते हैं। डेटाबेस इसे 5:00 यूटीसी में परिवर्तित करेगा और इसे स्टोर करेगा। बहुत बढ़िया।

    इस स्वचालित समायोजन को "पूर्ववत करने" के लिए डेटा को पास करने से पहले आपको समय समायोजित करना होगा। कुछ की तरह ...

    long originalTime = originalDate.getTime(); 
    Date newDate = new Date(originalTime - TimeZone.getDefault().getOffset(originalTime)); 
    ps.setDate(1, newDate); 
    

    डेटा वापस बाहर पढ़ना एक ऐसी ही रूपांतरण ..

    long dbTime = rs.getTimestamp(1).getTime(); 
    Date originalDate = new Date(dbTime + TimeZone.getDefault().getOffset(dbTime)); 
    

    यहाँ एक और मजेदार मोड़ है ...

    जावा में, जब से पढ़ने की आवश्यकता है डेटाबेस, हमेशा उपयोग करें: टाइमस्टैम्प myDate = resultSet.getTimestamp ("my_date", calendar.getInstance (TimeZone.getTimeZone ("UTC"));

    MySQL वास्तव में उस कैलेंडर पैरामीटर को अनदेखा करता है। यह वही मूल्य देता है चाहे आप इसे किस कैलेंडर को पास करते हैं।

    2

    मुझे एक ही समस्या थी, और मुझे ट्रैक करने के लिए लगभग एक दिन लग गया। मैं MySQL में डेटटाइम कॉलम संग्रहीत कर रहा हूं। अमेज़ॅन के क्लाउड में चल रहे आरडीएस इंस्टेंस को डिफ़ॉल्ट रूप से यूटीसी टाइमस्टैम्प के लिए सही ढंग से सेट किया गया है।

    छोटी गाड़ी कोड है:

    String startTime = "2013-02-01T04:00:00.000Z"; 
        DateTime dt = ISODateTimeFormat.dateTimeParser().parseDateTime(startTime);    
    
        PreparedStatement stmt = connection.prepareStatement(insertStatementTemplate); 
    
        Timestamp ts = new Timestamp(dt.getMillis()); 
        stmt.setTimestamp(1, ts, Calendar.getInstance(TimeZone.getTimeZone("UTC"))); 
    

    उपरोक्त कोड में, ".setTimestamp" फोन नहीं एक यूटीसी तिथि के रूप में की तारीख ले जाएगा!

    जांच के घंटों के बाद, यह जावा/MySQL चालक में एक ज्ञात बग साबित हुआ। सेट टिमस्टैम्प को सेट करने के लिए कॉल केवल कैलेंडर पैरामीटर को अनदेखा करता है।

    इसे ठीक करने के लिए "उपयोग LegacyDatetimeCode = false" को अपने डेटाबेस यूआरआई में जोड़ें।

    private final static String DatabaseName = 
        "jdbc:mysql://foo/?useLegacyDatetimeCode=false"; 
    

    जैसे ही मैं कि, MySQL डाटाबेस में संग्रहित तारीख बल्कि अपने स्थानीय कार्य केंद्र के समय क्षेत्र में से उचित यूटीसी रूप में था, किया।

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