Compter le nombre de jours entre deux dates


151

Comment compter le nombre de jours entre ces deux dates?

start_date = Date.parse "2012-03-02 14:46:21 +0100"
end_date =  Date.parse "2012-04-02 14:46:21 +0200"

Réponses:


209

Avec les classes Date (et DateTime), vous pouvez faire (end_date - start_date).to_ipour obtenir le nombre de jours de différence.


5
@MichaelDurrant Vous faites une supposition injustifiée. L'utilisateur ne précise pas s'il s'agit de chaînes ou non. En fait, comme ils utilisent des Rails, il est fort probable que les dates proviennent d'ActiveRecord qui les convertira automatiquement en objets de date. Le texte donné est également identique à la représentation de l'objet Date, ce qui rend très probable qu'il provienne d'une source native.
Andrew France

84
Cela me donne la différence en secondes PAS en jours avec des rails v3 / 4
2called-chaos

6
Pour autant que je sache, le comportement reste le même dans toutes les versions récentes de Ruby et ActiveSupport, incluant respectivement 2.0 et 4.1.0. Timeles objets renvoient cependant des secondes.
Andrew France

5
pour développer la réponse @ 2called-chaos, pour obtenir les jours dont vous auriez besoin (end_date - start_date) /1.day, ce qui vous donnerait un flottant. Si vous ne vouliez avoir que des journées complètes, vous pouvez utiliser ((end_date - start_date) /1.day) .ceil
David K.

2
@David Sauf que le commentaire de @ 2called-chaos se réfère à tort à des Timeobjets, pas à des Dateobjets. Peut-être pourriez-vous mettre à jour la dénomination dans votre commentaire pour indiquer qu'il ne s'agit pas de dates?
Andrew France

109

En supposant que end_dateet qu'ils start_datesoient tous deux de classe ActiveSupport::TimeWithZonedans Rails, vous pouvez utiliser:

(end_date.to_date - start_date.to_date).to_i

2
S'il s'agit de champs de table, cette réponse est la voie à suivre; au lieu du plus noté ici.
Ben

Ne fonctionne pas pour (Time.zone.now.to_date - 23.hours.ago.to_date).to_i, il donne 1 et devrait être 0
Yuri Ghensev

3
@YuriGhensev, cela dépend du moment où vous exécutez votre exemple de code, par exemple Time.zone.now.to_daterenvoie maintenant "Wed, 15 Nov 2017", tandis que 23.hours.ago.to_daterenvoie "Tue, 14 Nov 2017". La différence en nombre de jours est et doit être de 1, sauf si vous avez exécuté votre code dans l'heure précédant minuit.
lee

35

Rails a des aides intégrées qui pourraient résoudre ce problème pour vous. Une chose à garder à l'esprit est que cela fait partie des Helpers Actionview, donc ils ne seront pas disponibles directement depuis la console.

Essaye ça

<% start_time =  "2012-03-02 14:46:21 +0100" %>
<% end_time   =  "2012-04-02 14:46:21 +0200" %>
<%= distance_of_time_in_words(start_time, end_time)  %>

 "about 1 month"

@MaayanNaveh cela ne devrait pas être le cas lorsque vous avez besoin du nombre réel pour les calculs.
Fedcomp

Cette question est l'un de ces cas où la question elle-même est mieux posée différemment. Si vous suivez les autres réponses ici, vous rencontrerez des cas où parfois vous voulez que des semaines ou des années soient affichées au lieu de jours. Cela devrait vraiment être accepté comme la «bonne» réponse de Rails.
Dylan Pierce

34

J'ai continué à obtenir des résultats en quelques secondes, donc cela a fonctionné pour moi:

(Time.now - self.created_at) / 86400

1
@Epigene 1.dayn'est pas rubycomme OP demandé (dans les balises). C'est Railsou plus spécifique active supportsi created_atc'est fondamentalement une Modelméthode dans Railsso ..
Roko

26

pour obtenir le nombre de jours dans une plage horaire (juste un décompte de tous les jours)

(start_date..end_date).count
(start_date..end_date).to_a.size
#=> 32

pour obtenir le nombre de jours entre 2 dates

(start_date...end_date).count
(start_date...end_date).to_a.size
#=> 31

Merci pour ça @ a14m! M'a donné un moyen de faire des captures de date inclusives et exclusives :)
Kris Boyd

18

Aucune des réponses précédentes (à ce jour) ne donne la différence correcte en jours entre deux dates.

Celui qui se rapproche le plus est celui- . Une réponse complète convertirait to_ipuis diviserait:

(Time.now.to_i - 23.hours.ago.to_i) / 86400
>> 0

(Time.now.to_i - 25.hours.ago.to_i) / 86400
>> 1

(Time.now.to_i - 1.day.ago.to_i) / 86400
>> 1

Dans l'exemple spécifique de la question, il ne faut pas analyser Datesi le temps écoulé est pertinent. Utilisez Time.parseplutôt.


Cela peut ne pas fonctionner comme prévu lorsque les heures traversent une transition DST. Dans ce cas, la durée du jour de transition DST est légitimement inférieure à 24 heures, mais en raison de l'arithmétique des nombres entiers, ce jour ne sera pas du tout reflété.
PinnyM

4

Pour avoir le nombre de jours entiers entre deux dates ( DateTimeobjets):

((end_at - start_at).to_f / 1.day).floor

Même problème d'heure d'été que la réponse donnée par Yuri. L'arithmétique avec le temps n'est jamais aussi simple que prévu :)
PinnyM

0

Pour obtenir le nombre de jours de différence par deux dates:

(start.to_date...end.to_date).count - 1
or 
(end.to_date - start.to_date).to_i

-8
def business_days_between(date1, date2)
  business_days = 0
  date = date2
  while date > date1
   business_days = business_days + 1 unless date.saturday? or date.sunday?
   date = date - 1.day
  end
  business_days
end

3
beaucoup plus facile de soustraire les objets de date.
OpenCoderX

Le PO n'a jamais demandé d'ajuster les jours ouvrables. C'est vraiment compliqué de toute façon.
Nathan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.