-1

probably a simple fix but i just cant work it out,

Basically this is a little program I made to calculate the hours I've worked in a day in decimal format, (becasuse I have to do it like that for my timesheet for work) works perfectly fine, but I decided to add in a feature where if I enter restart at anytime the whole program restarts.

I tried calling Time within Time but doing that restarts but then finishes the original after starting over. I also tried making a Restart function that calls Time and then call Restart but that didn't work either.

So I wanted to break out of them both and call the program again, is this possible or not?

def Time():
    clear()
    def is_valid_hours():
        while True:
            h=input("Hour: ")
            if h=="restart": return "yes" #this line doesnt work (tried break)
            try:
                h=int(h)
                return h
            except:
                print("Please enter numbers!")
    def is_valid_Minutes():
        while True:
            h=input("Minute: ")
            if h=="restart": return "yes" # this is the other line (break tried)
            try:
                h=int(h)
                return h
            except:
                print("Please enter numbers!")
    print("Please use time in a 24hour clock format when using this calculator")
    print("Please enter arrival time:")
    arrivalTimeHours=is_valid_hours()
    arrivalTimeMinutes=is_valid_Minutes()

    print("Please enter length of lunch break: ")
    lunchBreakHours=is_valid_hours()
    lunchBreakMinutes=is_valid_Minutes()

    print("Please enter desired leave time: ")
    leaveTimeHours=is_valid_hours()
    leaveTimeMinutes=is_valid_Minutes()

    if arrivalTimeHours>0:
        arrivalTimeHours=arrivalTimeHours*60
    arrivalTime=arrivalTimeHours+arrivalTimeMinutes
    if lunchBreakHours>0:
        lunchBreakHours=lunchBreakHours*60
    lunchBreak=lunchBreakHours+lunchBreakMinutes
    if leaveTimeHours>0:
        leaveTimeHours=leaveTimeHours*60
    leaveTime=leaveTimeHours+leaveTimeMinutes

    totalTimeMinutes=leaveTime-(arrivalTime+lunchBreak)
    decimalTime=totalTimeMinutes/60
    print("Your decimal time is "str(decimalTime))
    newTime=input("Would you like to do a new time?: ")
    return newTime.lower()

newTime=Time()
while newTime=="yes" or newTime=="ye" or newTime=="y" or newTime=="yah" or newTime=="yeah" or newTime=="yh":
    newTime=Time()
input("Press enter to close")

EDIT: I did try doing this aswell, it didn't work either.

def Time():
    clear()
    notQuitting=True
    while notQuitting==True:
        def is_valid_hours():
            while True:
                h=input("Hour: ")
                if h=="restart":
                    notQuitting=False
                    return "yes"
                try:
                    h=int(h)
                    return h
                except:
                    print("Please enter numbers!")
        def is_valid_Minutes():
            while True:
                m=input("Minute: ")
                if m=="restart":
                    notQuitting=False
                    return "yes"
                try:
                    m=int(m)
                    return m
                except:
                    print("Please enter numbers!")
         #rest of code
WhatsThePoint
  • 3,395
  • 8
  • 31
  • 53
  • `if h.strip() == 'restart': raise MyException`? – jbndlr Dec 13 '16 at 09:46
  • You're making this more complicated than it needs to be. You don't need nested function definitions for this. Please see [Asking the user for input until they give a valid response](http://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response) – PM 2Ring Dec 13 '16 at 09:50

1 Answers1

1

You can use your own Exceptions for this purpose. Just make sure, that you don't leave them uncaught.

Have a look at this exemplary implementation:

import datetime

class RestartTimeException(Exception): pass # If user requests restart
class StopTimeException(Exception): pass    # If user requests stop

def take_time():
    def read_or_fail(prompt):
        while True: # As long as input is not valid or user does not abort...
            try:
                i = input(prompt).strip()
                if i == 'restart': # User wants to restart: raise.
                    raise RestartTimeException
                elif i == 'stop':  # User wants to abort: raise.
                    raise StopTimeException
                # Split input into hours and minutes and parse integer values (validity check)
                return tuple(int(p) for p in i.split(':')) 
            except (TypeError, ValueError):
                # On parsing failure inform user and retry
                print('  - Parsing error; re-requesting value.\n  - (Type \'stop\' to abort or \'restart\' to start over.)')

    # Read arrival time and make datetime object (ignore year, day, month)
    h, m = read_or_fail('> Arrival time (H:M): ')
    arr = datetime.datetime.strptime('{:d}:{:d}'.format(h, m), '%H:%M')

    # Read lunch break duration and make timedelta object
    h, m = read_or_fail('> Lunch duration (H:M): ')
    lun = datetime.timedelta(hours=h, minutes=m)

    # Read leaving time and make datetime object (ignore year, day, month)
    h, m = read_or_fail('> Leaving time (H:M): ')
    dep = datetime.datetime.strptime('{:d}:{:d}'.format(h, m), '%H:%M')

    # Calculate time difference as timedelta
    total = dep - arr - lun
    # Calculate difference in minutes (object only yields seconds)
    return total.seconds / 60.0

if __name__ == '__main__':
    do_new = True
    while do_new: # As long as the user wants to ...
        try:
            mins = take_time() # Get times, calculate difference
            print('  - MINUTES OF WORK: {:.2f}'.format(mins))
            do_new = input('> New calculation? ').strip().lower().startswith('y')
        except RestartTimeException:
            # Catch: User requested restart.
            print('  - Restart requested.')
        except (StopTimeException, BaseException):
            # Catch: User requested stop or hit Ctrl+C.
            try:
                print('  - Stop requested.')
            except KeyboardInterrupt:
                pass # Just for clean exit on BaseException/Ctrl+C
            do_new = False

Example output:

> Arrival time (H:M): 8:17
> Lunch duration (H:M): as
  - Parsing error; re-requesting value.
  - (Type 'stop' to abort or 'restart' to start over.)
> Lunch duration (H:M): 0:37
> Leaving time (H:M): 16:48
  - MINUTES OF WORK: 474.00
> New calculation? n
jbndlr
  • 4,965
  • 2
  • 21
  • 31