रूबी में व्यक्ति की आयु प्राप्त करें


125

मैं किसी व्यक्ति की उम्र उसके जन्मदिन से प्राप्त करना चाहता हूं। now - birthday / 365काम नहीं करता है, क्योंकि कुछ वर्षों में 366 दिन होते हैं। मैं निम्नलिखित कोड के साथ आया:

now = Date.today
year = now.year - birth_date.year

if (date+year.year) > now
  year = year - 1
end

क्या उम्र की गणना करने का एक और रूबी तरीका है?


6
मुझे यह सवाल पसंद है क्योंकि यह इस विचार को उजागर करता है कि "अधिक रूबी" और "कम रूबी" चीजें करने के तरीके हैं। यह महत्वपूर्ण है कि न केवल तार्किक रूप से सही हो (जो आप सी # उत्तर की प्रतिलिपि बनाकर हो सकते हैं), बल्कि स्टाइलिस्टिक रूप से सही भी हो सकते हैं। और Adinochestva का जवाब रूबी मुहावरे का अच्छा उपयोग करता है।
जेम्स ए। रोसेन

जवाबों:


410

मुझे पता है कि मुझे यहां पार्टी में देर हो रही है, लेकिन 29 फरवरी को एक लीप वर्ष में पैदा होने वाले किसी व्यक्ति की उम्र के साथ काम करने की कोशिश करने पर स्वीकृत उत्तर बुरी तरह से टूट जाएगा। ऐसा इसलिए है क्योंकि कॉल birthday.to_date.change(:year => now.year)अमान्य दिनांक बनाता है।

मैंने इसके बजाय निम्नलिखित कोड का उपयोग किया:

require 'date'

def age(dob)
  now = Time.now.utc.to_date
  now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end

4
इस का प्रयोग करें, चेक-मार्क वाले को नहीं जो छलांग नहीं लगा सकते
bgcode

तुम क्यों लौटते हो 0 || 1 के बजाय true|| false?
0112

1
@ alex0112 क्योंकि उस स्वीकार किए गए भ्रमित स्थिति का परिणाम (0 या 1) अब और जन्मतिथि के बीच के वर्षों में अंतर से घटाया जाता है। यह पता लगाने का इरादा है कि व्यक्ति का इस वर्ष अभी तक जन्मदिन है या नहीं और यदि नहीं, तो वे वर्षों के अंतर की तुलना में 1 वर्ष कम हैं।
दर्शन

2
@andrej अब = Date.today काम करता है लेकिन ध्यान दें कि यह टाइमज़ोन के साथ मुद्दों को नहीं संभालता है। रेल में Date.today सिस्टम टाइमज़ोन के आधार पर एक तारीख देता है। ActiveRecord आपके ऐप्स कॉन्फ़िगर किए गए टाइमज़ोन के आधार पर एक समय देता है। यदि सिस्टम टाइमज़ोन आपके एप्लिकेशन टाइमज़ोन से अलग है, तो आप प्रभावी रूप से दो अलग-अलग टाइमज़ोन से समय की तुलना करेंगे जो बहुत सटीक नहीं होगा।
पसंदीदा ओनवुमेने

क्या यह वास्तव में सबसे सरल उपाय है?
मार्को प्रिन्स

50

मैंने इस समाधान को अच्छी तरह से काम करने और अन्य लोगों के लिए पठनीय पाया है:

    age = Date.today.year - birthday.year
    age -= 1 if Date.today < birthday + age.years #for days before birthday

आसान और आपको लीप वर्ष और इस तरह से निपटने के बारे में चिंता करने की आवश्यकता नहीं है।


3
इसके लिए रेल की आवश्यकता होती है (उम्र के हिसाब से), लेकिन अगर आपको ऐसा कुछ करना है तो रेल की आवश्यकता नहीं है Date.today.month < birthday.month or Date.today.month == birthday.month && Date.today.mday < birthday.mday
चक

आप सही कह रहे हैं - क्षमा करें, मैंने रेल को मान लिया था क्योंकि प्रश्न को इसके साथ टैग किया गया था। लेकिन हाँ, आसानी से केवल रूबी के लिए संशोधित।
पी.जे.

1
मैंने इसे सबसे पहले चुना था क्योंकि यह सबसे सुंदर है, लेकिन उत्पादन में, यह अक्सर गलत है, जिन कारणों से मैं थाह नहीं करता हूं। Time.now.utc.to_date का उपयोग करने वाला ऊपर बेहतर काम कर रहा है।
केविन

@ केविन दिलचस्प। मुझे खुद से कभी कोई समस्या नहीं हुई है लेकिन इसका मतलब यह नहीं है कि कोई भी ऐसा नहीं है। क्या आप मुझे एक विशिष्ट उदाहरण दे सकते हैं? मैं जानना चाहता हूं कि क्या बग है। धन्यवाद।
पी.जे.

2
@sigvei - यह एक विशेषता है, बग नहीं;) अमेरिका सहित अधिकांश देशों में, 28 वें को कानूनी तौर पर आपके जन्मदिन को गैर-लीप वर्ष में माना जाता है यदि आप एक लीप बेबी हैं। व्यक्ति को वास्तव में 10. माना जाएगा
पीजे।

