modifying a time.struct_time

Mazen Harake mazen.harake at gmail.com
Fri Dec 16 05:32:13 EST 2011


Hi,

Easiest way is to change the time to seconds, add as many seconds as a
year/month/week/day/hour/minutes represent and then transform it back.

E.g.

>>> time.time()
1324031491.026137
>>> time.time() + 3600 # Add an hour
1324035105.082003
>>> time.gmtime(time.time() + 3600)
time.struct_time(tm_year=2011, tm_mon=12, tm_mday=16, tm_hour=11,
tm_min=31, tm_sec=57, tm_wday=4, tm_yday=350, tm_isdst=0)
>>>

On 16 December 2011 10:45, Ulrich Eckhardt
<ulrich.eckhardt at dominolaser.com> wrote:
> Hi!
>
> I'm trying to create a struct_time that is e.g. one year ahead or a month
> back in order to test some parsing/formatting code with different dates.
>
> Now, the straightforward approach is
>
>  t = time.localtime()
>  t.tm_year += 1
>
> This fails with "TypeError: readonly attribute". This kind-of makes sense,
> as an immutable object allows you to use it as key in a dict.
>
>
> The second approach is this:
>
>  l = list(t) # convert to a sequence
>  l[0] += 1 # increment year
>  t = time.struct_time(l) # convert to a struct_time
>
> This works but is ugly, because the code relies on the order inside the list
> and uses magic numbers to access them. The order is AFAICT not accessible
> programmatically but only documented, and not even in a way that makes clear
> that it is part of the API and as such actualy guaranteed. I could try to
> assert that the indices match using "if l[0] is t.tm_year", but this is
> still ugly.
>
>
> The next approach I tried was to simply create a derived class:
>
>  class my_time(time.struct_time):
>      pass
>
> This fails again with "TypeError: Error when calling the metaclass bases,
> type 'time.struct_time' is not an acceptable base type. I could try to
> encapsulate a struct_time and delegate attribute access to it in order to do
> this, but it also seems overkill. Also, using an immutable type as a
> baseclass and delegating access to members seems like hackery to me, prone
> to fail in situations where it is least expected.
>
>
> Then I tried duck typing. If it quacks like a duck, it better not be a
> crocodile! This looks like this:
>
>  struct my_time(object): pass
>  t = my_time()
>  t.tm_year = 2012
>  t.tm_month = 12
>  t.tm... # other fields accordingly
>  time.mktime(t)
>
> This fails with "TypeError: argument must be 9-item sequence, not my_time".
> I thought about using a collections.namedtuple, because a namedtuple is a
> tuple and therefore also a sequence, but that only leads me back to the
> problem that time.mktime() takes a sequence and the order of the sequence is
> not accessible programmatically.
>
>
> A last approach was to convert the thing to a dict and back. Alas, there is
> no conversion to a dict, otherwise
>
>  d = dict(t)
>  d['tm_year'] += 1
>  t = time.struct_time(d)
>
> would have been a straightforward approach.
>
>
> Does anyone have a suggestion how to solve this elegantly and pythonically?
> Also, what I'm wondering is if the lack of a clear way should be considered
> a bug or not.
>
>
> Cheers!
>
> Uli
>
> --
> http://mail.python.org/mailman/listinfo/python-list



More information about the Python-list mailing list