Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Dates and Times in Python (2014) Let's Build a Timed Quiz App Harder Time Machine

Vic A
Vic A
5,452 Points

Why won't this pass?!

i don't understand why this is an invalid keyword argument. Need help

time_machine.py
import datetime

starter = datetime.datetime(2015, 10, 21, 16, 29)

# Remember, you can't set "years" on a timedelta!
# Consider a year to be 365 days.

## Example
# time_machine(5, "minutes") => datetime(2015, 10, 21, 16, 34)
def time_machine(intx, y):
    timesy = ['months', 'days', 'hours', 'minutes']
    if y.lower() in timesy:  
        tde = starter + datetime.timedelta(y=intx)
    elif y.lower() == 'years':
        tde = starter + datetime.timedelta(days = (intx * 365))
    else:
        print("Invalid input...")

    return (tde - starter).y

3 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,441 Points

There are two areas to clean up:

  • The return statement should be a simple return tde. The goal is to return a new datetime object with the timedelta added in. The variable tde has this already. The trailing .y seems like a typo.
  • The assigning of the arguments to timedelta is a bit trickier. If you wish to do it in one variable filled command, then you need to expand y to it's value before it's interpreted as an keyword. Otherwise, keywords are taken literally as the string name of the keyword and they are not converted to the value the variable of the same name is pointing at. That is, "y" stays "y" and not the value of y.

One trick is to use keyword expansion ** before a dictionary containing the variable keyword and the variable value. The double-asterisk will change **{y:intx} to (value_of_y=value_of_intx) in an argument list.

  • The else: ... print() statements isn't needed for the challenge, but it good to see you covering the boundary cases. Nice!
Vic A
Vic A
5,452 Points

"I don't understand what you mean by "expand y to its value before it's interpreted as a keyword."

Chris Freeman
Chris Freeman
Treehouse Moderator 68,441 Points

The nuance is differentiating between the string "y" and the variable named y.

In the context of an argument list, the code y=intx will be parsed as "y" being the literal string name of a keyword parameter and not a variable. That is, there is no connection between the "y" and the variable y assigned in the functions signature parameter assignment.

The the literal "y" needs to be forced to be interpreted as the variable y and then it needs to be replaced with the value it points to before it is interpreted as the literal keyword argument to timedelta. By using the double-asterisk expansion, "y=intx" gets expanded to "month=intx_value" before it is used as the timedelta argument.

I hope that's clearer. It kind of sounds like I just repeated what was said earlier. Keep asking if you need more details!!

Vic A
Vic A
5,452 Points

No, i understand now thanks. I can tell your on a whole nother level than me but I'll get there :)