Как * изменить * объект struct_time?

Когда вы работаете со временем и датами в python, вы наткнетесь на объект time.struct_time:

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)

Теперь, когда эта структура не поддерживает назначение элемента (т.е. вы не можете сделать что-то вроде st[1]+=1), как еще можно увеличить, скажем, номер месяца.

Решения предлагают преобразовать этот time_struct в секунды и добавить соответствующее количество секунд, но это выглядит не очень хорошо. Вы также должны знать, сколько дней в месяц, или год является високосным годом или нет. Я хочу простой способ получить time_struct, например,

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)

только месяц увеличился на единицу. Создание time_struct с нуля было бы неплохо, но как? Какие существуют способы?

Ответ 1

Вместо этого используйте datetime модуль, который имеет гораздо более богатый набор объектов для обработки арифметики даты (времени):

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

Вы можете использовать отличный python-dateutil дополнительный модуль, чтобы получить более богатый набор возможностей для работы с дельтами:

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

relativedelta знает о високосных годах, длинах месяцев и т.д. и будет делать правильные вещи при добавлении месяца, например, 30 января (вы закончите с 28 или 29 февраля, он не будет пересекать границы месяца),

Ответ 2

Итак... схема для кортежа, лежащего в основе time_struct, приведена здесь в документации: http://docs.python.org/2/library/time.html#time.struct_time

И даже при том, что он доступен только для чтения как time_struct, вы можете использовать casting to list() для непосредственного доступа к этому кортежу (помните, чтобы обернуть ваш месяц после его увеличения и сохранить конечный диапазон в 1-12 а не 0-11). Затем функция time.struct_time() преобразует верный 9-кортеж обратно в 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))

Ответ 4

Если вы хотите избежать совпадения времени и времени со временем, вы можете конвертировать в временную метку unix, а затем вычесть количество секунд, которое вам нужно. Чтобы получить объект времени 24 часа назад:

time.gmtime(time.mktime(time.gmtime()) - 86400)

Однако, поскольку OP указал, что это плохо для работы с месяцами и должно быть зарезервировано на секунды, часы и дни.