Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to *change* a struct_time object?

Tags:

python

time

When dealing with times and dates in python, you will stumble across the time.struct_time object:

st = time.strptime("23.10.2012", "%d.%m.%Y")
print st
time.struct_time(tm_year=2012, tm_mon=10, tm_mday=23, tm_hour=0, tm_min=0,
                 tm_sec=0, tm_wday=1, tm_yday=297, tm_isdst=-1)

Now as this struct does not support item assignment (i.e. you cannot do something like st[1]+=1) how else is it possible to increase, say, the number of the month.

Solutions suggest to convert this time_struct into seconds and add the corresponding number of seconds, but this does not look nice. You also need to know how many days are in a month, or if the year is a leap year or not. I want an easy way to obtain a time_struct to be e.g.

time.struct_time(tm_year=2012, tm_mon=11, tm_mday=23, tm_hour=0, tm_min=0,
                 tm_sec=0, tm_wday=1, tm_yday=297, tm_isdst=-1)

with just the month increased by one. Creating a time_struct from scratch would be fine—but how? What ways are there?

like image 635
Alex Avatar asked Oct 23 '12 13:10

Alex


2 Answers

Use the datetime module instead, which has a far richer set of objects to handle date(time) arithmetic:

import datetime
adate = datetime.datetime.strptime("23.10.2012", "%d.%m.%Y").date()
adate + datetime.timedelta(days=30)

You can use the excellent python-dateutil add-on module to get an ever richer set of options for dealing with deltas:

from dateutil.relativedelta import relativedelta
adate + relativedelta(months=1)

relativedelta knows about leap years, month lengths, etc. and will do the right thing when adding a month to, say, January 30th (you end up with February 28th or 29th, it won't cross month boundaries).

like image 168
Martijn Pieters Avatar answered Nov 17 '22 04:11

Martijn Pieters


So... the schema for the tuple underlying time_struct is given in the documentation here: http://docs.python.org/2/library/time.html#time.struct_time

And even though it's read-only as a time_struct, you can use casting to list() to get at that tuple directly (remembering to wrap-around your month after you increment it, and keep the end range in 1-12 rather than 0-11). Then the time.struct_time() function will convert a valid 9-tuple back into a time_struct:

st = time.strptime("23.10.2012", "%d.%m.%Y")
st_writable = list(st)
st_writable[1] = (st_writable[1] + 1)%12 + 1
st = time.struct_time(tuple(st_writable))
like image 32
Christine Avatar answered Nov 17 '22 03:11

Christine