2012-03-22 14 views
7

जावा और MySQL से दिनांक और समय को संभालने के तरीके के बारे में पढ़ने और पढ़ने के बाद भी मैं उलझन में हूं।अभी भी जावा टाइमस्टैम्प आदि द्वारा भ्रमित MySQL

मान लें कि मैं java.util.Date ऑब्जेक्ट बना रहा हूं। उस वस्तु में यूटीसी में समय है। किसी भी स्वरूपण या अन्य समय क्षेत्रों में पार्सिंग को उदाहरण के साथ बनाया जा सकता है java.text.SimpleDateFormat

अब मैं अपनी दिनांक वस्तु को यूटीसी में MySQL डेटाबेस में संग्रहीत करना चाहता हूं। लेकिन जब मैं विधि java.sql.PreparedStatement में उपयोग करता हूं तो मुझे थोड़ा उलझन मिलता है। यहां कुछ नमूना कोड का पालन किया गया है जहां मैं अपनी तालिका में MySQL DATETIME और TIMESTAMP दोनों का परीक्षण करता हूं। मैं setString() और setTimestamp() विधियों दोनों के साथ तिथियां भी सम्मिलित करता हूं।

java.sql.Connection conn = java.sql.DriverManager.getConnection("jdbc:mysql://localhost/test","user","password"); 
java.sql.Statement st = conn.createStatement(); 

String q = "DROP TABLE IF EXISTS tmp"; 
st.execute(q); 
q = "CREATE TABLE tmp (dt_string TEXT, dt DATETIME, ts TIMESTAMP)"; 
st.execute(q); 

java.sql.PreparedStatement pst = conn.prepareStatement("INSERT INTO tmp SET dt_string=?, dt=?, ts=?"); 

java.text.SimpleDateFormat utc = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
utc.setTimeZone(java.util.TimeZone.getTimeZone("UTC")); 

java.util.TimeZone.setDefault(java.util.TimeZone.getTimeZone("EST")); 

System.out.println("Default time zone: " + java.util.TimeZone.getDefault().getID()); 
java.util.Date d = new java.util.Date(); 
System.out.println("A date: " + d); 
java.sql.Timestamp t = new java.sql.Timestamp(d.getTime()); 
System.out.println("The timestamp: " + t); 


pst.setString(1, utc.format(d)); 
pst.setString(2, utc.format(d)); 
pst.setString(3, utc.format(t)); 
pst.execute(); 

pst.setTimestamp(2, t); 
pst.setTimestamp(3, t); 
pst.execute(); 

System.out.println("Use calendar: " + utc.getCalendar().getTimeZone()); 
pst.setTimestamp(2, t, utc.getCalendar()); 
pst.setTimestamp(3, t, utc.getCalendar()); 
pst.execute(); 

conn.close(); 

जब मैं उपरोक्त भागता हूं तो मुझे निम्न आउटपुट मिलता है जो अपेक्षा की जाती है।

Default time zone: EST 
A date: Thu Mar 22 08:49:51 EST 2012 
The timestamp: 2012-03-22 08:49:51.784 
Use calendar: sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null] 

लेकिन जब मैं डेटाबेस में तालिका का निरीक्षण MySQL कमांड लाइन उपकरण का उपयोग कर रहा है:

mysql> select * from tmp; 
+---------------------+---------------------+---------------------+ 
| dt_string   | dt     | ts     | 
+---------------------+---------------------+---------------------+ 
| 2012-03-22 13:49:51 | 2012-03-22 13:49:51 | 2012-03-22 13:49:51 | 
| 2012-03-22 13:49:51 | 2012-03-22 08:49:51 | 2012-03-22 08:49:51 | 
| 2012-03-22 13:49:51 | 2012-03-22 08:49:51 | 2012-03-22 08:49:51 | 
+---------------------+---------------------+---------------------+ 
3 rows in set (0.00 sec) 

पहले कॉलम सिर्फ एक पाठ टाइप करें, जहां मैं यूटीसी स्टोर स्वरूपित तारीख है।

पहली पंक्ति में मैंने setString() विधि का उपयोग करके तिथियां संग्रहीत कीं।

दूसरी पंक्ति में मैंने setTimestamp(i,t) विधि का उपयोग करके दिनांक संग्रहीत किया। मुझे लगता है कि जेडीबीसी इसे स्टोर करने से पहले स्वचालित समय क्षेत्र (जिसे मैं ईएसटी पर सेट करता हूं) का उपयोग कर तारीख को स्वचालित रूप से परिवर्तित करता हूं। लेकिन TIMESTAMP हमेशा यूटीसी में स्वचालित रूप से संग्रहीत नहीं होना चाहिए। MySQL प्रलेखन का कहना है कि MySQL वर्तमान समय क्षेत्र से स्टोरेज के लिए यूटीसी में TIMESTAMP मानों को परिवर्तित करता है, और पुनर्प्राप्ति के लिए यूटीसी से वर्तमान समय क्षेत्र में वापस आता है। (अंक 1)।

अंत में, तीसरी पंक्ति के लिए मैंने तिथि को संग्रहीत करने के लिए pst.setTimestamp(2, t, utc.getCalendar()); का उपयोग किया ताकि ड्राइवर को यूटीसी समय क्षेत्र का उपयोग करना चाहिए। लेकिन स्पष्ट रूप से नहीं (अंक 2)।

