¿Cómo calcular días hábiles siguientes y anteriores en Rails?¿Cómo calcular el siguiente día hábil anterior en Rails?
Respuesta
Por lo que yo entiendo, esto es lo que estás buscando? (Probado)
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
puede comprobarlo de la siguiente manera:
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 su fecha en cuestión es un domingo, lo anterior no funciona, y si intenta aumentar 7 días desde el domingo, se mantendrá en un ciclo infinito. – DavidNorth
@DavidNorth, funciona bien. El siguiente día hábil después del domingo se puede considerar razonablemente lunes. Y parece que solo debes pasar 1 o -1 para skip_weekends, que es solo una ayuda para los otros dos métodos. (Aunque sería mejor si buscara argumentos inválidos en lugar de ir a un bucle infinito.) – antinome
Pasé el objeto Time como argumento y me quedé pensando cómo podría llevar más de 1 segundo obtener el resultado. Creo que sería mejor ser explícito haciendo 'date + = inc.day' –
Bueno, puedes usar algo como ayer = 1.days.ago para obtener la fecha de ayer. Use yesterday.strftime ('% w') para obtener el día de la semana como un número entero (0 = domingo, 6 = sábado). Si ayer es 0 (domingo), entonces el día anterior de la semana sería 3.days.ago ... ya entendiste la idea.
Y puede usar tomorrow = 1.days.since para obtener la fecha de mañana.
Aquí hay dos ejemplos para el número de días laborables entre dos fechas:
Aquí está un rubí fiestas joya:
Es posible que necesite para calcular los días laborales en el futuro a partir de fr om un sábado o domingo. 1 día hábil después de que un lunes sea el martes, 1 día hábil a partir de un domingo también debería ser el martes: el día inicial del fin de semana debe ignorarse. El siguiente logra esto:
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
Este es bueno. Iré con esto. Gracias. – juanpastas
Con la holidays-gem también se puede comprobar, si hay un día festivo. Si lo hace, debe definir la región que necesita. La joya de vacaciones también permite el uso de subregiones (por ejemplo, us-va ...)
Un código de ejemplo con vacaciones en Alemania (de) y estadounidense (americano).
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
Obtenga atención: skip_weekends_and_holidays
no incrementa días hábiles. Si aumenta 5 días desde un lunes, termina un lunes (a menos que este lunes no sea feriado). Si hubo vacaciones durante los 5 días, hay un incremento adicional.
Algunos código de prueba:
[
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]}"
}
Un extracto de resultado (Nochebuena):
====us======
Today: Monday December 24
Next B-day: December 26 - Wednesday
Previous B-day: December 23 - Sunday
Alemania tiene dos días libres (25 + 26,12):
====de======
Today: Monday December 24
Next B-day: December 27 - Thursday
Previous B-day: December 23 - Sunday
Actualización: Hice otra versión para determinar multipl e días hábiles:
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
Mi código de prueba:
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
Ver test_2012_12_24_us()
y date.next_business_days(7,...
Se termina en 2013, se respeta cada día de fiesta en el período.
tal vez esta joya puede ser útil para usted pregunta
https://github.com/bokmann/business_time
Esto le permiten calcular las horas y días hábiles a partir de una fecha determinada
Aquí es un método más rápido que utiliza un cálculo simple en vez de iterar durante los días.
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
El método está en el tiempo de la clase pero también se puede usar en la clase Date.
Me doy cuenta de que este es un hilo antiguo, pero tenía que trabajar con esto por mí mismo y estaba buscando un código muy breve que fuera trivial modificar si una empresa tenía días de apertura raros (como " cerrado domingo/lunes ").
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
supongo que podría ser acortado de nuevo para algo como esto, pero creo que resulta menos obvia
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
no necesita devolución en la última línea – piton4eg
Gracias @ piton4eg, acorta la versión corta un poco más. –
- 1. Datetime Python - Siguiente día hábil
- 2. Siguiente día hábil de la fecha especificada en PHP
- 3. Cómo obtener el día hábil anterior en una semana con el día hábil actual utilizando el servidor sql
- 4. ¿Cómo calculo el día hábil anterior en el script de shell ksh?
- 5. MySQL Siguiente/Registro anterior
- 6. fullcalendar siguiente y anterior
- 7. Obtener Día anterior
- 8. Java LinkedList anterior siguiente
- 9. Buscar anterior día natural pitón
- 10. primer día del mes anterior en javascript
- 11. ¿Cómo obtener el mes anterior y el siguiente?
- 12. jQuery Cycle Plugin Anterior/Siguiente
- 13. Calcular el día laborable más cercano en Postgres
- 14. seleccionar siguiente/anterior 10 filas en mysql
- 15. jQuery Carrusel. Cómo mostrar el elemento siguiente o anterior solo
- 16. Obtener el último día del mes anterior en Oracle Función
- 17. Rieles: registro anterior y siguiente de la consulta anterior
- 18. Calcular el último día en el trimestre ACTUAL
- 19. Seleccione el primer día del mes anterior en (DB2) SQL
- 20. flotador siguiente hermano dejó de hermano anterior
- 21. MySQL: seleccionar filas condicionalmente siguiente y anterior
- 22. Retorno Retorno del primer día hábil del mes desde el objeto XTS usando R
- 23. ¿Cómo acceder al elemento anterior/siguiente mientras está en bucle?
- 24. filtro django anterior a día (s)?
- 25. jquery ui datepicker año siguiente y anterior
- 26. Unicode Primero, Anterior, Siguiente y Último
- 27. Jpa paging con números y siguiente, anterior
- 28. SQL: Cómo producir la fecha siguiente dado mes y día
- 29. cómo obtener registros del día anterior usando tsql?
- 30. Obteniendo el modelo siguiente y anterior de una colección
son días de fiesta considerado un día hábil? ¿Los días hábiles son solo M-F? –
M-F solamente (días festivos considerados días hábiles). pero si me puede dar para filtrar las vacaciones que serán increíbles. –
¿Has intentado hacerlo? Debe agregar sus intentos de código en su pregunta. – rogeriopvl