2009-08-11 16 views
8

मेरे पास एक रेल समय-आधारित क्वेरी है जिसमें कुछ अजीब टाइमज़ोन संवेदनशील व्यवहार है, भले ही मुझे पता है कि मैं यूटीसी का उपयोग कर रहा हूं। संक्षेप में, इन प्रश्नों अलग जवाब दे:टाइमज़ोन के आधार पर यह रेल क्वेरी अलग-अलग व्यवहार क्यों करती है?

>> Model.find(:all,:conditions=>['created_at<=?',(Time.now-1.hours).gmtime]).length 
=> 279 
>> Model.find(:all,:conditions=>['created_at<=?',(Time.now-1.hours)]).length 
=> 280 

कहाँ डीबी वास्तव में एक मॉडल अंतिम घंटे में बनाया शामिल करता है, और मॉडल की कुल संख्या 280 तो केवल पहली क्वेरी सही है।

हालांकि, environment.rb में मेरे पास है:

config.time_zone = 'UTC' 

प्रणाली समय क्षेत्र (के रूप में 'तारीख' द्वारा रिपोर्ट) BST (जो जीएमटी + 1 है) - तो किसी भी तरह इस ऊपर से हवाएँ रूप में व्यवहार किया जा रहा है यूटीसी और तोड़ने के सवाल।

