Chciałbym poznać wiek osoby od daty jej urodzin. now - birthday / 365
nie działa, ponieważ niektóre lata mają 366 dni. Wymyśliłem następujący kod:
now = Date.today
year = now.year - birth_date.year
if (date+year.year) > now
year = year - 1
end
Czy istnieje bardziej rubinowy sposób obliczania wieku?
ruby-on-rails
ruby
Mantas
źródło
źródło
Odpowiedzi:
Wiem, że spóźniłem się na imprezę tutaj, ale przyjęta odpowiedź okropnie się załamie, gdy spróbujesz obliczyć wiek kogoś urodzonego 29 lutego w roku przestępnym. Dzieje się tak, ponieważ wywołanie
birthday.to_date.change(:year => now.year)
tworzy nieprawidłową datę.Zamiast tego użyłem następującego kodu:
źródło
true
||false
?Uważam, że to rozwiązanie działa dobrze i jest czytelne dla innych osób:
Łatwe i nie musisz się martwić o obsługę roku przestępnego i tym podobnych.
źródło
Date.today.month < birthday.month or Date.today.month == birthday.month && Date.today.mday < birthday.mday
.Użyj tego:
źródło
rails/activesupport
.Jedna linijka w Ruby on Rails (ActiveSupport). Obsługuje lata przestępne, sekundy przestępne i inne.
Logika z tego miejsca - Oblicz wiek w C #
Zakładając, że obie daty są w tej samej strefie czasowej, jeśli nie zadzwoń
utc()
wcześniejto_s()
w obu.źródło
(Date.today.to_s(:number).to_i - birthday.to_date.to_s(:number).to_i)/1e4.to_i
też działaźródło
Jak dotąd odpowiedzi są trochę dziwne. Twoja pierwotna próba była bardzo bliska właściwej metody:
Otrzymasz wynik ułamkowy, więc możesz przekonwertować wynik na liczbę całkowitą za pomocą
to_i
. Jest to lepsze rozwiązanie, ponieważ prawidłowo traktuje różnicę dat jako okres mierzony w dniach (lub sekundach w przypadku powiązanej klasy czasu) od zdarzenia. Następnie prosty podział przez liczbę dni w roku podaje wiek. Przy obliczaniu wieku w ten sposób, o ile zachowasz pierwotną wartość DOB, nie ma potrzeby uwzględniania lat przestępnych.źródło
birthday = DateTime.now - 1.year
daje mi wiek 0. Niestety dzielenie przez 365,25 jest trochę nieprecyzyjne.Moja sugestia:
Sztuczka polega na tym, że operacja minus z Time zwraca sekundy
źródło
Podoba mi się ten:
źródło
Ta odpowiedź jest najlepsza, zamiast tego zagłosuj za nią.
Podoba mi się rozwiązanie @ philnash, ale warunek może być zwarty. To wyrażenie boolowskie porównuje pary [miesiąc, dzień] w porządku leksykograficznym , więc zamiast tego można po prostu użyć porównania ciągów ruby'ego:
źródło
(Date.today.strftime('%Y%m%d').to_i - dob.strftime('%Y%m%d').to_i) / 10000
?To jest konwersja tej odpowiedzi (otrzymała dużo głosów):
Jest zdecydowanie wyjątkowy w swoim podejściu, ale ma sens, gdy zdasz sobie sprawę, co robi:
źródło
Ponieważ Ruby on Rails jest otagowany, klejnot dotiw zastępuje wbudowaną w Railsach wartość distance_of_times_in_words i zapewnia distance_of_times_in_words_hash której można użyć do określenia wieku. Lata przestępne są traktowane dobrze w części dotyczącej lat, chociaż należy pamiętać, że 29 lutego ma wpływ na część dni, która gwarantuje zrozumienie, czy taki poziom szczegółowości jest potrzebny. Ponadto, jeśli nie podoba ci się, jak dotiw zmienia format parametru distance_of_time_in_words, użyj opcji: vague, aby powrócić do pierwotnego formatu.
Dodaj dotiw do Gemfile:
W wierszu poleceń:
Uwzględnij DateHelper w odpowiednim modelu, aby uzyskać dostęp do distance_of_time_in_words i distance_of_time_in_words_hash. W tym przykładzie model to „Użytkownik”, a pole daty urodzin to „urodziny”.
Dodaj tę metodę do tego samego modelu.
Stosowanie:
źródło
Uważam, że jest to funkcjonalnie równoważne z odpowiedzią @ philnash, ale IMO jest łatwiejsze do zrozumienia.
Stosowanie:
źródło
Poniższe wydaje się działać (ale byłbym wdzięczny, gdyby został sprawdzony).
źródło
Jeśli nie obchodzi Cię dzień lub dwa, byłoby to krótsze i dość oczywiste.
źródło
Ok co z tym:
Zakładamy, że używamy railsów, wywołując
age
metodę na modelu, a model ma kolumnę bazy danych z datamidob
. Różni się to od innych odpowiedzi, ponieważ ta metoda wykorzystuje ciągi znaków do określenia, czy jesteśmy przed tegorocznymi urodzinami.Na przykład, jeśli
dob
to 2004/2/28, atoday
to 2014/2/28,age
to będzie2014 - 2004
lub10
. Pływaki będą0228
i0229
.b4bday
będzie"0228" < "0229"
lubtrue
. Na koniec odejmiemy1
odage
i otrzymamy9
.Byłby to normalny sposób porównania dwóch razy.
Działa to tak samo, ale
b4bday
linia jest za długa.2016
Roku jest również konieczne. Rezultatem było porównanie ciągów na początku.Ty też możesz to zrobić
Jeśli nie używasz szyn, spróbuj tego
👍🏼
źródło
Myślę, że o wiele lepiej nie liczyć miesięcy, ponieważ możesz uzyskać dokładny dzień w roku, używając
Time.zone.now.yday
.źródło
Pojawił się z odmianą tego rozwiązania w Railsach
źródło
DateHelper może być używany tylko do pobierania lat
źródło
źródło
źródło
źródło
Aby uwzględnić lata przestępne (i zakładając obecność aktywnego wsparcia):
years_since
poprawnie zmodyfikuje datę, aby uwzględnić lata inne niż przestępne (kiedy są urodziny02-29
).źródło
Oto moje rozwiązanie, które pozwala również na obliczenie wieku w określonym dniu:
źródło
Ja też musiałem sobie z tym poradzić, ale od miesięcy. Stało się zbyt skomplikowane. Najprościej przyszło mi do głowy:
Możesz zrobić to samo przez 12 miesięcy:
Spowoduje to użycie klasy Date do zwiększenia miesiąca, który zajmie 28 dni, rok przestępny itp.
źródło