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"
Andkjaer
la source

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.

Andrew France
la source
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
Lee
la source
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"
Justin Herrick
la source
@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
qui tombe
la source
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
a14m
la source
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.

Yuri Ghensev
la source
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
Dorian
la source
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
Giapnh
la source
-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
Teja
la source
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