33

इसे इस्तेमाल करो:

def age
  now = Time.now.utc.to_date
  now.year - birthday.year - (birthday.to_date.change(:year => now.year) > now ? 1 : 0)
end

41
यह तब टूटता है जब जन्मदिन ।to_date एक लीप वर्ष है और वर्तमान वर्ष नहीं है। कोई बड़ी घटना नहीं है, लेकिन इससे मुझे परेशानी हो रही है।
दर्शन

1
दार्शनिक के उत्तर को प्रोत्साहित करने के लिए नीचा दिखाना।
निक सोनानेवल्ड

2
दार्शनिक के जवाब को पसंद करने का एक और कारण यह है कि यह सादे पुराने रूबी के साथ काम करता है, जबकि स्वीकृत उत्तर केवल साथ काम करता है rails/activesupport
शेल्डन

16

रूबी ऑन रेल्स (ActiveSupport) में एक लाइनर। लीप वर्ष, लीप सेकंड और सभी संभालती है।

def age(birthday)
  (Time.now.to_s(:number).to_i - birthday.to_time.to_s(:number).to_i)/10e9.to_i
end

यहाँ से तर्क - C # में आयु की गणना करें

मान लें कि दोनों तिथियां एक ही समयक्षेत्र में हैं, यदि दोनों पर utc()पहले फोन नहीं किया to_s()गया है।


1
(Date.today.to_s(:number).to_i - birthday.to_date.to_s(:number).to_i)/1e4.to_iयह भी काम करता है
Hutchins

FWIW, लेकिन फिर "लीप सेकंड" पर मेरी गारंटी अमान्य हो जाएगी। ;-) (एफडब्ल्यूआईडब्ल्यू भाग 2, रूबी वैसे भी "लीप सेकंड" का समर्थन नहीं करता है)। :-)
विक्रांत चौधरी 19

1
मुझे यकीन नहीं है कि मैं इस पर उतर रही हूं। व्याख्या करने के लिए देखभाल, प्रिय downvoters?
विक्रांत चौधरी

@vikrantChaudhary मुझे नहीं पता, यह एक महान जवाब है। परीक्षण किया और काम करता है।
हेक्टर ऑर्डोनेज़

9
(Date.today.strftime('%Y%m%d').to_i - dob.strftime('%Y%m%d').to_i) / 10000

तो यह अनिवार्य रूप से उन दिनों में अंतर की गणना करता है यदि प्रत्येक माह 100 दिन लंबा था, और प्रत्येक वर्ष 100 महीने लंबा था। यदि आपको केवल वर्ष भाग रखने से कोई फर्क नहीं पड़ता है।
जोनाथन एलार्ड

6

