本问题已经有最佳答案,请猛点这里访问。
所以我试图找到一种方法,将日期时间对象增加一个月。然而,根据这个问题,这似乎不是那么简单。
我希望有这样的事情:
import datetime as dt
now = dt.datetime.now()
later = now + dt.timedelta(months=1)
但那不管用。如果可能的话,我也希望能够在下个月的同一天(或者最近的一天)去。例如,设置为1月1日的日期时间对象将增加到2月1日,而设置为2月28日的日期时间对象将增加到3月31日,而不是3月28日。
很明显,2月28日(通常)会映射到3月31日,因为它是一个月的最后一天,因此应该转到下个月的最后一天。否则,这将是一个直接的链接:增量应该转到下个月的同一个编号的日期。
在当前的Python版本中,有没有一种简单的方法可以做到这一点?
您需要更全面地指定所需的行为。为什么2月28日的地图要到3月31日?2月27日的地图应该是什么?3月30日?2月14日怎么样?2月15日?噢,"最近的选择"是什么意思?这并不明显。
@西哈,你需要更具体一点。我相信这样会改变那些不被接受的答案,从而使投票模式多样化。
stackoverflow.com/a/4406260/2632856
@西哈现在清楚了。谢谢。
查看EDOCX1[2]为了给一个日期增加一个特定的时间量,您可以继续使用timedelta来处理简单的事情,即。
use_date = use_date + datetime.timedelta(minutes=+10)
use_date = use_date + datetime.timedelta(hours=+1)
use_date = use_date + datetime.timedelta(days=+1)
use_date = use_date + datetime.timedelta(weeks=+1)
或者你可以开始使用relativedelta。
use_date = use_date+relativedelta(months=+1)
use_date = use_date+relativedelta(years=+1)
。
下个月最后一天:
use_date = use_date+relativedelta(months=+1)
use_date = use_date+relativedelta(day=31)
。
现在,这将提供2016年2月29日
下个月倒数第二天:
use_date = use_date+relativedelta(months=+1)
use_date = use_date+relativedelta(day=31)
use_date = use_date+relativedelta(days=-1)
下个月的最后一个星期五:
use_date = use_date+relativedelta(months=+1, day=31, weekday=FR(-1))
。
下个月的第二个星期二:
new_date = use_date+relativedelta(months=+1, day=1, weekday=TU(2))
这绝不是一份详尽的清单。文档可从以下网址获取:https://dateutil.readthedocs.org/en/latest/
这个怎么样?
def add_one_month(orig_date):
# advance year and month by one month
new_year = orig_date.year
new_month = orig_date.month + 1
# note: in datetime.date, months go from 1 to 12
if new_month > 12:
new_year += 1
new_month -= 12
new_day = orig_date.day
# while day is out of range for month, reduce by one
while True:
try:
new_date = datetime.date(new_year, new_month, new_day)
except ValueError as e:
new_day -= 1
else:
break
return new_date
编辑:
改进版本:
如果给定datetime.datetime对象,则保留时间信息
不使用try/catch,而是使用stdlib中的calendar模块中的calendar.monthrange:
import datetime
import calendar
def add_one_month(orig_date):
# advance year and month by one month
new_year = orig_date.year
new_month = orig_date.month + 1
# note: in datetime.date, months go from 1 to 12
if new_month > 12:
new_year += 1
new_month -= 12
last_day_of_month = calendar.monthrange(new_year, new_month)[1]
new_day = min(orig_date.day, last_day_of_month)
return orig_date.replace(year=new_year, month=new_month, day=new_day)
。
在热循环中抛出异常不是一个好的实践。
怎么会是热循环?最多循环3次。在给定随机日期的情况下,异常被抛出的次数相对较少,平均每个调用大约有0.016(6/365.25)个异常。如果这成为某个人的性能瓶颈,他们可以根据需要进行优化。
关于性能,我什么也没说,这并不是特例在软件工程中的用途。它们应该是例外情况,而不是通常的业务逻辑。
这不是截断时间信息吗?
好吧,长话短说,滚动你自己的日期代码是不明智的。对于某些类项目来说,这可能已经足够好用了,但是在处理日期时,您确实应该使用一个受支持、测试良好的库。因此,OP问题的答案可能只是"不",但我希望有一个或两个标准库用于这个非常常见的问题(我认为在链接的问题中讨论)。
在闰秒时引发异常。
@Djechlin:嗯,python的datetime一开始甚至不支持闰秒。
@真的吗?我一直认为这类事情很重要。
问题:在当前的Python版本中,有没有一种简单的方法可以做到这一点?
答:在当前的Python版本中,没有简单(直接)的方法可以做到这一点。
参考:请参考docs.python.org/2/library/datetime.html,第8.1.2节。TimeDelta对象。正如我们可以理解的那样,我们不能直接增加月份,因为它不是一个统一的时间单位。
另外:如果您想要第一天->第一天和最后一天->最后一天的映射,您应该在不同的月份分别处理它。
这不是一个有用的答案,因为真的没有理由相信你是对的,而不仅仅是误传。
不一定。他不会问"做那件事的简单方法是什么?"但"有没有简单的方法可以做到这一点?"答案是否定的。也许这个答案会阻止他白白浪费时间,并开始实施一个对他有用的解决方案,从而节省他时间和精力。
需要引文。你不是引文。
查找主要库(dateutil!)这就实现了它,这意味着它不存在于标准库中。引用行业领导者的博客文章。向控制该特性的Python的任何主体显示一个正式请求,或者在python n+1中找到直接支持它的计划。显示与此不兼容的python特性。为唯一有意义的地方显示文档。等。。。。
请看一下:docs.python.org/2/library/datetime.html,第8.1.2节。TimeDelta对象。请考虑OP要求"稍后=现在+dt.timedelta(months=1)"。正如您所看到的,您不能直接增加月份,因为它不是统一的。顺便说一句,有人已经给出了一个完整的答案。
好吧,把这个加到你的答案里,而不是告诉我。
@Djechlin引用了一篇由业内领袖撰写的博客——通过呼吁权威来寻找证据。反克拉克的第一定律,一个公认的知名人士说"不可能"的事情可能是错误的。;
@让我列出的所有东西都很好?太好了,谢谢。还有,一个尼特:证据!=证据。埃里克·利珀特相信C的某些东西是事实的证据。我并不认为这是一个谬论,但对每个人都是如此。
@苔丝·艾克勒·欧奇,继续这个讨论:物理学!=编程语言功能是否不存在。有时很有可能证明某些事情是不可能的。我相信你有足够的才智来做出区分;)
>>> now
datetime.datetime(2016, 1, 28, 18, 26, 12, 980861)
>>> later = now.replace(month=now.month+1)
>>> later
datetime.datetime(2016, 2, 28, 18, 26, 12, 980861)
编辑:失败
y = datetime.date(2016, 1, 31); y.replace(month=2) results in ValueError: day is out of range for month
号
这不是一个简单的方法,但是你可以使用你自己的功能,如下面的回答。
y = datetime.date(2016, 1, 31); y.replace(month=2)导致ValueError: day is out of range for month。
@塔莱纳,看起来没有简单的答案