Well,

I've been programming for all of about 5 hours in Python now. From first opening my browser and googling the term to making this post here. I've written something up too! It's a short script that accepts input from the user about their date of birth and just prints some statistics about it. Such as their age in days/months/years.

It has some basic error checking though it's nothing serious like checking whether or not the DAY part of the DATE is possible in that MONTH (i.e. so you can get the 31st of February and it will accept it). Though it does make sure you don't make a 13th month.

Please take a look and I'm particularly interested if anyone can tell me alternate ways of doing things that I've done, especially if it's more efficient (or just generally better).

Thanks in advance.

# Filename: age2.py
# Author: Mark Williams

#Do all the module imports first
import datetime

#Just a Def to all up to convert strings to UPPERCASE
def to_upper(string):
    upper_case = ""
    for character in string:
        if 'a' <= character <= 'z':
            location = ord(character) - ord('a')
            new_ascii = location + ord('A')
            character = chr(new_ascii)
        upper_case = upper_case + character
    return upper_case
#End of Def here.

#Next we'll import the date from that module we loaded.
from datetime import date

#And put the date today in a variable
now = date.today()

#Then we'll make a seperate variable for each 'piece'
#of the date for manipulation

#Yeah, YEAR input now with error checking
error_var = 0
while error_var == 0:
	y = int(raw_input('Please enter the YEAR of which you were born:    '))
	if y >= 2009:
		print "Error, you're not born yet! Try again."
	elif y < 0:
		print "Error, no way we're you born BC!"
	else:
		error_var = 1

#Next is Month input with error checking for both integer input
#and for string input.
error_val = 0
while error_val == 0:
	m = raw_input('Please enter the MONTH of which you were born:   ')
	try:
    		dummy = int(m)
	    	#error checking on the input number (as it was given as an integer)
		m = int (m)
		if m < 1 or m > 12:
		    	print "Error? That's not a month!"
	    	else:
		    	error_val = 1
	except:
		m = to_upper(m)[:3]
		#Convert the string version to an integer version
		#Lots of "error_val..." here, might take a look at
		#removing these somehow.
		if m == "JAN":
			m = 1
		elif m == "FEB":
			m = 2
			error_val = 1
		elif m == "MAR":
			m = 3
			error_val = 1
		elif m == "APR":
			m = 4
			error_val = 1
		elif m == "MAY":
			m = 5
			error_val = 1
		elif m == "JUN":
			m = 6
			error_val = 1
		elif m == "JUL":
			m = 7
			error_val = 1
		elif m == "AUG":
			m = 8
			error_val = 1
		elif m == "SEP":
			m = 9
			error_val = 1
		elif m == "OCT":
			m = 10
			error_val = 1
		elif m == "NOV":
			m = 11
			error_val = 1
		elif m == "DEC":
			m = 12
			error_val = 1
		else:
			print "\nError, didn't get which month you meant there either \n\
enter it as an integer (1 to 12) or type the month name out, \n\
either as an abbreviation (Jan, Feb, Mar...) or in \n\
full (January, February...)\n"

#Day input, again with error checking
error_var = 0
while error_var == 0:
	d = int(raw_input('Please enter the DAY on which you were born:     '))
	if d < 1 or d > 32:
		print "Error, what DAY did you say?"
	else:
		error_var = 1

#Added here so as to not double commands
d = int(d)
m = int(m)
y = int(y)

#Put the input-ed date into a single variable
birthday = date(y, m, d)
#Work out the persons age
age = now - birthday
#Convert that to years (allowing for leap years too
years = age.days / 365.25
#Convert it to months also
months = age.days / 12

## Output the data!
print "\nToday, your are:\n\n"
print age.days, " days"
print months, " months"
print "or"
print int(years), " years old!"

#Now just for fun we'll play with some list stuff
#I'll try and make it look neat and 'readable' too.
a = [\
'January',\
'February',\
'March',\
'April',\
'May',\
'June',\
'July',\
'August',\
'September',\
'October',\
'November',\
'December']
#Prepare 'm' for 'a'
m = m - 1
#Add the 'st', 'nd', 'rd' or 'th' bit to the day!
if d == 1 or d == 21 or d == 31:
	d = str(d) + 'st'
elif d == 2 or d == 22 or d == 32:
	d = str(d) + 'nd'
elif d == 3 or d == 23:
	d = str(d) + 'rd'
elif d > 3 and d <= 20 or d >23 and d <= 30:
	d = str(d) + 'th'
