Comment calculer les jours ouvrables suivants et précédents dans les rails? P>
12 Réponses :
Eh bien, vous pouvez utiliser quelque chose comme Et vous pouvez utiliser demain = 1.day.Suite strong> pour obtenir la date de demain. p>
Autant que je sache, c'est ce que vous recherchez? (Testé)
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
Si votre date en question est un dimanche, ce qui précède ne fonctionne pas, et si vous essayez d'incrémenter 7 jours à partir du dimanche, il colle dans une boucle infinie.
@Davidnorth, ça marche bien. Le jour ouvrable suivant après dimanche peut raisonnablement être considéré comme lundi. Et il semble que vous ne soyez que supposé passer 1 ou -1 à Skip_weekends, qui n'est qu'un assistant pour les deux autres méthodes. (Bien que ce soit mieux si cela vérifiait les arguments invalides au lieu d'entrer dans une boucle infinie.)
J'ai passé l'objet de temps comme argument et je me suis demandé comment cela pourrait prendre plus de 1 seconde pour atteindre le résultat. Je pense qu'il serait préférable d'être explicite en faisant date + = inc.day code>
Je pense que dans votre skip_weekends code> méthode date.way% 7 code> est inutile, date.way code> est toujours entre 0..6 code>. Donc, cela pourrait être comme pendant [6, 0] .include? (Date.fra) faire code>
@RKallensee ou vous pouvez utiliser date.way% 6 == 0 code>. Moins de calcul mais yagni, et plus difficile pour la compréhension
Voici deux exemples pour le nombre de jours ouvrables entre deux dates: p>
Voici une gemme de vacances rubis: p>
Vous devrez peut-être calculer des jours ouvrables à l'avenir à partir d'un samedi ou un dimanche. 1 jour ouvrable Après un lundi est le mardi, 1 jour ouvrable d'un dimanche devrait également être mardi - la journée de début du week-end devrait être ignorée. Ce qui suit réalise ceci:
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
Celui-ci est agréable. Je vais y aller avec ça. Merci.
avec le Holidays-Gem Vous pouvez également vérifier, s'il y a des vacances publiques. Si vous le faites, vous devez définir la région dont vous avez besoin. Les vacances-Gem permettent également d'utiliser des sous-régions (par exemple, US-VA ...)
Un exemple de code avec des vacances allemandes (DE) et US-américain (US) (US). P>
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
Peut-être que cette gemme peut être utile pour vous question p>
https://github.com/bokmann/business_time P>
Cela vous permet de calculer les heures et les jours d'activité à partir d'une date donnée p>
Voici une méthode plus rapide qui utilise un calcul simple au lieu d'itération au cours des jours.
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
Je me rends compte que c'est un vieux fil, mais je devais juste travailler celui-ci pour moi et je cherchais un peu de code très court qui était trivial pour modifier si une entreprise avait des jours d'ouverture bizarre (comme "fermé Dimanche / lundi ").
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
N'a pas besoin de retour dans la dernière ligne
Merci @ Piton4eg, raccourci la version courte un peu plus.
date = Date.today date.next_weekday date.prev_weekday
Il est malheureux que nous ne l'ayons pas dans un rubis simple :(
Ceci est la mise en œuvre:
require 'business_time' date = Time.now next_workday(date) private def next_workday(date:) return date = date.next_weekday while date.workday? end
Y a-t-il un prev_weekday code> aussi et fonctionne-t-il exactement de la même manière?
Je ne sais pas, je l'ai utilisé comme ça seulement, je devrais le tester
Ceci est une méthode que j'utilise dans mon script de planification de la production:
# (today is 2019-03-08)
shift_business_days(Time.now, 2)
##=> #<Date: 2019-03-12 ((2458555j,0s,0n),+0s,2299161j)>
shift_business_days('5/20', -10)
##=> #<Date: 2019-05-06 ((2458610j,0s,0n),+0s,2299161j)>
Si vous utilisez des rails, vous pouvez créer une configuration / initialisateurs / date_time.rb utilisation: p>
Les vacances sont-elles considérées comme une journée d'affaires? Les jours ouvrables sont-ils juste m-f?
M-F seulement (jours fériés considérés comme des jours ouvrables). Mais si vous pouvez me donner pour filtrer les vacances qui seront géniales.
Avez-vous essayé de le faire? Vous devriez ajouter vos tentatives de code dans votre question.
Le calcul des jours de vacances est assez compliqué, vous devrez le faire (probablement) par pays. S'il s'agit d'une application financière, vous devrez le faire par échange.