Jak obliczyć następny i poprzedni dzień roboczy w Rails?Jak obliczyć następny, poprzedni dzień roboczy w Rails?
Odpowiedz
O ile rozumiem, tego właśnie szukasz? (Przetestowane)
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
Można przetestować go w następujący sposób:
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
Jeśli twoja data jest niedziela, powyższe nie działa, a jeśli spróbujesz inkrementacji 7 dni od niedzieli, to w nieskończonej pętli. – DavidNorth
@DavidNorth, działa dobrze. Następny dzień roboczy po niedzieli można uznać za poniedziałek. I wydaje się, że masz tylko przekazać 1 lub -1 do skip_weekends, który jest tylko pomocnikiem dla pozostałych dwóch metod. (Chociaż byłoby lepiej, gdyby sprawdził niepoprawne argumenty zamiast wchodzenia w nieskończoną pętlę.) – antinome
Przekazałem obiekt Time jako argument i zastanawiałem się, jak to trwało więcej niż 1 sekundę, aby uzyskać wynik. Myślę, że lepiej byłoby być wyraźnym, wykonując 'date + = inc.day' –
Cóż, możesz użyć czegoś takiego jak wczoraj = 1.dnia.ago, aby otrzymać wczorajszą datę. Użyj yesterday.strftime ('% w'), aby uzyskać dzień tygodnia jako liczbę całkowitą (0 = niedziela, 6 = sobota). Jeśli wczoraj jest 0 (niedziela), to poprzedni dzień tygodnia będzie 3.days.ago ... wpadniesz na pomysł.
I możesz użyć jutro = 1.dnias. Do, aby otrzymać jutrzejszą datę.
Oto dwa przykłady dotyczące liczby dni roboczych między dwiema datami:
Oto Ruby święta gem:
może trzeba obliczyć dni roboczych w przyszłości począwszy od fr w sobotę lub niedzielę. 1 dzień roboczy po poniedziałku jest we wtorek, 1 dzień roboczy od niedzieli również powinien być wtorek - rozpoczęcie dnia weekendowego należy zignorować. Poniższa osiąga to:
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
Ten jest miły. Pójdę z tym. Dzięki. – juanpastas
Z holidays-gem można również sprawdzić, czy nie jest świętem państwowym. Jeśli to zrobisz, musisz zdefiniować region, którego potrzebujesz. Święto-klejnot umożliwia także używanie subregionów (np. Us-va ...)
Przykładowy kod z niemieckimi (de) i amerykańsko-amerykańskimi (nami) świętami.
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
Uwaga: skip_weekends_and_holidays
nie zwiększa dni roboczych. W przypadku wzrostu o 5 dni od poniedziałku, kończysz w poniedziałek (chyba że ten poniedziałek nie jest dniem wolnym). Jeśli w ciągu 5 dni był urlop, jest dodatkowy przyrost.
Niektóre kod badania:
[
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]}"
}
wyciąg z wynikiem (wigilijnÄ)
====us======
Today: Monday December 24
Next B-day: December 26 - Wednesday
Previous B-day: December 23 - Sunday
Niemcy ma dwa wolne dni (25 + 26,12)
====de======
Today: Monday December 24
Next B-day: December 27 - Thursday
Previous B-day: December 23 - Sunday
Aktualizacja: Zrobiłem kolejną wersję, aby określić multipl e dni roboczych:
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
mojego kodu testu:
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
Zobacz test_2012_12_24_us()
i date.next_business_days(7,...
skończyć w 2013 roku, każdy urlop w okresie jest przestrzegana.
może ten klejnot może być przydatna dla kwestionujesz
https://github.com/bokmann/business_time
To pozwala obliczyć godzin i dni działalności od dnia danego
Tutaj jest szybsza metoda, która używa prostego obliczenia zamiast iterowania w ciągu dni.
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
Metoda dotyczy klasy Czas, ale może być również używana w klasie Data.
Zdaję sobie sprawę, że jest to stary wątek, ale po prostu musiałem rozwiązać ten problem dla siebie i szukałem bardzo krótkiego kodu, który byłby drobiazgowy do modyfikacji, gdyby firma miała dziwne dni otwarcia (np. zamknięta w niedzielę/poniedziałek ").
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
Przypuszczam, że to może być ponownie skrócić do czegoś takiego, ale myślę, że to staje się mniej oczywista
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
nie potrzebują powrotu w ostatniej linii – piton4eg
Dzięki @ piton4eg, skrócono krótszą wersję nieco więcej. –
- 1. Datetime Python - Następny dzień roboczy
- 2. Get Poprzedni dzień
- 3. Szyny: pobierz następny/poprzedni rekord
- 4. Jak uzyskać poprzedni dzień roboczy w ciągu tygodnia z bieżącym dniem roboczym przy użyciu serwera sql
- 5. Zdobądź następny/poprzedni element w ObjectListView
- 6. Jak obliczyć następny piątek w Pythonie?
- 7. Znajdź poprzedni dzień kalendarzowy w Pythonie
- 8. Jak obliczyć ostatni dzień miesiąca w SQL?
- 9. Jp pager z numerami i następny, poprzedni
- 10. Jak wybrać następny i poprzedni Edytuj teksty w widoku
- 11. Jak uzyskać poprzedni i następny miesiąc w kalendarzu
- 12. Oblicz najbliższy dzień roboczy w Postgresie
- 13. Używając polecenia `dzień spełnienia wymogu, aby poprzedni, bieżący i następny miesiąc
- 14. Jak usunąć poprzedni następny przycisk z wirtualnej klawiatury IOS
- 15. Karuzela jQuery. Jak wyświetlić tylko następny lub poprzedni element Tylko
- 16. Usuń przycisk "poprzedni", "następny" i "zrobione" w formularzu HTML
- 17. Jak mogę wybrać "ostatni dzień roboczy miesiąca" w Pandach?
- 18. Poprzedni i Następny przycisk z licznikiem nakładki przy użyciu jQuery
- 19. Jak znaleźć poprzedni i następny rekord za pomocą pojedynczego zapytania w MySQL?
- 20. Railsy: "Następny post" i "Poprzedni post" w moim widoku pokazu, jak?
- 21. Jak uzyskać poprzedni element?
- 22. Implementacja przycisków Poprzedni/Następny tekst w widoku UITableView w celu uczynienia pierwszego respondenta UITextField w niewidocznej komórce
- 23. MySQL - wybierz jeden wiersz - następnie jeden następny i jeden poprzedni względny do wybranego
- 24. Pobierz poprzedni i następny wiersz z wierszy wybranych z (gdzie) warunkach
- 25. Pierwsze następny poniedziałek lub czwartek z moment.js
- 26. Czy istnieje sposób, aby KNP paginator pokaz tylko pokazać następny i poprzedni przyciski
- 27. Jak obliczyć interwał między datetime w MySQL?
- 28. Jak dodać dzień na dzień w Linq do SQL
- 29. Format daty w dzień, dzień miesiąca, rok
- 30. klienta roboczy w Jenkins
są dniami uważana za dzień roboczy? Czy dni robocze to tylko M-F? –
Tylko M-F (święta za dni robocze). , ale jeśli możesz mi filtrować wakacje, które będą niesamowite. –
Czy próbowałeś to zrobić? Powinieneś dodać swoje próby kodowe do swojego pytania. – rogeriopvl