print "\n\nAlso I can tell you that you were born on: ", d, a[m], y
#That's all folks!

Nice job! Here's a nitpicky critique -- take it as a compliment to your obvious talent at picking up a language in short order.

Am I correct in thinking that your background is in C?

(1) no '\' is needed after ','. Python accepts a comma as a line continuation character.

(2) the function to_upper() is correct, but also unnecessary. Python strings have a built-in method .upper() that does exactly the same (but faster, being in C).

(3) In general, modules should be imported at the top of the program.

(4) The error-checking can be done more concisely (and correctly -- you don't catch non-integer inputs) like this:

while True:
    try:
       year = int(raw_input("What year were you born? "))
   except:
       print "enter an integer, please!"
       continue
   if year < 0: 
       print "Impossible!  You weren't born BC!"
   elif year > now.year:  # << Note dynamic checking!
      print "Impossible!  You aren't born in the future!"
   else:
      break

(5) the month-getting code should be shoved into a function for clarity. And, it can take advantage of Python's advanced structures:

def get_month():
   months = ["JAN","FEB","MAR",etc.]
   while True:
       month = raw_input("What month were you born? ")
       month = month[:3].upper()
       if month in months:
          return months.index(month) + 1
       else:
          try:
              month = int(month)
              if 0 < month < 13:
                   return month
              else:
                   print "invalid month!"
                   continue
          except:
               print "invalid month!"

This takes the place of the long if ... elif chain.

(6) Python really does include all the batteries. The datetime module can do all of this in one fell swoop:

def extract_date(s):
    try:
        date = datetime.datetime.strptime(s, "%d %m %Y")
    except:
        try:
            date = datetime.datetime.strptime(s, "%d %b %Y")
	except:
	    return None
    return date

while True:
   year = raw_input("What year were you born? ")
   month = raw_input("What month were you born? ")
   day = raw_input("What day were you born? ")
   bday = extract_date(day + " " + month[:3].title() + " "+ year)
   if bday == None:
      print "Illegal info!"
      continue
   else:
      break

Again, take all of these as incentive to keep learning; your original code is good.

Jeff

Haha, you're right on the money there.
I did used to play around with C back when I was a windows user.
Now that I'm 100% Linux I sort of just...stopped. I guess that's why I'm here now, I miss playing around with coding.

I did see the built-in method upper, though I guess I didn't look close enough.

Also, I definitely like the

elif year > now.year: # << Note dynamic checking!

I feel daft for not doing that myself!

The rest is good thanks, it's exactly what I was after. My code worked but it was plain to see that it wasn't beautiful! Haha.

I'll add your comments to my source and carry on with a little more python today.


Thanks a lot!

Jeff, thanks for the idea. I was just working on a project that needed a secure date input. This what I came up with:

# a more secure way to enter a date

import datetime as dt

def enter_date():
    """
    asks to enter year, month and day and returns
    date info as <type 'datetime.datetime'>
    """
    def extract_date(s):
        try:
            # month given as a decimal number
            date = dt.datetime.strptime(s, "%d %m %Y")
        except:
            try:
                # month given as a 3 letter abreviation
                date = dt.datetime.strptime(s, "%d %b %Y")
            except:
                return None
        return date

    while True:
        year = raw_input("Enter year (eg. 1979): ")
        # you can enter number of month, full name or 3 letter abbreviation
        month = raw_input("Enter month (eg. 9 or sep): ")
        day = raw_input("Enter the day of the month: ")
        date = extract_date(day + " " + month[:3].title() + " " + year)
        if date == None:
            print "Illegal info!"
            continue
        else:
            return date


date = enter_date()

# testing ...
#print date, type(date)           # 2001-09-11 00:00:00 <type 'datetime.datetime'>
#print date.strftime("%m/%d/%Y")  # 09/11/2001
#print date.strftime("%d%b%Y")    # 11Sep2001

# do something with it ...
today = dt.datetime.today()
age = today - date
# assumes week starts with Monday
weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
week_day = weekdays[dt.date.weekday(date)]
print "Today is %s" % today.strftime("%d%b%Y")
print "%s was %d days ago on a %s" % (date.strftime("%d%b%Y"), age.days, week_day)

"""
my output -->
Enter year (eg. 1979): 2001
Enter month (eg. 9 or sep): september
Enter the day of the month: 11
Today is 03Mar2008
11Sep2001 was 2365 days ago on a Tuesday
"""
This article has been dead for over six months. Start a new discussion instead.