रूबी DateTime
और Time
वर्गों के बीच क्या अंतर है और किन कारकों के कारण मुझे एक या दूसरे को चुनना होगा?
रूबी DateTime
और Time
वर्गों के बीच क्या अंतर है और किन कारकों के कारण मुझे एक या दूसरे को चुनना होगा?
जवाबों:
रूबी (2.0+) के नए संस्करणों में वास्तव में दो वर्गों के बीच महत्वपूर्ण अंतर नहीं है। कुछ पुस्तकालय ऐतिहासिक कारणों से एक या दूसरे का उपयोग करेंगे, लेकिन नए कोड को जरूरी नहीं कि संबंधित होना चाहिए। स्थिरता के लिए एक चुनना संभवतः सबसे अच्छा है, इसलिए कोशिश करें और अपने पुस्तकालयों से क्या उम्मीद करें। उदाहरण के लिए, ActiveRecord DateTime को प्राथमिकता देता है।
रूबी 1.9 और कई प्रणालियों से पहले के संस्करणों में समय का प्रतिनिधित्व एक 32-बिट हस्ताक्षरित मूल्य के रूप में किया जाता है, जो 1 जनवरी, 1970 यूटीसी के बाद से सेकंड की संख्या का वर्णन करता है, जो कि POSIX- मानक time_t
मान के आसपास एक पतला आवरण है , और यह बाध्य है:
Time.at(0x7FFFFFFF)
# => Mon Jan 18 22:14:07 -0500 2038
Time.at(-0x7FFFFFFF)
# => Fri Dec 13 15:45:53 -0500 1901
रूबी के नए संस्करण त्रुटियों को पैदा किए बिना बड़े मूल्यों को संभालने में सक्षम हैं।
डेटटाइम एक कैलेंडर-आधारित दृष्टिकोण है जहां वर्ष, महीना, दिन, घंटा, मिनट और दूसरा व्यक्तिगत रूप से संग्रहीत किया जाता है। यह रूल्स ऑन रूब का निर्माण है जो SQL- मानक DATETIME फ़ील्ड के चारों ओर आवरण के रूप में कार्य करता है। इनमें मनमाने तरीके से तारीखें होती हैं और यह समय के लगभग किसी भी बिंदु का प्रतिनिधित्व कर सकता है क्योंकि अभिव्यक्ति की सीमा आमतौर पर बहुत बड़ी होती है।
DateTime.new
# => Mon, 01 Jan -4712 00:00:00 +0000
इसलिए यह आश्वस्त है कि डेटटाइम ब्लॉग पोस्ट अरस्तू से संभाल सकता है।
किसी एक को चुनते समय, अंतर अब कुछ व्यक्तिपरक हैं। ऐतिहासिक रूप से डेटटाइम ने इसे कैलेंडर फैशन में हेरफेर करने के लिए बेहतर विकल्प प्रदान किए हैं, लेकिन इनमें से कई तरीकों को समय के साथ-साथ कम से कम रेल के वातावरण में चित्रित किया गया है।
[जुलाई २०१8 संपादित करें]
नीचे दिए गए सभी रूबी 2.5.1 में अभी भी सही हैं। से संदर्भ दस्तावेज़ :
डेटटाइम किसी भी छलांग सेकंड पर विचार नहीं करता है, किसी भी गर्मी के समय के नियमों को ट्रैक नहीं करता है।
इससे पहले कि इस धागे में क्या नोट नहीं किया गया है, इसके कुछ फायदों में से एक है DateTime
: यह कैलेंडर सुधारों से अवगत है जबकि Time
ऐसा नहीं है:
[...] रूबी का समय वर्ग एक ग्रैफिक ग्रेगोरियन कैलेंडर लागू करता है और कैलेंडर सुधार की कोई अवधारणा नहीं है [...]।
संदर्भ दस्तावेज का उपयोग करने की सिफारिश के साथ समाप्त होता है, Time
जब विशेष रूप से निकट-अतीत, वर्तमान या भविष्य की तारीखों / समय के साथ काम करते हैं और केवल DateTime
तब उपयोग करते हैं, उदाहरण के लिए, शेक्सपियर के जन्मदिन को सही रूप से परिवर्तित करने की आवश्यकता है: (जोर दिया)
तो आपको Ruby में DateTime का उपयोग कब करना चाहिए और आपको समय का उपयोग कब करना चाहिए? लगभग निश्चित रूप से आप समय का उपयोग करना चाहते हैं क्योंकि आपका ऐप संभवतः वर्तमान तिथियों और समय के साथ काम कर रहा है। हालाँकि, यदि आपको ऐतिहासिक संदर्भ में दिनांक और समय से निपटने की आवश्यकता है, तो आप DateTime […] का उपयोग करना चाहेंगे । अगर आपको भी टाइमजोन से निपटना है, तो बेस्ट ऑफ लक - बस ध्यान रखें कि आप शायद स्थानीय सौर समय से निपटेंगे, क्योंकि यह 19 वीं शताब्दी तक नहीं था जब तक कि रेलवे के परिचय ने मानक समय की आवश्यकता को पूरा नहीं किया था और अंततः टाइमज़ोन।
[/ जुलाई २०१8 संपादित करें]
रूबी 2.0 के रूप में, अन्य उत्तरों में अधिकांश जानकारी पुरानी है।
विशेष रूप से, Time
अब व्यावहारिक रूप से अनबाउंड है। यह एपोच से 63 बिट से भी कम या अधिक हो सकता है:
irb(main):001:0> RUBY_VERSION
=> "2.0.0"
irb(main):002:0> Time.at(2**62-1).utc # within Integer range
=> 146138514283-06-19 07:44:38 UTC
irb(main):003:0> Time.at(2**128).utc # outside of Integer range
=> 10783118943836478994022445751222-08-06 08:03:51 UTC
irb(main):004:0> Time.at(-2**128).utc # outside of Integer range
=> -10783118943836478994022445747283-05-28 15:55:44 UTC
बड़े मूल्यों का उपयोग करने का एकमात्र परिणाम प्रदर्शन होना चाहिए, जो तब बेहतर होता है जब Integer
एस का उपयोग किया जाता है (बनाम Bignum
एस ( Integer
रेंज के बाहर मान ) या Rational
एस (जब नैनोसेकंड ट्रैक किए जाते हैं):
रूबी 1.9.2 के बाद से, टाइम कार्यान्वयन एक हस्ताक्षरित 63 बिट पूर्णांक, बिग्नम या तर्कसंगत का उपयोग करता है। पूर्णांक युग के बाद से नैनोसेकंड की एक संख्या है जो 1823-11-12 से 2116-02-20 तक का प्रतिनिधित्व कर सकती है। जब बिग्नम या परिमेय का उपयोग किया जाता है (1823 से पहले, 2116 के बाद, नैनोसेकंड के तहत), तो समय धीमा हो जाता है जब पूर्णांक का उपयोग किया जाता है। ( http://www.ruby-doc.org/core-2.1.0/Time.html )
दूसरे शब्दों में, जहाँ तक मैं समझता हूँ, DateTime
अब संभावित मूल्यों की एक व्यापक श्रेणी को शामिल नहीं करता हैTime
।
इसके अलावा, DateTime
संभवतः पहले के दो अनधिकृत प्रतिबंधों पर ध्यान दिया जाना चाहिए:
डेटटाइम किसी भी लेप्सकंड पर विचार नहीं करता है, किसी भी गर्मी के समय के नियमों को ट्रैक नहीं करता है। ( http://www.ruby-doc.org/stdlib-2.1.0/libdoc/date/rdoc/Date.html#class-Date-label-DateTime )
सबसे पहले, DateTime
लीप सेकंड की कोई अवधारणा नहीं है:
irb(main):001:0> RUBY_VERSION
=> "2.0.0"
irb(main):002:0> require "date"
=> true
irb(main):003:0> t = Time.new(2012,6,30,23,59,60,0)
=> 2012-06-30 23:59:60 +0000
irb(main):004:0> dt = t.to_datetime; dt.to_s
=> "2012-06-30T23:59:59+00:00"
irb(main):005:0> t == dt.to_time
=> false
irb(main):006:0> t.to_i
=> 1341100824
irb(main):007:0> dt.to_time.to_i
=> 1341100823
उपरोक्त उदाहरण के साथ काम करने के लिए Time
, OS को लीप सेकंड का समर्थन करने की आवश्यकता होती है और टाइमज़ोन जानकारी को सही तरीके से सेट करने की आवश्यकता होती है, जैसे TZ=right/UTC irb
(कई यूनिक्स सिस्टम पर)।
दूसरा, DateTime
समय क्षेत्र की बहुत सीमित समझ है और विशेष रूप से दिन के उजाले की बचत की कोई अवधारणा नहीं है । यह बहुत समय को यूटीसी + एक्स ऑफ़सेट के रूप में समय क्षेत्र संभालता है:
irb(main):001:0> RUBY_VERSION
=> "2.0.0"
irb(main):002:0> require "date"
=> true
irb(main):003:0> t = Time.local(2012,7,1)
=> 2012-07-01 00:00:00 +0200
irb(main):004:0> t.zone
=> "CEST"
irb(main):005:0> t.dst?
=> true
irb(main):006:0> dt = t.to_datetime; dt.to_s
=> "2012-07-01T00:00:00+02:00"
irb(main):007:0> dt.zone
=> "+02:00"
irb(main):008:0> dt.dst?
NoMethodError: undefined method `dst?' for #<DateTime:0x007f34ea6c3cb8>
यह तब परेशानी का कारण बन सकता है जब समय को DST के रूप में दर्ज किया जाता है और फिर DateTime
स्वयं के बाहर सही ऑफसेट का ट्रैक न रखते हुए एक गैर-DST समय क्षेत्र में बदल दिया जाता है (कई ऑपरेटिंग सिस्टम वास्तव में पहले से ही आपके लिए इस बात का ध्यान रख सकते हैं)।
कुल मिलाकर, मैं कहूंगा कि आजकल Time
अधिकांश अनुप्रयोगों के लिए बेहतर विकल्प है।
इसके अलावा एक महत्वपूर्ण अंतर पर भी ध्यान दें: जब आप किसी समय ऑब्जेक्ट में कोई संख्या जोड़ते हैं, तो इसे सेकंड में गिना जाता है, लेकिन जब आप किसी डेटटाइम में कोई संख्या जोड़ते हैं, तो उसे दिनों में गिना जाता है।
Time
लीप सेकंड की कोई अवधारणा नहीं है, इसलिए यह इससे अलग नहीं है DateTime
। मुझे नहीं पता कि आपने अपने उदाहरण कहां से चलाए, लेकिन मैंने Time.new(2012,6,30,23,59,60,0)
2.0 से 2.7 तक के अलग-अलग रूबी संस्करणों में कोशिश की और हमेशा मिला 2012-07-01 00:00:00 +0000
।
Time
लीप सेकंड का समर्थन करता है या नहीं यह आपके OS और टाइमज़ोन कॉन्फ़िगरेशन पर निर्भर करता है। उदाहरण के लिए: TZ=right/UTC ruby -e 'p Time.new(2012,6,30,23,59,60,0)'
=> 2012-06-30 23:59:60 +0000
जबकि TZ=UTC ruby -e 'p Time.new(2012,6,30,23,59,60,0)'
=> 2012-07-01 00:00:00 +0000
।
मुझे लगता है कि रूबी मानक पुस्तकालयों में इस सवाल का दुर्भाग्यपूर्ण आम जवाब में से एक "क्या अंतर है": दो वर्गों / कामों को अलग-अलग लोगों द्वारा अलग-अलग समय पर अलग-अलग तरीके से बनाया गया था। यह जावा जैसी किसी चीज़ के सावधानीपूर्वक नियोजित विकास की तुलना में रूबी के विकास की सामुदायिक प्रकृति के दुर्भाग्यपूर्ण परिणामों में से एक है। डेवलपर्स नई कार्यक्षमता चाहते हैं, लेकिन मौजूदा एपीआई पर कदम नहीं उठाना चाहते हैं, इसलिए वे सिर्फ एक नया वर्ग बनाते हैं - अंतिम उपयोगकर्ता के लिए दोनों के अस्तित्व के लिए कोई स्पष्ट कारण नहीं है।
यह सामान्य रूप से सॉफ़्टवेयर पुस्तकालयों के लिए सच है: अक्सर इसका कारण कुछ कोड या एपीआई होता है, जो तार्किक होने के बजाय ऐतिहासिक होता है।
प्रलोभन DateTime के साथ शुरू करना है क्योंकि यह अधिक सामान्य लगता है। दिनांक ... और समय, सही? गलत। समय भी तारीखों को बेहतर बनाता है, और वास्तव में टाइमज़ोन को पार्स कर सकता है जहां डेटटाइम नहीं हो सकता है। साथ ही यह बेहतर प्रदर्शन करता है।
मैं हर जगह समय का उपयोग कर चुका हूं।
हालांकि सुरक्षित होने के लिए, मैं डेटाइम तर्कों के लिए अपने Timey API में पारित होने की अनुमति देता हूं, और या तो रूपांतरित करता हूं। इसके अलावा अगर मुझे पता है कि दोनों में मेरी दिलचस्पी का तरीका है या तो मैं स्वीकार करता हूं, तो इस विधि को मैंने एक्सएमएल (टीवीएसटीवी के लिए) में परिवर्तित करने के लिए लिखा है
# Will take a date time as a string or as a Time or DateTime object and
# format it appropriately for xmtlv.
# For example, the 22nd of August, 2006 at 20 past midnight in the British Summertime
# timezone (i.e. GMT plus one hour for DST) gives: "20060822002000 +0100"
def self.format_date_time(date_time)
if (date_time.respond_to?(:rfc822)) then
return format_time(date_time)
else
time = Time.parse(date_time.to_s)
return format_time(time)
end
end
# Note must use a Time, not a String, nor a DateTime, nor Date.
# see format_date_time for the more general version
def self.format_time(time)
# The timezone feature of DateTime doesn't work with parsed times for some reason
# and the timezone of Time is verbose like "GMT Daylight Saving Time", so the only
# way I've discovered of getting the timezone in the form "+0100" is to use
# Time.rfc822 and look at the last five chars
return "#{time.strftime( '%Y%m%d%H%M%S' )} #{time.rfc822[-5..-1]}"
end
Time.new(2011, 11, 1, 10, 30)
पैदा करता है 2011-11-01 10:30:00 +0700
, जबकि DateTime.new(2011, 11, 1, 10, 30)
उत्पादन करता है Tue, 01 Nov 2011 10:30:00 +0000
।
मैंने पाया कि अलग-अलग टाइमज़ोन में एक दिन की शुरुआत / अंत की गणना और गणना करने जैसी चीजें डेटाइम के साथ करना आसान है, यह मानते हुए कि आप ActiveSupport एक्सटेंशन का उपयोग कर रहे हैं ।
मेरे मामले में मुझे उपयोगकर्ता के स्थानीय समय के आधार पर उपयोगकर्ता के टाइमज़ोन (मनमानी) में दिन के अंत की गणना करने की आवश्यकता थी जो मुझे एक स्ट्रिंग के रूप में मिली, जैसे "2012-10-10 10:10 +0300"
डेटटाइम के साथ यह उतना ही सरल है
irb(main):034:0> DateTime.parse('2012-10-10 10:10 +0300').end_of_day
=> Wed, 10 Oct 2012 23:59:59 +0300
# it preserved the timezone +0300
अब समय के साथ इसे उसी तरह आजमाते हैं:
irb(main):035:0> Time.parse('2012-10-10 10:10 +0300').end_of_day
=> 2012-10-10 23:59:59 +0000
# the timezone got changed to the server's default UTC (+0000),
# which is not what we want to see here.
वास्तव में, समय को पार्स करने से पहले टाइमजोन को जानने की जरूरत है (यह भी नोट करें Time.zone.parse
, नहीं Time.parse
):
irb(main):044:0> Time.zone = 'EET'
=> "EET"
irb(main):045:0> Time.zone.parse('2012-10-10 10:10 +0300').end_of_day
=> Wed, 10 Oct 2012 23:59:59 EEST +03:00
तो, इस मामले में डेटाइम के साथ जाना निश्चित रूप से आसान है।
DateTime.parse('2014-03-30 01:00:00 +0100').end_of_day
पैदा करता है Sun, 30 Mar 2014 23:59:59 +0100
, लेकिन Time.zone = 'CET'; Time.zone.parse('2014-03-30 01:00:00').end_of_day
पैदा करता है Sun, 30 Mar 2014 23:59:59 CEST +02:00
(CET = + 01: 00, CEST = + 02: 00 - सूचना ऑफ़सेट परिवर्तित)। लेकिन ऐसा करने के लिए, आपको उपयोगकर्ता के टाइमज़ोन पर अधिक जानकारी चाहिए (न केवल ऑफसेट बल्कि यह भी कि बचत समय का उपयोग किया जाता है)।
Time.zone.parse
है बहुत उपयोगी होता है जब विभिन्न क्षेत्रों के साथ बार पार्स करने - यह आप जो क्षेत्र के बारे में आप का उपयोग करना चाहिए सोचने के लिए बाध्य करती है। कभी-कभी Time.find_zone और भी बेहतर काम करता है।
DateTime
ने उस ऑफसेट को पार्स किया जो आपने दिया था, जो कि +0100 था। आपने Time
एक ऑफसेट नहीं दिया , लेकिन एक टाइमज़ोन ("सीईटी" एक ऑफसेट का वर्णन नहीं करता है, यह एक टाइमज़ोन का नाम है)। Timezones में पूरे वर्ष अलग-अलग ऑफसेट हो सकते हैं, लेकिन एक ऑफसेट एक ऑफसेट है और यह हमेशा एक जैसा होता है।
विचार करें कि वे कस्टम तात्कालिकता के साथ टाइमज़ोन को अलग तरह से कैसे संभालते हैं:
irb(main):001:0> Time.new(2016,9,1)
=> 2016-09-01 00:00:00 -0400
irb(main):002:0> DateTime.new(2016,9,1)
=> Thu, 01 Sep 2016 00:00:00 +0000
irb(main):003:0> Time.new(2016,9,1).to_i
=> 1472702400
irb(main):004:0> DateTime.new(2016,9,1).to_i
=> 1472688000
समय सीमा आदि बनाते समय यह मुश्किल हो सकता है।
ऐसा लगता है कि कुछ मामलों में व्यवहार बहुत अलग है:
Time.parse("Ends from 28 Jun 2018 12:00 BST").utc.to_s
"2018-06-28 09:00:00 UTC"
Date.parse("Ends from 28 Jun 2018 12:00 BST").to_time.utc.to_s
"2018-06-27 21:00:00 यूटीसी"
DateTime.parse("Ends from 28 Jun 2018 12:00 BST").to_time.utc.to_s
"2018-06-28 11:00:00 यूटीसी"
Date
(अस्वाभाविक रूप से) केवल खजूर ही खाता है, और जब Date
इसे परिवर्तित किया जाता है Time
, तो यह हमेशा स्थानीय समयक्षेत्र में मध्यरात्रि को समय के रूप में उपयोग करता है। इस तथ्य के बीच का अंतर Time
और TimeDate
उपजी है Time
जो BST को नहीं समझता है, जो आश्चर्य की बात है, यह देखते हुए कि टाइमज़ोन आमतौर पर Time
(उदाहरण के लिए, डेलाइट सेविंग टाइम के संबंध में) द्वारा अधिक सही तरीके से नियंत्रित किया जाता है । तो इस मामले में, केवल DateTime
पूरे स्ट्रिंग को सही ढंग से पार्स करता है।
नील्स गैंसर के जवाब के अलावा आप इस तर्क पर विचार कर सकते हैं:
ध्यान दें कि रूबी स्टाइल गाइड काफी स्पष्ट रूप से इस पर एक स्थिति बताता है:
कोई दिनांक समय नहीं
जब तक आपको ऐतिहासिक कैलेंडर सुधार के लिए खाते की आवश्यकता नहीं है, तब तक डेटटाइम का उपयोग न करें - और यदि आप करते हैं, तो स्पष्ट रूप से अपने इरादों को स्पष्ट रूप से बताने के लिए प्रारंभ तर्क निर्दिष्ट करें।
# bad - uses DateTime for current time DateTime.now # good - uses Time for current time Time.now # bad - uses DateTime for modern date DateTime.iso8601('2016-06-29') # good - uses Date for modern date Date.iso8601('2016-06-29') # good - uses DateTime with start argument for historical date DateTime.iso8601('1751-04-23', Date::ENGLAND)