अब तक के जवाब थोड़े अजीब हैं। आपका मूल प्रयास ऐसा करने के लिए सही तरीके से बहुत करीब था:

birthday = DateTime.new(1900, 1, 1)
age = (DateTime.now - birthday) / 365.25 # or (1.year / 1.day)

आपको एक आंशिक परिणाम मिलेगा, इसलिए परिणाम को पूर्णांक के साथ बदलने के लिए स्वतंत्र महसूस करें to_i। यह एक बेहतर समाधान है क्योंकि यह घटना के बाद से दिनों (या संबंधित समय वर्ग के मामले में सेकंड) में मापा गया समय अवधि के रूप में तिथि अंतर को सही ढंग से मानता है। फिर एक वर्ष में दिनों की संख्या से एक साधारण विभाजन आपको आयु प्रदान करता है। इस तरह से वर्षों की आयु की गणना करते समय, जब तक आप मूल डीओबी मूल्य को बनाए रखते हैं, तब तक लीप वर्षों के लिए कोई भत्ता देने की आवश्यकता नहीं होती है।


जन्मदिन = Time.mktime (1960,5,5) मुझे सीमा से बाहर (काल की समस्याएं?)
एंड्रयू ग्रिम

हाँ, जाने के युग मुद्दों। मैंने इसे हल करने के लिए उत्तर अपडेट कर दिया है।
बॉब अमन

birthday = DateTime.now - 1.yearमुझे 0. की उम्र देता है। दुर्भाग्य से, 365.25 से विभाजित करना थोड़ा असंभव है।
समीर तलवार

आप डेटाइम ऑब्जेक्ट से 1.year को घटा नहीं सकते। 1. वर्ष में आपकी संख्या सेकंड के अनुसार हो जाती है। डेटटाइम ऑब्जेक्ट्स दिनों के आधार पर काम करते हैं। उदाहरण के लिए: (DateTime.now - 365.25) .strftime ("% D") सटीकता के रूप में, यदि आप वास्तव में सिर्फ जन्मदिन के साथ काम कर रहे हैं, तो यह बहुत सटीक है। इस तथ्य का तथ्य यह है कि लोग पहले से ही उम्र के साथ आते हैं। हम समय पर एक सटीक क्षण में पैदा हुए हैं, लेकिन जब हम अपना DOB लिखते हैं, तो हम आमतौर पर सटीक घंटे, मिनट और हमारे जन्म का दूसरा समय नहीं देते हैं। यहाँ मेरा तर्क यह है कि आप वास्तव में मैन्युअल रूप से यह गणना नहीं करना चाहते हैं।
बॉब अमन

1
यह 1900 से पहले पैदा हुए लोगों के लिए काम नहीं करता है। उदाहरण के लिए गर्ट्रूड बैनेस 2009 में अपने जन्मदिन पर 114.9979 की उम्र के रूप में बताई गई है।
एंड्रयू ग्रिम

6

मेरा सुझाव:

def age(birthday)
    ((Time.now - birthday.to_time)/(60*60*24*365)).floor
end

चाल यह है कि टाइम रिटर्न सेकंड के साथ माइनस ऑपरेशन


यह लगभग सही है। लीप वर्ष का मतलब है कि एक वर्ष वास्तव में 365.25 दिन लंबा है। इसका मतलब यह भी है कि सबसे अच्छा, यह तरीका आपके जन्मदिन में 18 घंटे तक आपकी उम्र नहीं बढ़ा सकता है।
रयान लू

5

मैं यह पसंद है:

now = Date.current
age = now.year - dob.year
age -= 1 if now.yday < dob.yday

अगर आपको लगता है कि यह एक 3yo प्रश्न का एक उचित दावेदार है जिसमें पहले से ही 10 अन्य उत्तर हैं, तो आपको व्यक्तिगत प्राथमिकता से अधिक कारणों को शामिल करना चाहिए। अन्यथा, आपको ज्यादा ध्यान नहीं मिलेगा
जॉन ड्वोरक

