Low commit activity in last 3 years
A long-lived project that still receives updates
A Ruby Library for dealing with business calendar.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

>= 2.0
>= 12.0
~> 3.0
~> 1.60

Runtime

 Project Readme

BusinessDateCalculator

CI

Biblioteca Ruby para cálculos com calendário de dias úteis: identificar feriados, mover datas entre dias úteis, contar dias úteis entre datas e ajustar datas não-úteis para o próximo ou anterior dia útil.

Pensada para casos de uso financeiros (cotização e liquidação de fundos, D+N, dias úteis no calendário ANBIMA/B3), mas sem dependências de feriados específicos — você fornece a lista.

Instalação

Adicione ao Gemfile:

gem 'business_date_calculator', '~> 1.0'

E rode:

bundle install

Ou instale isoladamente:

gem install business_date_calculator

Uso

Criando um calendário

require 'business_date_calculator'

start_date = Date.parse('2024-01-01')
end_date   = Date.parse('2024-12-31')
holidays   = [Date.parse('2024-01-01'), Date.parse('2024-12-25')]

calendar = BusinessDateCalculator::Calendar.new(start_date, end_date, holidays)

O calendário expande automaticamente seu range internamente quando você pergunta por datas fora do intervalo inicial — você não precisa pré-dimensionar.

is_holiday?(date)

Retorna true para fins de semana ou datas na lista de feriados:

calendar.is_holiday?(Date.parse('2024-01-01'))  # => true  (feriado)
calendar.is_holiday?(Date.parse('2024-01-06'))  # => true  (sábado)
calendar.is_holiday?(Date.parse('2024-01-08'))  # => false (segunda)

adjust(date, convention)

Ajusta uma data não-útil para o próximo dia útil (:following) ou anterior (:preceding). Use :unadjusted para devolver a data sem modificar.

calendar.adjust(Date.parse('2024-01-06'), :following)   # => 2024-01-08 (segunda)
calendar.adjust(Date.parse('2024-01-06'), :preceding)   # => 2024-01-05 (sexta)
calendar.adjust(Date.parse('2024-01-08'), :following)   # => 2024-01-08 (já é dia útil)

advance(date, n, convention = :following)

Avança n dias úteis a partir de date. Aceita n negativo para recuar.

calendar.advance(Date.parse('2024-01-08'), 5)    # => 2024-01-15
calendar.advance(Date.parse('2024-01-15'), -3)   # => 2024-01-10
calendar.advance(Date.parse('2024-01-06'), 1)    # => 2024-01-09 (sábado avança para seg + 1)

Se date cai num dia não-útil, ele é ajustado primeiro segundo a convention antes de avançar.

networkdays(date1, date2, convention1 = :unadjusted, convention2 = :unadjusted)

Retorna a contagem de "saltos" entre dias úteis nas duas datas. Equivalente a índice_util(date2) - índice_util(date1):

mon = Date.parse('2024-01-08')
fri = Date.parse('2024-01-12')

calendar.networkdays(mon, fri)  # => 4 (segunda→sexta: 4 saltos)
calendar.networkdays(mon, mon)  # => 0 (mesma data)

Levanta ArgumentError se date1 > date2.

Se as datas passadas não são úteis, especifique convenções de ajuste:

sat = Date.parse('2024-01-06')
fri = Date.parse('2024-01-12')

calendar.networkdays(sat, fri, :following, :unadjusted)  # ajusta sat → mon, depois conta

last_day_of_previous_month(date)

Retorna o último dia útil do mês anterior:

calendar.last_day_of_previous_month(Date.parse('2024-03-15'))
# => 2024-02-29 (sexta — último dia útil de fevereiro)

Thread-safety

Métodos públicos são protegidos por Monitor (reentrante). Múltiplas threads podem chamar métodos da mesma instância concorrentemente sem corrupção de estado durante reconstruções internas.

Marshal / Rails.cache

A classe implementa marshal_dump / marshal_load para funcionar com Rails.cache.fetch e outros consumidores que serializam via Marshal. O Monitor interno é recriado fresh na desserialização.

Desenvolvimento

bundle install
bundle exec rspec          # roda testes
bundle exec rubocop        # lint
bundle exec bundler-audit  # security audit das deps

Release

  1. Atualize lib/business_date_calculator/version.rb
  2. Atualize CHANGELOG.md
  3. bundle exec rake release — cria tag git, faz push e publica no rubygems.org

Contribuindo

  1. Fork
  2. git checkout -b minha-feature
  3. Adicione testes pra mudança (TDD recomendado)
  4. Garanta bundle exec rspec e bundle exec rubocop passando
  5. Pull Request pra master

License

MIT. Veja LICENSE.txt (se ausente, MIT padrão).