11
votes

Comment calculer la prochaine journée d'affaires dans les rails?

Comment calculer les jours ouvrables suivants et précédents dans les rails?


4 commentaires

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.


12 Réponses :


0
votes

Eh bien, vous pouvez utiliser quelque chose comme hier = 1.days.ago pour obtenir la date d'hier. Utilisez hier.strfTime ('% w') pour obtenir le jour de la semaine en tant qu'oeur (0 = dimanche 6 = samedi). Si hier est 0 (dimanche), le jour précédent de la semaine serait de 3.days.Ago ... vous avez l'idée.

Et vous pouvez utiliser demain = 1.day.Suite pour obtenir la date de demain.


0 commentaires

22
votes

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  


5 commentaires

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


Je pense que dans votre skip_weekends méthode date.way% 7 est inutile, date.way est toujours entre 0..6 . Donc, cela pourrait être comme pendant [6, 0] .include? (Date.fra) faire


@RKallensee ou vous pouvez utiliser date.way% 6 == 0 . Moins de calcul mais yagni, et plus difficile pour la compréhension




3
votes

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


1 commentaires

Celui-ci est agréable. Je vais y aller avec ça. Merci.



10
votes

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    


0 commentaires

3
votes

Peut-être que cette gemme peut être utile pour vous question

https://github.com/bokmann/business_time

Cela vous permet de calculer les heures et les jours d'activité à partir d'une date donnée


0 commentaires

0
votes

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


0 commentaires

1
votes

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


2 commentaires

N'a pas besoin de retour dans la dernière ligne


Merci @ Piton4eg, raccourci la version courte un peu plus.



8
votes
date = Date.today
date.next_weekday
date.prev_weekday

1 commentaires

Il est malheureux que nous ne l'ayons pas dans un rubis simple :(



0
votes

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


2 commentaires

Y a-t-il un prev_weekday 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



0
votes

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)>


0 commentaires

0
votes

Si vous utilisez des rails, vous pouvez créer une configuration / initialisateurs / date_time.rb xxx

utilisation: xxx


0 commentaires