web-dev-qa-db-fra.com

Itération entre deux DateTimes, avec un pas d'une heure

Je cherche un moyen efficace, dans Ruby 1.9.x/Rails 3.2.x, d’itérer une itération entre deux objets DateTime, avec un pas d’une heure.

('2013-01-01'.to_datetime .. '2013-02-01'.to_datetime).step(1.hour) do |date|
   ...
end

Je comprends qu’un problème avec cela est que 1.hour n’est que le nombre de secondes, mais mes tentatives pour convertir cela en objet DateTime et l’utiliser comme étape ne fonctionnent pas non plus.

J'ai regardé " Méfiez-vous de Ruby Sugar ". Près du bas, il est mentionné que DateTime a une méthode directe step. Je l'ai confirmé en exécutant methods sur un objet DateTime, mais je ne trouve aucune documentation sur step dans DateTime, dans les documents de Ruby's ou de Rails.

29
Brian

Similaire à ma réponse dans " Comment renvoyer un tableau de jours et d'heures d'une plage? ", l'astuce consiste à utiliser to_i pour travailler avec des secondes depuis l'époque:

('2013-01-01'.to_datetime.to_i .. '2013-02-01'.to_datetime.to_i).step(1.hour) do |date|
  puts Time.at(date)
end

Notez que Time.at() effectue la conversion en utilisant votre fuseau horaire local. Vous pouvez donc spécifier le temps universel coordonné à l'aide de Time.at(date).utc.

52
Alistair A. Israel

Peut-être tard, mais vous pouvez le faire sans Rails, par exemple pour avancer avec les heures:

Ruby 2.1.0

require 'time' 

hour_step = (1.to_f/24)

date_time = DateTime.new(2015,4,1,00,00)
date_time_limit = DateTime.new(2015,4,1,6,00)

date_time.step(date_time_limit,hour_step).each{|e| puts e}

2015-04-01T00:00:00+00:00
2015-04-01T01:00:00+00:00
2015-04-01T02:00:00+00:00
2015-04-01T03:00:00+00:00
2015-04-01T04:00:00+00:00
2015-04-01T05:00:00+00:00
2015-04-01T06:00:00+00:00

Ou minutes:

#one_minute_step = (1.to_f/24/60)

fifteen_minutes_step = (1.to_f/24/4)

date_time = DateTime.new(2015,4,1,00,00)
date_time_limit = DateTime.new(2015,4,1,00,59)

date_time.step(date_time_limit,fifteen_minutes_step).each{|e| puts e}

2015-04-01T00:00:00+00:00
2015-04-01T00:15:00+00:00
2015-04-01T00:30:00+00:00
2015-04-01T00:45:00+00:00

J'espère que ça aide.

10
Juan Matias

Voici quelque chose que je suis venu récemment avec:

require 'active_support/all'

def enumerate_hours(start, end_)
  Enumerator.new { |y| loop { y.yield start; start += 1.hour } }.take_while { |d| d < end_ }
end

enumerate_hours(DateTime.now.utc, DateTime.now.utc + 1.day)
# returns [Wed, 20 Aug 2014 21:40:46 +0000, Wed, 20 Aug 2014 22:40:46 +0000, Wed, 20 Aug 2014 23:40:46 +0000, Thu, 21 Aug 2014 00:40:46 +0000, Thu, 21 Aug 2014 01:40:46 +0000, Thu, 21 Aug 2014 02:40:46 +0000, Thu, 21 Aug 2014 03:40:46 +0000, Thu, 21 Aug 2014 04:40:46 +0000, Thu, 21 Aug 2014 05:40:46 +0000, Thu, 21 Aug 2014 06:40:46 +0000, Thu, 21 Aug 2014 07:40:46 +0000, Thu, 21 Aug 2014 08:40:46 +0000, Thu, 21 Aug 2014 09:40:46 +0000, Thu, 21 Aug 2014 10:40:46 +0000, Thu, 21 Aug 2014 11:40:46 +0000, Thu, 21 Aug 2014 12:40:46 +0000, Thu, 21 Aug 2014 13:40:46 +0000, Thu, 21 Aug 2014 14:40:46 +0000, Thu, 21 Aug 2014 15:40:46 +0000, Thu, 21 Aug 2014 16:40:46 +0000, Thu, 21 Aug 2014 17:40:46 +0000, Thu, 21 Aug 2014 18:40:46 +0000, Thu, 21 Aug 2014 19:40:46 +0000, Thu, 21 Aug 2014 20:40:46 +0000, Thu, 21 Aug 2014 21:40:46 +0000] 
4
Ian Hummel

Je ne suis pas tout à fait sûr que cela va aider, mais consultez cette page de débordement de pile, la question semble similaire.

calcule la différence de temps en jours, heures et minutes

0
Pinkgriptape92