Subtração de datas Ruby (por exemplo, 90 dias atrás)

88

Fiquei um pouco estragado pela API Joda-Time de:

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

Estou tentando fazer algo semelhante em Ruby, mas estou

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

No entanto, a matemática está errada aqui (estou realmente trabalhando com datas à meia-noite).

Existe uma API amigável para subtração de datas?

Darthtrevino
fonte

Respostas:

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

Executando isso através do console IRB, recebo:

>>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)>

Se precisar de tempo, você pode apenas dizer now = DateTime.now

Matt
fonte
Sua postagem original, pré-edição, estava mais perto do que eu precisava, mas Date.Now estava protegida. Date.today funcionou. Se você alterar sua primeira sinopse para a linha agora = Date.today, eu aceitarei.
darthtrevino
3
@Matt: e como subtrair 90 horas em vez de dias?
Esteban Feldman
@EstebanFeldman Datetambém permite frações para que você possa fazer Date.today - (90.0/24.0). O resultado pode ser facilmente convertido to_datetimeou to_timetambém.
jchook 01 de
15

Para aqueles que usam Rails, verifique o seguinte:

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
Abdo
fonte
10

Se você estiver usando Rails ou não se importar em incluir ActiveSupport, você pode usar o DSL Numérico # dias como este:

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 

Como você está trabalhando com datas em vez de horas, também deve começar com instâncias de Date ou converter suas intâncias de DateTime com #to_date. Ao adicionar / subtrair números de instâncias de data, os números são implicitamente dias.

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)> 
Gabe Martin-Dempesy
fonte
8

Ruby suporta aritmética de data nas classes Date e DateTime , que fazem parte da biblioteca padrão do Ruby. Ambas as classes expõem os métodos # + e # - , que somam e subtraem dias de uma data ou hora.

$ 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" 

Use os métodos # << e # >> para operar em meses em vez de dias. A aritmética em meses é um pouco diferente da aritmética em dias. Usar Date em vez de DateTime torna o efeito mais óbvio.

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

Seguindo seu exemplo do tempo joda, você pode escrever algo assim em Ruby.

now =  DateTime.now
ninety_days_ago = now - 90

ou talvez apenas

ninety_days_ago = DateTime.now - 90
Mike Sherrill 'Cat Recall'
fonte
5

Este é um post muito antigo, mas se você quiser continuar com um Timeobjeto, como foi pedido originalmente, ao invés de mudar para um Dateobjeto que você pode querer considerar usar Ruby Facets.

Ruby Facets é uma biblioteca padronizada de extensões para as principais classes Ruby.

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

Ao solicitar as Facetas, você pode fazer o seguinte com os objetos Tempo.

Time.now.less(90, :days)

bigtunacan
fonte
Este projeto não é atualizado há dois anos e abriu questões com um único comentário. Está morto.
user4674453
@ user4674453 A última atualização foi há seis meses. É uma biblioteca estável que ainda funciona com a última versão do Ruby. Nem todas as bases de código precisam ser atualizadas diariamente para não serem consideradas "mortas".
bigtunacan
5

use o número de segundos:

Time.now - 90*24*60*60
Rubi
fonte
-1

Solução simples:

days90_ago = 90.days.ago.to_date.to_s

OUTPUT:
puts 90_days_ago
=> "2019-10-09" # considering cur_date: 2020-01-07
Ravistm
fonte
Isso está usando ActiveSupport (Rails).
Espen