2009-08-13 16 views
4

Nehmen wir an, ich habe 2 Strings 'Jan-2010' und 'Mar-2010' und ich möchte es so analysieren, dass es 2 datetime Objekte zurückgibt: 1-Jan-2010 und 31-Mar- 2010 (dh der letzte Tag).Parsing Monat Jahr Paare in Datetime

Was wäre die beste Strategie in Python? Sollte ich die Zeichenfolge einfach in Token aufteilen oder reguläre Ausdrücke verwenden und dann die Kalenderfunktionen verwenden, um den letzten Tag des Monats für "Mar-2010" zu erhalten (den ersten Tag zu bekommen ist trivial, in diesem Fall immer 1, es sei denn ich wollte) der erste Arbeitstag des Monats).

Irgendwelche Vorschläge? Danke im Voraus.

Antwort

2
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')) 

die Drucke:

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 
5

strptime tut der String in Daten in Ihrem Namen Parsen:

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

viel besser als Herumspielen mit tokenization, regexp, & c -) .

Um das Datum des letzten Tages des Monats, können Sie in der Tat das Kalender-Modul verwenden:

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

Sie fast allein mit Datumzeit ordentlich zu tun könnte, zB einen NAHEZU Arbeitsansatz:

aber, ach !, das bricht für Dezember, und der Code benötigt, um Dezember zu spezialisieren, macht den Gesamtansatz goofier als Kalender bietet ;-).

+0

@ Alex: Um es über Dezember funktioniert ein zu den Tagen hinzuzufügen (nicht auf die Monate), da es keinen Monat relativ Timedelta . – nosklo

+0

@nosko, yep, Ich habe deinen raffinierten Trick gesehen (Hinzufügen von 31 Tagen, dann zurück zum 1. des Monats), aber ich mag es nicht, Datumsangaben herumzuwerfen, wenn Daten alles sind, was benötigt wird und .date() tut die Extraktion Datum von Datetime einfach gut ;-) –

+0

@Alex: Ja aber ... Ich sehe nicht, wie das, was du gesagt hast, damit zusammenhängt, was wir vorher geredet haben. – nosklo

0

Riffing auf Alex Martelli:

import datetime 
def lastofmonthHelper(MmmYyyy): # Takes a date 
    return MmmYyyy.replace(year=MmmYyyy.year+(MmmYyyy.month==12), month=MmmYyyy.month%12 + 1, day=1) - datetime.timedelta(days=1) 

>>> for month in range(1,13): 
...  t = datetime.date(2009,month,1) 
...  print t, lastofmonthHelper(t) 
... 
2009-01-01 2009-01-31 
2009-02-01 2009-02-28 
2009-03-01 2009-03-31 
2009-04-01 2009-04-30 
2009-05-01 2009-05-31 
2009-06-01 2009-06-30 
2009-07-01 2009-07-31 
2009-08-01 2009-08-31 
2009-09-01 2009-09-30 
2009-10-01 2009-10-31 
2009-11-01 2009-11-30 
2009-12-01 2009-12-31 

Sie müssen nicht den ersten Tag des Monats verwenden, BTW. Ich hätte das in einen Kommentar geschrieben, aber wir alle wissen, wie sich die Formatierung entwickelt hätte. Fühlen Sie sich frei, Alex zu verbessern.

Wenn Sie mit dem Ergebnis einer firstofmonth() Aufruf aufrufen, erhalten Sie das gewünschte Ergebnis:

>>> lastofmonthHelper(firstofmonth('Apr-2009')) 
datetime.date(2009, 4, 30) 
3

Ich empfehle, die Python-Zeitreihen-Modul, das Sie herunterladen und über hier lesen:

http://pytseries.sourceforge.net/

Sie sollten auch die dateutil Paket zum Parsen des Datums-Zeichenfolge verwenden, die Sie hier finden können:

http://labix.org/python-dateutil

Dann können Sie so etwas wie dieses

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 

tun Diese Lösung ist abhängig out außerhalb Module, aber sie sind sehr leistungsfähig und gut geschrieben.

1

ich weiß, es ist lange weg, aber wenn jemand braucht:

from dateutil import rrule 
from dateutil import parser 
from datetime import datetime 

first_day = parser.parse('Jan-2010',default=datetime(1,1,1)) 
last_day = rrule.rrule(rrule.MONTHLY,count=1,bymonthday=-1, bysetpos=1,dtstart=parser.parse('Mar-2010'))