1
यह तब टूटता है जब एक वर्ष एक लीप वर्ष होता है और दूसरा नहीं होता है
आर्टमे

अगर अंतिम yr
फेब

5

यह उत्तर सबसे अच्छा है, इसके बजाय इसे बढ़ाएं।


मुझे @ दर्शन का समाधान पसंद है, लेकिन सशर्त बैक्टीरिया हो सकता है। बूलियन अभिव्यक्ति जो करती है उसकी तुलना लेक्सिकोग्राफ़िक क्रम का उपयोग करते हुए [महीने, दिन] जोड़ियों से की जाती है , इसलिए कोई इसके बजाय माणिक की स्ट्रिंग तुलना का उपयोग कर सकता है:

def age(dob)
  now = Date.today
  now.year - dob.year - (now.strftime('%m%d') < dob.strftime('%m%d') ? 1 : 0)
end

1
किस बारे में (Date.today.strftime('%Y%m%d').to_i - dob.strftime('%Y%m%d').to_i) / 10000?
रयान लू

वाह, यह तो बहुत बकवास है। आपको जवाब देना चाहिए और पुरस्कार इकट्ठा करना चाहिए!
आर्टम

हम्म, वास्तव में मैं देख रहा हूं कि यह जवाब मेरा पहले से ही था
आर्टम

ओह, अब मैं भी करता हूँ ... -_- '
रेयान लू

4

यह इस उत्तर का रूपांतरण है (इसे बहुत अधिक वोट प्राप्त हुए हैं):

# convert dates to yyyymmdd format
today = (Date.current.year * 100 + Date.current.month) * 100 + Date.today.day
dob = (dob.year * 100 + dob.month) * 100 + dob.day
# NOTE: could also use `.strftime('%Y%m%d').to_i`

# convert to age in years
years_old = (today - dob) / 10000

यह निश्चित रूप से अपने दृष्टिकोण में अद्वितीय है, लेकिन जब आपको एहसास होता है कि यह क्या करता है:

today = 20140702 # 2 July 2014

# person born this time last year is a 1 year old
years = (today - 20130702) / 10000

# person born a year ago tomorrow is still only 0 years old
years = (today - 20130703) / 10000

# person born today is 0
years = (today - 20140702) / 10000  # person born today is 0 years old

# person born in a leap year (eg. 1984) comparing with non-leap year
years = (20140228 - 19840229) / 10000 # 29 - a full year hasn't yet elapsed even though some leap year babies think it has, technically this is the last day of the previous year
years = (20140301 - 19840229) / 10000 # 30

# person born in a leap year (eg. 1984) comparing with leap year (eg. 2016)
years = (20160229 - 19840229) / 10000 # 32

बस एहसास हुआ कि यह वही
aser है

1

क्योंकि पर रूबी टैग है, dotiw मणि को ओवरराइड करता है रेल निर्मित distance_of_times_in_words और प्रदान करता है distance_of_times_in_words_hash जो उम्र का निर्धारण किया जा सकता है। लीप वर्ष को वर्ष के भाग के लिए ठीक से नियंत्रित किया जाता है, हालांकि यह ध्यान रखें कि 29 फरवरी को उन दिनों वाले हिस्से पर प्रभाव पड़ता है जो यह समझते हैं कि अगर विस्तार के स्तर की आवश्यकता है इसके अलावा, अगर आपको यह पसंद नहीं है कि कैसे dotiv दूरी_of_time_in_words के प्रारूप को बदलता है, तो मूल स्वरूप में वापस आने के लिए: अस्पष्ट विकल्प का उपयोग करें।

Gemfile में dotiw जोड़ें:

gem 'dotiw'

कमांड लाइन पर:

bundle

Date_elper को दूरी_of_time_in_words और दूरी_of_time_in_words_hash तक पहुँच प्राप्त करने के लिए उपयुक्त मॉडल में शामिल करें। इस उदाहरण में मॉडल 'उपयोगकर्ता' है और जन्मदिन का क्षेत्र 'जन्मदिन' है।