मैं यूटीसी में डिफ़ॉल्ट समय क्षेत्र सेट करके यूटीसी में तिथियों को स्टोर करने के लिए समस्या को आसानी से ठीक कर सकता हूं। लेकिन फिर भी, मैं समझना चाहता हूं कि उपरोक्त दो मुद्दों के लिए क्या चल रहा है।

+0

* "पुनर्प्राप्ति के लिए यूटीसी से वर्तमान समय क्षेत्र में वापस" * आउटपुट में आप जो देखते हैं वह है। –

+0

धन्यवाद, लेकिन क्या आप इस पर विस्तार कर सकते हैं? – Peter

+0

टाइमस्टैम्प को आंतरिक रूप से यूटीसी में संग्रहीत किया जाता है, लेकिन जब आप उन्हें 'mysql' क्लाइंट का उपयोग करके आउटपुट करते हैं, तो उन्हें स्थानीय समय में प्रस्तुत किया जाता है, जैसे MySQL दस्तावेज़ आपको बताता है। समस्या के लिए वही 2. यहां समस्या क्या है? –

उत्तर

0

MySQL डेटाटाइम फ़ील्ड भयानक हैं जब आप उनके चारों ओर अपने सिर को लपेटते हैं।

आपके द्वारा उपयोग किए जा रहे "SimpleDateFormat" में समय क्षेत्र संलग्न नहीं है, इसलिए आपका डेटाबेस मानता है कि आप अपने सर्वर के टाइमज़ोन में एक तिथि दर्ज कर रहे हैं। यदि आप एक -500 समय क्षेत्र में हैं, तो इसे यूटीसी में परिवर्तित करने के लिए 5 घंटे जोड़ते हैं, और फिर जब आप इसे प्राप्त करते हैं, तो यह इसे आपके स्थानीय समय में बदलने के लिए 5 घंटे घटा देता है।

जब आपने अपना टाइमस्टैम्प यूटीसी में डालने से पहले कनवर्ट किया था, तब भी आपने स्ट्रिंग पर टाइमज़ोन का सामना नहीं किया था। आपके डेटाबेस ने उसी ऑपरेशन पर प्रदर्शन किया। 5 घंटे 2012-03-22 13:49:51 में जोड़ा गया था, इसलिए आपका डीबी संग्रहीत 2012-03-22 18:49:51 (अभी भी मानते हैं -0500)।

यह सब का वास्तव में मजेदार हिस्सा यह है कि आप डेटाबेस कनेक्शन पर टाइमज़ोन सेट कर सकते हैं, और आपके द्वारा प्राप्त या डालने वाले सभी डेटा आपके कनेक्शन के साथ बदल जाएंगे!

+0

लेकिन मैं केवल स्ट्रिंग बनाने के लिए SimpleDateFormat का उपयोग करता हूं जिसे मैं डेटाबेस में टेक्स्ट फ़ील्ड में दर्ज करता हूं। टाइमस्टैम या टाइमस्टैम्प फ़ील्ड में टाइमस्टैम्प का प्रत्यक्ष आवेषण SimpleDateFormat का उपयोग नहीं करता है। – Peter

1

अंत में, मैं कुछ समझ रहा हूं, लेकिन इसके बजाय PostgreSQL का उपयोग कर रहा हूं।मैं मूल रूप से

Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost"); 

st.execute("CREATE TABLE tmp (ts_string TEXT, ts TIMESTAMP WITH TIME ZONE)"); 
//st.execute("CREATE TABLE tmp (ts_string TEXT, ts TIMESTAMP WITHOUT TIME ZONE)"); 

का उपयोग करने और

pst.setString(1, utc.format(d)); 
pst.setTimestamp(2, t); 
pst.execute(); 

pst.setTimestamp(2, t, utc.getCalendar()); 
pst.execute(); 

के रूप में दिनांक लेखन उपरोक्त कोड दोहराया जब TIMESTAMP WITH TIMEZONE क्योंकि यह का ट्रैक रख रहा है मैं से psql

postgres=# select * from tmp; 
     ts_string  |    ts    
-------------------------+---------------------------- 
2012-03-23 12:48:28.057 | 2012-03-23 13:48:28.057+01 
2012-03-23 12:48:28.057 | 2012-03-23 13:48:28.057+01 
(2 rows) 

निम्नलिखित आउटपुट प्राप्त प्रयोग किया जाता है सिस्टम (सर्वर) समय क्षेत्र, जो सीईटी (+01) है। दिनांक सही हैं हालांकि सीईटी में प्रदर्शित किया गया है।

अगर मैं बजाय TIMESTAMP WITHOUT TIME ZONE का उपयोग मैं बस के रूप में

postgres=# select * from tmp; 
     ts_string  |   ts   
-------------------------+------------------------ 
2012-03-23 12:49:04.120 | 2012-03-23 07:49:04.12 
2012-03-23 12:49:04.120 | 2012-03-23 12:49:04.12 
(2 rows) 

हो और पहले मामले में यह सामान्य समय क्षेत्र (जो मैं ईएसटी करने के लिए सेट) का उपयोग करता है, और तारीख स्वाभाविक रूप से "गलत" है, MySQL मामला हालांकि, दूसरे मामले में यह यूटीसी का उपयोग करता है क्योंकि मैंने इसे setTimestamp() विधि के लिए तर्क के रूप में पारित किया है, और यही वह है जिसे मैंने MySQL में करने की कोशिश की। मेरे लिए, ऐसा लगता है कि MySQL जावा ड्राइवर setTimestamp() में Calendar तर्क को अनदेखा करता है। शायद मुझे कुछ याद आया।

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