Как рассчитать следующий и предыдущие рабочие дни в Rails?Как рассчитать следующий, предыдущий рабочий день в Rails?
ответ
Насколько я понимаю, это то, что вы ищете? (Тестировал)
require 'date'
def next_business_day(date)
skip_weekends(date, 1)
end
def previous_business_day(date)
skip_weekends(date, -1)
end
def skip_weekends(date, inc)
date += inc
while (date.wday % 7 == 0) or (date.wday % 7 == 6) do
date += inc
end
date
end
Вы можете проверить это следующим образом:
begin
t = Date.new(2009,9,11) #Friday, today
puts "Today: #{Date::DAYNAMES[t.wday]} #{Date::MONTHNAMES[t.mon]} #{t.day}"
nextday = next_business_day(t)
puts "Next B-day: #{Date::MONTHNAMES[nextday.mon]} #{nextday.day}"
previousday = previous_business_day(nextday)
puts "back to previous: #{Date::MONTHNAMES[previousday.mon]} #{previousday.day}"
yesterday = previous_business_day(previousday)
puts "yesterday: #{Date::MONTHNAMES[yesterday.mon]} #{yesterday.day}"
end
Если ваша дата в воскресенье, указанное выше не работает, и если вы попытаетесь увеличить 7 дней с воскресенья, она будет придерживаться бесконечного цикла. – DavidNorth
@DavidNorth, он отлично работает. На следующий рабочий день после воскресенья можно разумно считать понедельник. И кажется, что вы должны только передать 1 или -1 в skip_weekends, что является лишь помощником для двух других методов. (Хотя было бы лучше, если бы он проверял недействительные аргументы вместо того, чтобы переходить в бесконечный цикл.) – antinome
Я передал объект Time в качестве аргумента, и мне было интересно, как это может занять более 1 секунды, чтобы получить результат. Я думаю, что было бы лучше быть явным, делая «date + = inc.day» –
Ну, вы можете использовать что-то наподобие вчера = 1.days.ago, чтобы получить вчерашнюю дату. Используйте вчера. Strftime ('% w'), чтобы получить день недели как целое число (0 = воскресенье, 6 = суббота). Если вчера 0 (воскресенье), то в предыдущий день недели будет 3.days.ago ... вы получите эту идею.
И вы можете использовать завтра = 1.days.since, чтобы получить дату завтрашнего дня.
Вот два примера для числа рабочих дней между двумя датами:
Вот Рубин праздники перл:
Вам может понадобиться для расчета рабочих дней в будущем начиная с fr om в субботу или воскресенье. 1 рабочий день после понедельника вторник, 1 рабочий день с воскресенья также должен быть во вторник - начало выходного дня должно быть проигнорировано. Ниже это достигается:
class Date
def business_days_future(inc)
date = skip_weekend
inc.times do
date = date + 1
date = date.skip_weekend
end
date
end
# If date is a saturday or sunday, advance to the following monday
def skip_weekend
if wday == 0
self + 1
elsif wday == 6
self + 2
else
self
end
end
end
Это хорошо. Я пойду с этим. Благодарю. – juanpastas
С holidays-gem вы также можете проверить, если есть государственный праздник. Если вы это сделаете, вы должны определить регион, в котором вы нуждаетесь. Праздник-драгоценный камень позволяет также использовать субрегионы (например, us-va ...)
Пример кода с немецкими (де) и американо-американскими (нами) праздниками.
require 'holidays'
require 'holidays/us'
require 'holidays/de'
class Date
def next_business_day(region=:any)
skip_weekends_and_holidays(1,region)
end
def previous_business_day(region=:any)
skip_weekends_and_holidays(-1,region)
end
def skip_weekends_and_holidays(inc, region = :any)
date = self + inc
while (date.wday == 6 or date.holiday?(region)) do
date += inc
end
date
end
end
Привлеките внимание: skip_weekends_and_holidays
не увеличивает рабочие дни. Если вы увеличиваете 5 дней с понедельника, вы заканчиваете понедельник (если этот понедельник не будет праздником). Если в течение 5 дней был праздник, есть дополнительный прирост.
Некоторые тест-код:
[
Date.new(2012,6,8), #Friday
Date.new(2012,6,10), #Monday
Date.new(2012,6,9), #Sunday
Date.new(2012,12,24), #Christmas eve
Date.new(2012,12,26), #After Christmas
].each{|t|
%w{us de}.each{|region|
puts "====#{region}======"
puts "Today: #{Date::DAYNAMES[t.wday]} #{Date::MONTHNAMES[t.mon]} #{t.day}"
nextday = t.next_business_day(region)
puts "Next B-day: #{Date::MONTHNAMES[nextday.mon]} #{nextday.day} - #{Date::DAYNAMES[nextday.wday]}"
previousday = t.previous_business_day(region)
puts "Previous B-day: #{Date::MONTHNAMES[previousday.mon]} #{previousday.day} - #{Date::DAYNAMES[previousday.wday]}"
}
Выписка из результата (Сочельник):
====us======
Today: Monday December 24
Next B-day: December 26 - Wednesday
Previous B-day: December 23 - Sunday
Германия имеет два свободных дня (25 + 26,12):
====de======
Today: Monday December 24
Next B-day: December 27 - Thursday
Previous B-day: December 23 - Sunday
Обновление: я сделал еще одну версию, чтобы определить множитель е рабочих дней:
require 'holidays'
require 'holidays/us'
#~ require 'holidays/de'
class Date
def next_business_day(region=:any)
next_business_days(1,region)
end
def next_business_days(inc, region=:any)
date = self
inc.times{
date = date.next
while (date.wday == 6 or date.holiday?(region)) do
date = date.next
end
}
date
end
def previous_business_day(region=:any)
previous_business_days(1,region)
end
def previous_business_days(inc, region=:any)
date = self
inc.times{
date = date.prev_day
while (date.wday == 6 or date.holiday?(region)) do
date = date.prev_day
end
}
date
end
end
Мой тестовый код:
require 'test/unit'
class BDay_Test < Test::Unit::TestCase
def test_2012_06_08_us()
date = Date.new(2012, 6, 8)
assert_equal(Date.new(2012, 06, 10), date.next_business_day('us'))
assert_equal(Date.new(2012, 06, 7), date.previous_business_day('us'))
assert_equal(Date.new(2012, 06, 17), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 05, 31), date.previous_business_day(7, 'us'))
end
def test_2012_06_08_de()
date = Date.new(2012, 6, 8)
assert_equal(Date.new(2012, 06, 10), date.next_business_day('de'))
assert_equal(Date.new(2012, 06, 7), date.previous_business_day('de'))
assert_equal(Date.new(2012, 06, 17), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 05, 31), date.previous_business_day(7, 'de'))
end
def test_2012_06_10_us()
date = Date.new(2012, 6, 10)
assert_equal(Date.new(2012, 06, 11), date.next_business_day('us'))
assert_equal(Date.new(2012, 06, 8), date.previous_business_day('us'))
assert_equal(Date.new(2012, 06, 18), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 06, 1), date.previous_business_day(7, 'us'))
end
def test_2012_06_10_de()
date = Date.new(2012, 6, 10)
assert_equal(Date.new(2012, 06, 11), date.next_business_day('de'))
assert_equal(Date.new(2012, 06, 8), date.previous_business_day('de'))
assert_equal(Date.new(2012, 06, 18), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 06, 1), date.previous_business_day(7, 'de'))
end
def test_2012_06_09_us()
date = Date.new(2012, 6, 9)
assert_equal(Date.new(2012, 06, 10), date.next_business_day('us'))
assert_equal(Date.new(2012, 06, 8), date.previous_business_day('us'))
assert_equal(Date.new(2012, 06, 17), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 06, 1), date.previous_business_day(7, 'us'))
end
def test_2012_06_09_de()
date = Date.new(2012, 6, 9)
assert_equal(Date.new(2012, 06, 10), date.next_business_day('de'))
assert_equal(Date.new(2012, 06, 8), date.previous_business_day('de'))
assert_equal(Date.new(2012, 06, 17), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 06, 1), date.previous_business_day(7, 'de'))
end
def test_2012_12_24_us()
date = Date.new(2012, 12, 24)
assert_equal(Date.new(2012, 12, 26), date.next_business_day('us'))
assert_equal(Date.new(2012, 12, 23), date.previous_business_day('us'))
assert_equal(Date.new(2013, 01, 3), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 12, 16), date.previous_business_day(7, 'us'))
end
def test_2012_12_24_de()
date = Date.new(2012, 12, 24)
assert_equal(Date.new(2012, 12, 27), date.next_business_day('de'))
assert_equal(Date.new(2012, 12, 23), date.previous_business_day('de'))
assert_equal(Date.new(2013, 01, 4), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 12, 16), date.previous_business_day(7, 'de'))
end
def test_2012_12_26_us()
date = Date.new(2012, 12, 26)
assert_equal(Date.new(2012, 12, 27), date.next_business_day('us'))
assert_equal(Date.new(2012, 12, 24), date.previous_business_day('us'))
assert_equal(Date.new(2013, 01, 4), date.next_business_days(7, 'us'))
assert_equal(Date.new(2012, 12, 17), date.previous_business_day(7, 'us'))
end
def test_2012_12_26_de()
date = Date.new(2012, 12, 26)
assert_equal(Date.new(2012, 12, 27), date.next_business_day('de'))
assert_equal(Date.new(2012, 12, 24), date.previous_business_day('de'))
assert_equal(Date.new(2013, 01, 4), date.next_business_days(7, 'de'))
assert_equal(Date.new(2012, 12, 17), date.previous_business_day(7, 'de'))
end
end
test_2012_12_24_us()
Смотрите и date.next_business_days(7,...
Вы заканчиваете в 2013 году, каждый праздник в период соблюдается.
может быть, этот драгоценный камень может быть полезен для вас вопрос
https://github.com/bokmann/business_time
Это позволит вам рассчитать часы и дни бизнеса с даты, указанной
Вот быстрый метод, который использует простой расчет вместо итерации в течение дней.
class Time
def shift_weekdays(num_weekdays)
base = self
# corner case: self falls on a Sat or Sun then treat like its the next Monday
case self.wday
when 0
base = self + 1.day
when 6
base = self + 2.day
end
day_of_week = base.wday - 1 # Monday is 0
weekends = (day_of_week + num_weekdays)/5
base + (weekends*2).days + num_weekdays.days
end
end
Метод находится в классе Time, но может использоваться и для класса Date.
Я понимаю, что это старая тема, но мне просто нужно было это сделать для себя, и я искал очень короткую часть кода, которая была тривиальной для изменения, если у бизнеса были странные дни открытия (например, закрыто воскресенье/понедельник ").
def next_business_day(from_day)
workdays = [1,2,3,4,5,6]
test_day = from_day + 1.day
return workdays.include?(test_day.wday) ? test_day : next_business_day(test_day)
end
Я предполагаю, что это может быть снова укорачивается к чему-то вроде этого, но я думаю, что это становится менее заметным
def next_business_day(from_day)
test_day = from_day + 1.day
[1,2,3,4,5,6].include?(test_day.wday) ? test_day : next_business_day(test_day)
end
не нужно возвращать в последней строке – piton4eg
Спасибо @ piton4eg, укоротил короткую версию немного больше. –
- 1. Установить следующий/предыдущий рабочий день
- 2. Получить предыдущий рабочий день
- 3. Как рассчитать предыдущий рабочий день в сценарии оболочки ksh?
- 4. Получить предыдущий рабочий день
- 5. Нужно найти следующий и предыдущий рабочий день в оракула
- 6. Расчет на следующий рабочий день
- 7. Momentjs Следующий рабочий день
- 8. Как найти следующий рабочий день
- 9. Получите пользовательский предыдущий рабочий день в VBA
- 10. Рассчитать ближайший рабочий день в Postgres
- 11. Чтобы найти следующий рабочий день
- 12. Powershell Golf: Следующий рабочий день
- 13. Как получить следующий рабочий день в powershell
- 14. Как рассчитать рабочий день в Дата измерения
- 15. Datetime Python - Следующий рабочий день
- 16. Как найти следующий рабочий день: MATLAB
- 17. Как получить следующий день и предыдущий день определенной даты?
- 18. Javascript следующий и предыдущий день функция
- 19. Google Spreadsheet, находя предыдущий рабочий день
- 20. Angularjs следующий и предыдущий день, год, месяц
- 21. следующий рабочий день даты дате в oracle
- 22. Рассчитать рабочий день в SQL Server
- 23. Требовать предыдущий рабочий день минус праздничные дни
- 24. Получить предыдущий рабочий день с moment.js
- 25. Предыдущий и следующий день, код C
- 26. Улучшить скрипт, чтобы получить предыдущий рабочий день
- 27. Как получить предыдущий рабочий день в команде windows (через powershell)
- 28. Oracle SQL 11g - следующий рабочий день запрос
- 29. Vba Следующий рабочий день Включая праздник
- 30. Дата начала, а на следующий рабочий день:
праздники считается рабочий день? Являются ли рабочие дни только M-F? –
Только M-F (праздники считаются рабочими днями). , но если вы можете дать мне отфильтровать праздники, которые будут потрясающими. –
Вы пытались это сделать? Вы должны добавить свои попытки кода в свой вопрос. – rogeriopvl