class User < ActiveRecord::Base
  include ActionView::Helpers::DateHelper

इस विधि को उसी मॉडल में जोड़ें।

def age
  return nil if self.birthday.nil?
  date_today = Date.today
  age = distance_of_time_in_words_hash(date_today, self.birthday).fetch("years", 0)
  age *= -1 if self.birthday > date_today
  return age
end

उपयोग:

u = User.new("birthday(1i)" => "2011", "birthday(2i)" => "10", "birthday(3i)" => "23")
u.age

1

मेरा मानना ​​है कि यह कार्यात्मक रूप से @ दर्शन के उत्तर के बराबर है, लेकिन IMO अधिक आसानी से समझ में आता है।

class BirthDate
  def initialize(birth_date)
    @birth_date = birth_date
    @now = Time.now.utc.to_date
  end

  def time_ago_in_years
    if today_is_before_birthday_in_same_year?
      age_based_on_years - 1
    else
      age_based_on_years
    end
  end

  private

  def age_based_on_years
    @now.year - @birth_date.year
  end

  def today_is_before_birthday_in_same_year?
    (@now.month < @birth_date.month) || ((@now.month == @birth_date.month) && (@now.day < @birth_date.day))
  end
end

उपयोग:

> BirthDate.new(Date.parse('1988-02-29')).time_ago_in_years
 => 31 

0

निम्नलिखित काम करने लगता है (लेकिन अगर इसकी जाँच की गई तो मैं इसकी सराहना करूँगा)।

age = now.year - bday.year
age -= 1 if now.to_a[7] < bday.to_a[7]

0

यदि आप एक या दो दिन की परवाह नहीं करते हैं, तो यह कम और सुंदर आत्म-व्याख्यात्मक होगा।

(Time.now - Time.gm(1986, 1, 27).to_i).year - 1970

0

ठीक है इस बारे में:

def age
  return unless dob
  t = Date.today
  age = t.year - dob.year
  b4bday = t.strftime('%m%d') < dob.strftime('%m%d')
  age - (b4bday ? 1 : 0)
end

यह मान रहा है कि हम रेल का उपयोग कर रहे हैं, ageएक मॉडल पर विधि को बुला रहे हैं , और मॉडल में डेट डेटाबेस कॉलम है dob। यह अन्य उत्तरों से अलग है क्योंकि यह विधि यह निर्धारित करने के लिए तार का उपयोग करती है कि क्या हम इस वर्ष के जन्मदिन से पहले हैं।

उदाहरण के लिए, यदि dob2004/2/28 है और today2014/2/28 है, या ageहोगा । झांकियां और होंगी । हो जाएगा या । अंत में, हम घटा देंगे से और मिल ।2014 - 20041002280229b4bday"0228" < "0229"true1age9

यह दो बार की तुलना करने का सामान्य तरीका होगा।

def age
  return unless dob
  t = Date.today
  age = today.year - dob.year
  b4bday = Date.new(2016, t.month, t.day) < Date.new(2016, dob.month, dob.day)
  age - (b4bday ? 1 : 0)
end

यह वही काम करता है, लेकिन b4bdayलाइन बहुत लंबी है। 2016वर्ष भी अनावश्यक है। शुरुआत में स्ट्रिंग तुलना परिणाम था।

आप यह भी कर सकते हैं

Date::DATE_FORMATS[:md] = '%m%d'

def age
  return unless dob
  t = Date.today
  age = t.year - dob.year
  b4bday = t.to_s(:md) < dob.to_s(:md)
  age - (b4bday ? 1 : 0)
end

यदि आप रेल का उपयोग नहीं कर रहे हैं, तो यह प्रयास करें

def age(dob)
  t = Time.now
  age = t.year - dob.year
  b4bday = t.strftime('%m%d') < dob.strftime('%m%d')
  age - (b4bday ? 1 : 0)
end

👍🏼


बस फिजी, आपका जवाब तार्किक रूप से वही है जो दलनाश का है। उसका जवाब बहुत साफ है और रेल पर भरोसा नहीं करता है।
मानस

