Odejmowanie dat w Ruby (np. 90 dni temu)


89

Trochę mnie rozpieszczało API czasu joda:

DateTime now = new DateTime();
DateTime ninetyDaysAgo = now.minusDays(90);

Próbuję zrobić coś podobnego w Rubim, ale jestem

now = Time.now
ninetyDaysAgo = now - (90*24)

Jednak matematyka jest tutaj wyłączona (naprawdę pracuję z datami o północy).

Czy istnieje przyjazny interfejs API do odejmowania dat?

Odpowiedzi:


105
require 'date'
now = Date.today
ninety_days_ago = (now - 90)

Uruchamiając to przez konsolę IRB otrzymuję:

>>require 'date'
now = Date.today
ninety_days_ago = (now - 90)

require 'date'
=> false
now = Date.today
=> #<Date: 2011-03-02 (4911245/2,0,2299161)>
ninety_days_ago = (now - 90)
=> #<Date: 2010-12-02 (4911065/2,0,2299161)>

Jeśli potrzebujesz czasu, możesz po prostu powiedzieć now = DateTime.now


Twój oryginalny post, przed edycją, był bliżej tego, czego potrzebowałem, ale Date.Now był chroniony. Data. Dzisiaj pracował. Jeśli zmienisz swoją pierwszą notkę tak, aby linia teraz = Date.today, zaakceptuję ją.
darthtrevino

3
@Matt: i jak odjąć 90 godzin zamiast dni?
Esteban Feldman

@EstebanFeldman Datepozwala również na ułamki, więc możesz to zrobić Date.today - (90.0/24.0). Wynik można łatwo przekonwertować to_datetimelub to_timeteż.
jchook

15

Dla tych, którzy używają Railsów, sprawdź:

DateTime.now - 10.days
=> Sat, 04 May 2013 12:12:07 +0300

20.days.ago - 10.days
=> Sun, 14 Apr 2013 09:12:13 UTC +00:00

10

Jeśli używasz Railsów lub nie masz nic przeciwko dołączeniu ActiveSupport, możesz użyć Numeric # days DSL w następujący sposób:

ruby-1.9.2-p136 :002 > Date.today
 => Wed, 02 Mar 2011 
ruby-1.9.2-p136 :003 > Date.today - 90.days
 => Thu, 02 Dec 2010 

Ponieważ pracujesz z datami zamiast godzinami, powinieneś również zacząć od wystąpień Date lub przekonwertować swoje intencje DateTime za pomocą #to_date. Podczas dodawania / odejmowania liczb z wystąpień dat liczby są niejawnie dniami.

ruby-1.9.2-p136 :016 > DateTime.now.to_date
 => #<Date: 2011-03-02 (4911245/2,0,2299161)> 
ruby-1.9.2-p136 :017 > DateTime.now.to_date - 90
 => #<Date: 2010-12-02 (4911065/2,0,2299161)> 

8

Ruby obsługuje arytmetykę dat w klasach Date i DateTime , które są częścią standardowej biblioteki Rubiego. Obie te klasy udostępniają metody # + i # - , które dodają i odejmują dni od daty lub godziny.

$ irb
 > require 'date'
 => true 
 > (DateTime.new(2015,4,1) - 90).to_s  # Apr 1, 2015 - 90 days
 => "2015-01-01T00:00:00+00:00"
 > (DateTime.new(2015,4,1) - 1).to_s   # Apr 1, 2015 - 1 day
 => "2015-03-31T00:00:00+00:00" 

Użyj metod # << i # >> , aby operować na miesiącach zamiast dni. Arytmetyka miesięcy różni się nieco od arytmetyki dni. Użycie Date zamiast DateTime sprawia, że ​​efekt jest bardziej oczywisty.

 > (Date.new(2015, 5, 31) << 3).to_s  # May 31 - 3 months; 92 days diff
 => "2015-02-28" 

Idąc za przykładem czasu joda, możesz napisać coś takiego w Rubim.

now =  DateTime.now
ninety_days_ago = now - 90

a może po prostu

ninety_days_ago = DateTime.now - 90

5

To jest bardzo stary post, ale jeśli chcesz pozostać przy Timeobiekcie, tak jak pierwotnie o to pytano, zamiast przełączać się na Dateobiekt, którego możesz chcieć rozważyć Ruby Facets.

Ruby Facets to ustandaryzowana biblioteka rozszerzeń dla podstawowych klas Rubiego.

http://rubyworks.github.io/facets/

Wymagając Facets, możesz następnie wykonać następujące czynności z obiektami Time.

Time.now.less(90, :days)


Ten projekt nie był aktualizowany od dwóch lat i otworzył problemy jednym komentarzem. Nie żyje.
user4674453

@ user4674453 Ostatnia aktualizacja była sześć miesięcy temu. Jest to stabilna biblioteka, która nadal działa z najnowszą wersją Rubiego. Nie wszystkie bazy kodów muszą być aktualizowane codziennie, aby nie zostały uznane za „martwe”.
bigtunacan


-1

Proste rozwiązanie:

days90_ago = 90.days.ago.to_date.to_s

OUTPUT:
puts 90_days_ago
=> "2019-10-09" # considering cur_date: 2020-01-07

Używa ActiveSupport (Rails).
Espen
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.