1

I can not figure out how to take the year, day and week to return the month. Right now I am just trying to develop a Python Script that will do this. The goal after finishing this script is to use it for a Spark SQL Query to find the month since in my data I am given a day, year and week in each row.

As of now my python code looks like so. This code only works for the statement I have into the print(getmonth(2, 30 ,2018) returning 7. I have tried other dates and the output is only "None". I have tried variables also, but no success there.

import datetime

def month(day, week, year):
    for month in range(1,13):
        try:
            date = datetime.datetime(year, month, day)
        except ValueError:
            iso_year, iso_weeknum, iso_weekday = date.isocalendar()
            if iso_weeknum == week:
                return date.month
print(getmonth(2, 30, 2018))


#iso_(year,weeknum,weekday) are the classes for ISO. Year is 1-9999, weeknum is 0-52 or 53, and weekday is 0-6
#isocaldenar is a tuple (year, week#, weekday)
Travis
  • 657
  • 6
  • 24
  • 1
    Shouldn't it be `def getmonth(day, week, year):` or `print(month(28, 30, 2018))` ? Your code returns `None` for `print(month(28, 30, 2018))` as well. – Luci Jun 16 '17 at 15:01
  • `if` reached only if exception happened, you should move it to `try` block or unindent it by one level – mugiseyebrows Jun 16 '17 at 15:06
  • @Deuce def getmonth( day,week, year) also returns none – Travis Jun 16 '17 at 15:10
  • @Deuce I see. It should be moved as well. There should only be `pass` or `print("error")` in `except` block to satisfy syntax rules. – mugiseyebrows Jun 16 '17 at 15:11
  • I don't understand the input, how is day 28 and week is 30?, week makes sense as it is the 30th week of the year, but the 28 is eluding me – Nick is tired Jun 16 '17 at 15:12
  • @NickA I think that may have been a mistake by me. I was messing with days on a 1-365 base and just forgot to change it back from 0-6 – Travis Jun 16 '17 at 15:21

3 Answers3

0

A simpler solution can be created using the pendulum library. As in your code, loop through month numbers, create dates, compare the weeks for these dates against the desired date. If found halt the loop; if the date is not seen then exit the loop with, say, a -1.

>>> import pendulum
>>> for month in range(1,13):
...     date = pendulum.create(2018, month, 28)
...     if date.week_of_year == 30:
...         break
... else:
...     month = -1
...     
>>> month
7
>>> date
<Pendulum [2018-07-28T00:00:00+00:00]>
Bill Bell
  • 21,021
  • 5
  • 43
  • 58
0

Here is a brute force method that loops through the days of the year (It expects the day as Monday being 0 and Sunday being 6, it also returns the Month 0 indexed, January being 0 and December being 11):

import datetime

def month(day, week, year):
    #Generate list of No of days of the month
    months = [31,28,31,30,31,30,31,31,30,31,30,31]
    if((year % 4 == 0 and year % 100 != 0) or year % 400 == 0): months[1] += 1

    #ISO wk1 of the yr is the first wk with a thursday, otherwise it's wk53 of the previous yr
    currentWeek = 1 if day < 4 else 0

    #The day that the chosen year started on
    currentDay = datetime.datetime(year, 1, 1).weekday()

    #Loop over every day of the year
    for i in range(sum(months)):
        #If the week is correct and day is correct you're done
        if day == currentDay and week == currentWeek:
            return months.index(next(filter(lambda x: x!=0, months)))

        #Otherwise, go to next day of wk/next wk of yr
        currentDay = (currentDay + 1) % 7
        if currentDay == 0:
            currentWeek += 1

        #And decrement counter for current month
        months[months.index(next(filter(lambda x: x!=0, months)))]-=1

print(month(2, 30, 2018)) # 6 i.e. July

months.index(next(filter(lambda x: x!=0, months))) is used to get the first month of that we haven't used all of the days of, i.e. the month you're currently in.

Nick is tired
  • 6,860
  • 20
  • 39
  • 51
0

I don't really understand your questions, but i think datetime will work... sorce: Get date from ISO week number in Python:

>>> from datetime import datetime
>>> day = 28
>>> week = 30
>>> year = 2018
>>> t = datetime.strptime('{}_{}_{}{}'.format(day,week,year,-0), '%d_%W_%Y%w')
>>> t.strftime('%W')
'30'
>>> t.strftime('%m')
'07'
>>>
farax
  • 131
  • 7