@ मंतस फिलनाश ने कहा कि उन्होंने एक रेल परियोजना में उस पद्धति का उपयोग किया। आप टैग में रेल थे। उसकी विधि में खदान की तुलना में दो अधिक हैं। उनकी पद्धति की अंतिम पंक्ति को समझना कठिन है।
क्रूज़ नुन्ज़

क्षमा करें, लेकिन दर्शन का कोड आपकी तुलना में बहुत अधिक साफ है। साथ ही, उसका कोड एक सरल विधि है। तुम्हारा "dob" मान होने पर निर्भर करता है। जो कि नए उपयोगकर्ताओं के लिए स्पष्ट नहीं हो सकता है। और कोड की ज्यादा मदद भी नहीं करता है। हां, आपका अंतिम नमूना इससे छुटकारा दिलाता है। लेकिन फिल्नाश का यह एकदम सही रखना है कि यह सरल-बेवकूफ कोड का टुकड़ा है।
मंटास

0

मुझे लगता है कि यह महीनों की गिनती नहीं करना बेहतर है, क्योंकि आप एक वर्ष का सटीक दिन उपयोग करके प्राप्त कर सकते हैं Time.zone.now.yday

def age
  years  = Time.zone.now.year - birthday.year
  y_days = Time.zone.now.yday - birthday.yday

  y_days < 0 ? years - 1 : years
end

0

इस समाधान की एक भिन्नता के साथ आया था

def age(dob)
    now = Date.today
    age = now.year - dob.year
    age -= 1 if dob > now.years_ago(age)
    age
end

0

डेटहेल्पर का उपयोग केवल वर्ष प्राप्त करने के लिए किया जा सकता है

puts time_ago_in_words '1999-08-22'

लगभग 20 साल


0
  def computed_age
    if birth_date.present?
      current_time.year - birth_date.year - (age_by_bday || check_if_newborn ? 0 : 1)
    else
      age.presence || 0
    end
  end


  private

  def current_time
    Time.now.utc.to_date
  end

  def age_by_bday
    current_time.month > birth_date.month
  end

  def check_if_newborn
    (current_time.month == birth_date.month && current_time.day >= birth_date.day)
  end```

-1
  def birthday(user)
    today = Date.today
    new = user.birthday.to_date.change(:year => today.year)
    user = user.birthday
    if Date.civil_to_jd(today.year, today.month, today.day) >= Date.civil_to_jd(new.year, new.month, new.day)
      age = today.year - user.year
    else
      age = (today.year - user.year) -1
    end
    age
  end


-1

लीप वर्ष के लिए खाते में (और एक्टिविस्पोर्ट उपस्थिति मानकर):

def age
  return unless birthday
  now = Time.now.utc.to_date
  years = now.year - birthday.year
  years - (birthday.years_since(years) > now ? 1 : 0)
end

years_sinceगैर-लीप वर्ष (जब जन्मदिन है 02-29) को ध्यान में रखते हुए तारीख को सही ढंग से संशोधित करेगा ।


-1

यहाँ मेरा समाधान है जो एक विशिष्ट तिथि में आयु की गणना करने की अनुमति देता है:

def age on = Date.today
  (_ = on.year - birthday.year) - (on < birthday.since(_.years) ? 1 : 0)
end

-2

मुझे इससे भी निपटना था, लेकिन महीनों से। रास्ता बहुत जटिल हो गया। सबसे आसान तरीका मैं सोच सकता था:

def month_number(today = Date.today)
  n = 0
  while (dob >> n+1) <= today
    n += 1
  end
  n
end

आप 12 महीनों के साथ भी ऐसा कर सकते हैं:

def age(today = Date.today)
  n = 0
  while (dob >> n+12) <= today
    n += 1
  end
  n
end

यह महीने को बढ़ाने के लिए दिनांक वर्ग का उपयोग करेगा, जो 28 दिनों और लीप वर्ष आदि से निपटेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.