views:

45

answers:

3

I'm pretty new to Python, so hopefully the problem I'm having has a simple solution.

At work we always us either Shell (ksh) or Perl for all of our scripting work. Since python has been shipped with Solaris for some time now, it has (finally) been given the green light as a scripting platform. I've started prototyping some improvements to our scripts using Python.

What I'm trying to accomplish is taking a time stamp and a string representing a time stamp and creating a datetime object for some date arithmetic.

My example code follows:

#!/bin/python

import datetime

fileTime="201009211100"
format = "YYYYmmdd"

yIdxS = format.find('Y')
yIdxE = format.rfind('Y')

if not fileTime[yIdxS:yIdxE+1].isdigit():
    print "ERROR: Year in wrong format"
    exit
else:
    print "Year [" + fileTime[yIdxS:yIdxE+1] + "]"

mIdxS = format.find('m')
mIdxE = format.rfind('m')

if not fileTime[mIdxS:mIdxE+1].isdigit():
    print "ERROR: Month in wrong format"
    exit
else:
    print "Month [" + fileTime[mIdxS:mIdxE+1] + "]"

dIdxS = format.find('d')
dIdxE = format.rfind('d')

if not fileTime[dIdxS:dIdxE+1].isdigit():
    print "ERROR: Day in wrong format"
    exit
else:
    print "Day [" + fileTime[dIdxS:dIdxE+1] + "]"


old = datetime.date( fileTime[yIdxS:yIdxE+1], \
                     fileTime[mIdxS:mIdxE+1], \
                     fileTime[dIdxS:dIdxE+1] );

I'm getting the following output/error:

Year [2010]
Month [09]
Day [21]
Traceback (most recent call last):
  File "./example.py", line 37, in <module>
    fileTime[dIdxS:dIdxE+1] );
TypeError: an integer is required

I don't understand why I'm getting this TypeError exception. My understanding of Python's dynamic typing is that I shouldn't need to convert a string to an integer if the string is all digits.

So the problem would seem to be I'm either missing something that I need, or my understanding of the language is flawed.

Any help would be greatly appreciated. Thanks.

A: 

Python is more strongly typed; it does not make automatic conversions from strings to integer. The global function int is needed to do the conversion.

Kathy Van Stone
Do you mean atoi?
Gaius
+1  A: 

Strongly consider using datetime.datetime.strptime:

import datetime

tests=["201009211100","201009211199"]
for fileTime in tests:
    try:
        date=datetime.datetime.strptime(fileTime,'%Y%m%d%H%M')
        print(date)
    except ValueError as err:
        print(fileTime,err)

# 2010-09-21 11:00:00
# ('201009211199', ValueError('unconverted data remains: 9',))

Or, if you install the third-party module, dateutil, you could parse it like this:

In [106]: import dateutil.parser as dparser

In [107]: dparser.parse('201009211100')
Out[107]: datetime.datetime(2010, 9, 21, 11, 0)

Notice that dateutil tries to parse the string without you explicitly declaring the format. This has to be used carefully (with testing and control over admissible input strings) since otherwise there are ambiguous dates which dateutil may parse incorrectly.

unutbu
This is definitely the right way to do it - breaking up strings by position is surely one of those things you'd go to Python to get away from
Gaius
Awesome, Thanks! This also works great for all those differently formatted time stamps like YYYY-mm-dd, YYYYmmddHHMM, etc. Which is where I was ultimately heading.
LukeFu
A: 

datetime.date wants integers. Change the last line of your code like this to get your desired results:

old = datetime.date( int(fileTime[yIdxS:yIdxE+1]), \
                 int(fileTime[mIdxS:mIdxE+1]), \
                 int(fileTime[dIdxS:dIdxE+1]) );

However, there's an easier and maybe more pythonic way too:

old = datetime.datetime.strptime(fileTime, '%Y%m%d%H%M')

Doing this at the top of your script, you get the ease of extracting the various pieces like so:

print 'Month: %d' % old.month 
Randy