2

I'm currently unsure on the logic to be used for the below problem and new to programming as well.(Currently learning python)

Trying to iterate thru every date for a given month - say 05/01 -- 05/31 and print it out in the below format.

enter image description here

Monday thru Friday dates are to be printed separately. Saturday & Sunday dates are to be printed separately.

If the month starts on say Friday - 05/01/2020, ouput should be like enter image description here as, its the last weekday of that week.

For the month of April 2020, output would be like below, as April month's 1st week started on Wednesday.

enter image description here

I managed to comeup with the below try, but not sure how to proceed further.

import sys
from datetime import date, datetime, timedelta

year = int(sys.argv[1])
month = int(sys.argv[2])
st_dt = int(sys.argv[3])
en_dt = int(sys.argv[4])

first_date = datetime(year, month, st_dt).date()
get_first_day = datetime(year, month, st_dt).isoweekday()

def daterange(startDate, endDate, delta=timedelta(days=1)):
    currentDate = startDate
    while currentDate <= endDate:
        yield currentDate
        currentDate += delta

for date in daterange(date(year, month, st_dt), date(year, month, en_dt), delta=timedelta(days=1)):
     print(date)


  date.py 2020 5 1 31 # script

Came up with a standalone 'if loop' and as i said before, not sure how to construct the bigger picture :(

if get_first_day == 1:
        #print("Monday")
        sec_d =  first_date + timedelta(days=4)
elif get_first_day == 2:
        sec_d = first_date + timedelta(days=3)
elif get_first_day == 3:
        sec_d = first_date + timedelta(days=2)
elif get_first_day == 4:
        sec_d = first_date + timedelta(days=2)
elif get_first_day == 5:
        sec_d = first_date
        #print("Friday")
else:
        pass

print(f"Second date:{sec_d} ") -- which gave  -- > Second date:2020-05-01
Rookie1999
  • 111
  • 1
  • 8

1 Answers1

2

You could keep the dates in a dictionary, dictionary key is tuple of calendar week and type of day (weekend, day of the week).

Each day is saved by in the allDays dictionary, grouped by the combination of weeknum and type of day as key:

 ('18', 'weekend'): [datetime.date(2020, 5, 2), datetime.date(2020, 5, 3)],
 ('18', 'working'): [datetime.date(2020, 5, 1)],
 ('19', 'weekend'): [datetime.date(2020, 5, 9), datetime.date(2020, 5, 10)],
 ('19', 'working'): [datetime.date(2020, 5, 4), ...

So you just need to take out the fist and last item of each dict item:

import sys
from datetime import date, datetime, timedelta

year, month, st_dt, en_dt = 2020, 5, 1, 31

first_date = datetime(year, month, st_dt).date()
get_first_day = datetime(year, month, st_dt).isoweekday()

def daterange(startDate, endDate, delta=timedelta(days=1)):
    currentDate = startDate
    while currentDate <= endDate:
        yield currentDate
        currentDate += delta

allDays = {}
_lastDayType = None
for dte in daterange(date(year, month, st_dt), date(year, month, en_dt), delta=timedelta(days=1)):
    if 0 <= dte.weekday() < 5:
        _dayType = 'working'
    else:
        _dayType = 'weekend'

    _weeknum = dte.strftime("%V")  # number of calendar week
    _key = (_weeknum, _dayType)
    if _key not in allDays:        # create an empty list if unique key doesnt exist
        allDays[_key] = []
    allDays[_key].append(dte)      # add the dates ...

for k,v in allDays.items():
    if len(v) == 1:
        first, last = v[0], v[0]
    else:
        first, last = v[0], v[-1]
    print("%s >> %s" % (first, last))

Output:

2020-05-01 >> 2020-05-01
2020-05-02 >> 2020-05-03
2020-05-04 >> 2020-05-08
2020-05-09 >> 2020-05-10
2020-05-11 >> 2020-05-15
2020-05-16 >> 2020-05-17
2020-05-18 >> 2020-05-22
2020-05-23 >> 2020-05-24
2020-05-25 >> 2020-05-29
2020-05-30 >> 2020-05-31
Maurice Meyer
  • 17,279
  • 4
  • 30
  • 47
  • That was so fast ! :) THanks !!!! I'm kind of lost with the below logic `_weeknum = dte.strftime("%V") _key = (_weeknum, _dayType) if _key not in allDays: allDays[_key] = [] allDays[_key].append(dte)` Could you kindly explain that. – Rookie1999 Jun 03 '20 at 10:54
  • I'm trying to add an addtional functionality to check if a date in the given date range is national holiday, print "NH" and that corresponding date. Ex: 2020-05-04 & 2020-05-14 are national holidays and that date alone should be printed like `NH 5/4/2020 5/4/2020 ...... NH 5/14/2020 5/14/2020` I tried: `ph = [] for d in public_holiday: ph.append(date(year, month, int(d))) ..... for k,v in allDays.items(): week_end = '' gh = '' ........ elif v in ph: print("NH") else: first, last = v[0], v[-1]` – Rookie1999 Jun 03 '20 at 14:53
  • SHould I raise it a separate question – Rookie1999 Jun 03 '20 at 14:55
  • ph array's ouput is `[datetime.date(2020, 5, 4), datetime.date(2020, 5, 14)]` – Rookie1999 Jun 03 '20 at 14:56
  • Yes, make a new question. – Maurice Meyer Jun 03 '20 at 14:57
  • Thanks a ton for your time here :) https://stackoverflow.com/questions/62176391/check-list-item-is-present-in-dictionary – Rookie1999 Jun 03 '20 at 15:15
  • Tried multiple options nothing worked. Am i using the data type incorrectly ? https://stackoverflow.com/questions/62176391/check-list-item-is-present-in-dictionary – Rookie1999 Jun 03 '20 at 16:10
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/215247/discussion-between-rookie1999-and-maurice-meyer). – Rookie1999 Jun 03 '20 at 16:31