Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

parsing month year pairs into datetime

Let's say i have 2 strings 'Jan-2010' and 'Mar-2010' and i want to parse it such that it returns 2 datetime objects: 1-Jan-2010 and 31-Mar-2010 (i.e. the last day).

What would be the best strategy in python? Should i just split the string into tokens or use regular expressions and then use the calendar functions to get say the last day of the month for 'Mar-2010' (getting the first day is trivial, its always 1 in this case unless i wanted the first working day of the month).

Any suggestions? Thanks in advance.

like image 665
Asim Avatar asked Aug 13 '09 18:08

Asim


3 Answers

strptime does the string parsing into dates on your behalf:

def firstofmonth(MmmYyyy):
  return datetime.datetime.strptime(MmmYyyy, '%b-%Y').date()

much better than messing around with tokenization, regexp, &c!-).

To get the date of the last day of the month, you can indeed use the calendar module:

def lastofmonth(MmmYyyy):
  first = firstofmonth(MmmYyyy)
  _, lastday = calendar.monthrange(first.year, first.month)
  return datetime.date(first.year, first.month, lastday)

You could ALMOST do it neatly with datetime alone, e.g., an ALMOST working approach:

def lastofmonth(MmmYyyy):
  first = firstofmonth(MmmYyyy)
  return first.replace(month=first.month+1, day=1
             ) - datetime.timedelta(days=1)

but, alas!, this breaks for December, and the code needed to specialcase December makes the overall approach goofier than calendar affords;-).

like image 107
Alex Martelli Avatar answered Oct 17 '22 23:10

Alex Martelli


I highly recommend using the python timeseries module, which you can download and read about here:

http://pytseries.sourceforge.net/

You should also use the dateutil package for parsing the date string, which you can find here:

http://labix.org/python-dateutil

Then you can do something like this

import datetime
import dateutil.parser
import scikits.timeseries as TS
m1 = TS.Date('M', datetime=dateutil.parser.parse('Jan-2010'))
m2 = TS.Date('M', datetime=dateutil.parser.parse('Mar-2010'))
d1 = m1.asfreq('D', relation='START') # returns a TS.Date object
d2 = m2.asfreq('D', relation='END')

firstDay = d1.datetime
lastDay = d2.datetime

This solution is dependent out outside modules, but they're very powerful and well written.

like image 31
Greg Avatar answered Oct 17 '22 23:10

Greg


from datetime import datetime, timedelta

def first_day(some_date):
    return some_date.replace(day=1, hour=0, minute=0, second=0, microsecond=0)

def next_month(some_date):
    return first_day(first_day(some_date) + timedelta(days=31))

def last_day(some_date):
    return next_month(some_date) - timedelta(days=1)

# testing:

months = [('Jan-2010', 'Mar-2010'), # your example
          ('Apr-2009', 'Apr-2009'), # same month, 30 days
          ('Jan-2008', 'Dec-2008'), # whole year
          ('Jan-2007', 'Feb-2007')] # february involved

for date1, date2 in months:
    print first_day(datetime.strptime(date1, '%b-%Y')),
    print '-', 
    print last_day(datetime.strptime(date2, '%b-%Y'))

That prints:

2010-01-01 00:00:00 - 2010-03-31 00:00:00
2009-04-01 00:00:00 - 2009-04-30 00:00:00
2008-01-01 00:00:00 - 2008-12-31 00:00:00
2007-01-01 00:00:00 - 2007-02-28 00:00:00
like image 30
nosklo Avatar answered Oct 17 '22 22:10

nosklo