Подсчитать количество дней между двумя датами


151

Как посчитать количество дней между этими двумя датами?

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

Ответы:


209

С помощью классов Date (и DateTime) вы можете (end_date - start_date).to_iполучить разницу в количестве дней.


5
@MichaelDurrant Вы делаете необоснованное предположение. Пользователь не указывает, являются ли они строками или нет. Фактически, поскольку они используют Rails, наиболее вероятно, что даты поступают из ActiveRecord, который автоматически приводит их к объектам дат. Данный текст также идентичен представлению объекта Date, поэтому весьма вероятно, что он исходит из собственного источника.
Эндрю Франс

84
Это дает мне разницу в секундах, а НЕ в днях с рельсами v3 / 4
2called-chaos

6
Насколько я могу судить, поведение остается неизменным во всех последних версиях Ruby и ActiveSupport, включая 2.0 и 4.1.0 соответственно. Timeобъекты возвращают секунды, хотя.
Эндрю Франция

5
чтобы расширить ответ @ 2called-chaos, чтобы получить дни, которые вам понадобятся (end_date - start_date) /1.day, что даст вам float. Если вы хотите иметь только полные дни, вы можете использовать ((end_date - start_date) /1.day) .ceil
David K.

2
@David За исключением того, что комментарий @ 2called-chaos по ошибке ссылается на Time объекты, а не Dateобъекты. Возможно, вы могли бы обновить названия в своем комментарии, чтобы отразить, что они не являются датами?
Андрей Франция

109

Предполагая, что end_dateи start_dateоба класса ActiveSupport::TimeWithZoneв Rails, вы можете использовать:

(end_date.to_date - start_date.to_date).to_i

2
Если это связано с полями таблицы, этот ответ - путь; вместо самого рейтингового прямо здесь.
Бен

Не работает (Time.zone.now.to_date - 23.hours.ago.to_date).to_i, он дает 1 и должен быть 0
Юрий Генцев

3
@YuriGhensev, это зависит от того, когда вы запускаете пример кода, например, прямо сейчас Time.zone.now.to_dateвозвращает «ср, 15 ноября 2017», а 23.hours.ago.to_dateвозвращает «вт, 14 ноя 2017». Разница в количестве дней равна и должна быть равна 1, если вы не запускали свой код за час до полуночи.
Ли

35

В Rails есть несколько встроенных помощников, которые могут решить эту проблему за вас. Следует иметь в виду, что это часть помощников Actionview, поэтому они не будут доступны непосредственно из консоли.

Попробуй это

<% 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 не должно быть, когда вам нужно фактическое число для расчетов.
Fedcomp

Этот вопрос является одним из тех случаев, когда сам вопрос лучше задавать иначе. Если вы будете следовать другим ответам здесь, вы столкнетесь с тем, что иногда вам нужны недели или годы вместо дней. Это действительно должно быть принято как «правильный» ответ Rails.
Дилан Пирс

34

Я продолжал получать результаты в секундах, так что это сработало для меня:

(Time.now - self.created_at) / 86400

1
@Epigene 1.dayне rubyсоответствует требованию OP (в тегах). Это Railsили более конкретно, active supportхотя created_atэто в основном Modelметод в Railsтак ..
Роко

26

чтобы получить количество дней во временном интервале (просто подсчет всех дней)

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

чтобы узнать количество дней между двумя датами

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

Спасибо за это @ a14m! Дали мне способ сделать инклюзивные и эксклюзивные съемки даты :)
Крис Бойд

18

Ни один из предыдущих ответов (на эту дату) не дает правильной разницы в днях между двумя датами.

Тот, что ближе всего, - тот, кто готов . Полный ответ преобразовал бы to_iи затем разделил бы:

(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

В конкретном примере вопроса не следует анализировать, имеет Dateли значение прошедшее время. Используйте Time.parseвместо этого.


Это может работать не так, как ожидалось, когда время пересекает переход на летнее время, продвигаясь вперед. В этом случае продолжительность переходного дня в летнее время на законных основаниях составляет менее 24 часов, но из-за целочисленной арифметики этот день не будет отражен вообще.
PinnyM

4

Чтобы иметь количество целых дней между двумя датами ( DateTimeобъектами):

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

Тот же DST вопрос, что и ответ, который дал Юрий. Арифметика со временем никогда не бывает такой простой, как можно было бы ожидать :)
PinnyM

0

Чтобы получить разницу дней по двум датам:

(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
гораздо проще вычесть объекты даты.
OpenCoderX

ОП никогда не спрашивал о корректировке на рабочие дни. В любом случае это действительно запутанно.
Натан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.