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


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.