¿Cuál sería la forma más eficiente de asignar un horario de 6 días a una semana laboral (excluyendo los fines de semana)? ¿Hay algún algoritmo existente que se adapte a este propósito? El caso de uso sería tomar la fecha actual para realizar una función y generar el día correspondiente.

Por ejemplo:

Hoy, 15/02/2017 sería un día 1. day(2/15/2017) = "Day 1"
Mañana, 2/16 sería un día 2. day(2/16/2017) = "Day 2"
El viernes sería un día 3. day(2/17/2017) = "Day 3"
El lunes sería un día 4. day(2/20/2017) = "Day 4"
etc.

Idealmente, esto se ejecutaría en Python, pero cualquier implementación funcionaría

-1
Sman 16 feb. 2017 a las 05:30

5 respuestas

La mejor respuesta

Puede crear fácilmente un generador que devuelva las fechas a partir de hoy con {{X0} }. Luego, puede filtrar los fines de semana con date.weekday y ajusta el resultado en enumerate a obtener índice para cada día:

from datetime import date, timedelta
from itertools import count
import calendar

WORK_WEEK = 6

today = date.today()

# Generator producing successive dates starting from today
dates = (today + timedelta(days=i) for i in count())

# Generator filtering weekends
work_dates = (d for d in dates if d.weekday() <= calendar.FRIDAY)

for i, d in enumerate(work_dates):
    # Print only 10 first days
    if i == 10: 
        break
    print('{} -> Day {}'.format(d, i % WORK_WEEK + 1))

Salida:

2017-02-16 -> Day 1
2017-02-17 -> Day 2
2017-02-20 -> Day 3
2017-02-21 -> Day 4
2017-02-22 -> Day 5
2017-02-23 -> Day 6
2017-02-24 -> Day 1
2017-02-27 -> Day 2
2017-02-28 -> Day 3
2017-03-01 -> Day 4
2
niemmi 16 feb. 2017 a las 03:01

Dada una fecha que es un "día 1", esto devolverá el número de día programado para cualquier fecha dada:

import datetime

def day_number(day1, target_date):
  days = (target_date - day1).days
  weeks = days // 7
  workdays = weeks * 5
  whole_week = day1 + datetime.timedelta(days=weeks*7)
  for d in range(days % 7):
    day = whole_week + datetime.timedelta(days=d)
    if day.weekday() < 5:
      workdays += 1
  return workdays % 6 + 1
1
trincot 16 feb. 2017 a las 21:38

A juzgar por lo que dijiste en tu problema, no solo quieres el día de la semana, sino cuántos días laborables desde una fecha de inicio. Esta sería mi solución. Esto excluye excepciones extrañas como vacaciones.

from datetime import date


def day(day, month, year):
    # Create starting date, in this case 10th Feb, 2017
    # Let's assume the starting date is a weekday
    startingDate = date(2017, 2, 10)

    # Create ending date based on user input
    endingDate = date(year, month, day)

    # First check if the user input is a weekend
    if endingDate.weekday() == 5 or endingDate.weekday() == 6:
        return "This is not a workday"

    # Calculate the total days in between the two dates
    totalDays = (endingDate - startingDate).days

    #Subtract two days for every weekend
    totalDays -= int(totalDays/7)*2

    return "Day " + str(totalDays)


def main():
    print(day(14, 2, 2017))


main()
0
Sishaar Rao 16 feb. 2017 a las 03:15

Puedes usar momentjs, es una buena biblioteca que te ayuda con calendarios como este

moment().subtract(10, 'days').calendar(); // 02/05/2017
moment().subtract(6, 'days').calendar();  // Last Thursday at 9:06 PM
moment().subtract(3, 'days').calendar();  // Last Sunday at 9:06 PM
moment().subtract(1, 'days').calendar();  // Yesterday at 9:06 PM
moment().calendar();                      // Today at 9:06 PM
moment().add(1, 'days').calendar();       // Tomorrow at 9:06 PM
moment().add(3, 'days').calendar();       // Saturday at 9:06 PM
moment().add(10, 'days').calendar();      // 02/25/2017

También la instalación es muy fácil momento de instalación de bower --save # bower npm momento de instalación --save # npm Install-Package Moment.js # NuGet spm momento de instalación --save # spm meteor add momentjs: moment # meteor

0
diegol 16 feb. 2017 a las 03:08

Si lo entiendo correctamente, puede crear una instancia de un objeto de fecha, luego usar timedelta para agregar los días correspondientes, filtrar los fines de semana, utilizando una lista de comprensión. Además, puede verificar si hoy es parte de un fin de semana o no primero:

import datetime

today = datetime.date.today()

if today.weekday() < 5:  # this if-else ensures today isn't a weekend
    first = today
else:
    delta = 7 - today.weekday() 
    first = today + datetime.timedelta(days=delta)

work_days = [first]
num = 1
while len(work_days) < 6:  # get the next 5 week days, since we have the first already
    curr = first + datetime.timedelta(days=num)
    if curr.weekday() < 5:
        work_days.append(curr)
    num += 1
0
the_constant 16 feb. 2017 a las 03:39