यह मुझे सभी प्रकार की समस्याओं का कारण बन रहा है क्योंकि मुझे किसी कार्रवाई में अलग-अलग समय में गुजरने वाली क्वेरी को पैरामीटर करने की आवश्यकता होती है (जिसे बाद में टाइम.परसे() का उपयोग करके परिवर्तित किया जाता है, और भले ही मैं यूटीसी टाइम्स में भेजूं, एक घंटे से दूर 'डीएसटी मुद्दे फसल बहुत कुछ। यहां तक ​​कि '.gmtime()' का उपयोग करने से हमेशा इसे ठीक नहीं लगता है।

जाहिर है कि अंतर किसी भी तरह से एक अंतर्निहित रूपांतरण से होता है जिसके परिणामस्वरूप बीएसटी को गलत तरीके से यूटीसी के रूप में माना जाता है, लेकिन क्यों? रेलवे यूटीसी में टाइमस्टैम्प स्टोर नहीं करता है? टाइम क्लास टाइमज़ोन जागरूक नहीं है? मैं रेल का उपयोग कर रहा हूं 2.2.2

तो यहां क्या हो रहा है - और इसके आसपास कार्यक्रम करने का सुरक्षित तरीका क्या है?

संपादित करें, कुछ अतिरिक्त जानकारी दिखाने के लिए क्या DB और समय वर्ग कर रहे हैं:

>> Model.find(:last).created_at 
=> Tue, 11 Aug 2009 20:31:07 UTC +00:00 
>> Time.now 
=> Tue Aug 11 22:00:18 +0100 2009 
>> Time.now.gmtime 
=> Tue Aug 11 21:00:22 UTC 2009 

उत्तर

13

Time वर्ग सीधे अपने कॉन्फ़िगर किया गया समय क्षेत्र के बारे में पता नहीं है। रेल 2.1 ने टाइमज़ोन समर्थन का एक गुच्छा जोड़ा, लेकिन Time अभी भी आपके स्थानीय टाइमज़ोन पर कार्य करेगा। यही कारण है कि Time.now एक बीएसटी समय देता है।

आप जो चाहते हैं Time.zone के साथ बातचीत करना है। आप इस पर विधियों को कॉल कर सकते हैं जैसे आप टाइम क्लास स्वयं करेंगे लेकिन यह इसे निर्दिष्ट समय क्षेत्र में वापस कर देगा।

Time.zone.now # => Tue, 11 Aug 2009 21:31:45 UTC +00:00 
Time.zone.parse("2:30 PM Aug 23, 2009") # => Sun, 23 Aug 2009 14:30:00 UTC +00:00 

एक और बात आप सावधान है के साथ अगर तुम कभी डेटाबेस पर क्वेरी कर जहां बार की तुलना कर रहे हैं, लेकिन यकीन है कि (भले ही आप एक अलग समय क्षेत्र निर्दिष्ट है) का उपयोग करने UTC समय क्योंकि रेल होना जरूरी हमेशा डेटाबेस में यूटीसी स्टोर करता है।

Item.all(:conditions => ["published_at <= ?", Time.now.utc]) 

इसके अलावा, बजाय Time.now-1.hour1.hour.ago है। इसे पढ़ना आसान है और रेल स्वचालित रूप से कॉन्फ़िगर किए गए टाइमज़ोन का उपयोग करेंगे।

+0

दिलचस्प ... Time.utc Time.gmtime के लिए एक पर्याय है? इसके अलावा मुझे >> Time.zone => # > प्राप्त करें। मुझे लगता है कि समस्या यह है कि "11 अगस्त 22:00:18 +0100 200 9" और "ट्यू 11 अगस्त 21:00:22 यूटीसी 200 9" के बारे में सोचने के मेरे तरीके के लिए एक ही तार्किक समय का संदर्भ लें। मुझे लगता है कि एसक्यूएल बनाने के दौरान रेल/रूबी ऑफसेट को अनदेखा कर रहा है। – frankodwyer

+1

मेरा मानना ​​है कि समय # यूटीसी समय # जीएमटाइम के लिए सिर्फ एक उपनाम है।साथ ही, टाइमज़ोन ऑफसेट को सामान्य समय (टाइम.now) से निपटने पर नजरअंदाज कर दिया जाता है लेकिन Time.zone.now का उपयोग करते समय ध्यान में रखा जाता है। हमेशा Time.zone का उपयोग करने के लिए सबसे अच्छा है तो आपको उस पर "utc" कॉल नहीं करना चाहिए। – ryanb

+0

धन्यवाद, जो बहुत मदद करता है। यह मेरे लिए अनजान है कि यह इस तरह से काम करता है लेकिन कम से कम मैं समझता हूं कि अब क्या हो रहा है। मैंने तदनुसार कोड बदल दिया है और ऐसा लगता है कि इस मुद्दे को मंजूरी दे दी गई है। एक और चीज जो मेरे कोड को फेंक रही थी वह थी कि 1. वर्ष 1 साल तक समान रूप से विभाजित नहीं है जैसा कि मैंने उम्मीद की थी ... मैं एक लूप कर रहा था और इसके कारण एक असंबंधित लेकिन इसी तरह की त्रुटि प्राप्त कर रहा था। – frankodwyer

0

समयक्षेत्र आप स्थापित करने की आवश्यकता ब्रिटेन है, यह स्वचालित रूप से संभाल लेंगे BST

Time.zone = 'UK' 
Time.zone.now 
=> Sun, 17 Oct 2010 02:09:54 BST +01:00 
+0

मेरा मानना ​​है कि यह अब समय होना चाहिए। ज़ोन = "लंदन" – simonmorley

+0

हां यह अब लंदन होगा – MatthewFord

0
start_date_format = DateTime.strptime(@start_date, date_format) 
start_date_format_with_hour = 
DateTime.strptime((start_date_format.to_i + timezone_offset*60*60).to_s,'%s').strftime(date_format) 

end_date_format = DateTime.strptime(@end_date, date_format) 
end_date_format_with_hour = DateTime.strptime((end_date_format.to_i + timezone_offset*60*60).to_s,'%s').strftime(date_format) 

@filters_date = "invoices.created_at >= ? AND invoices.created_at < ?", start_date_format_with_hour, end_date_format_with_hour 
+0

बस कोड का एक टुकड़ा छोड़ना शायद ही कभी सहायक होता है। कृपया थोड़ा सा समझाएं कि कोड क्या करता है। – lexicore

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