背景:
一般我们在数据统计或者是多图标数据展示的时候,经常会用到今日、昨日、近一周、近一月等等不同的时间维度提供给客户进行时间选择,以期通过不同时间的变化趋势,展示业务的动态发展。
在处理这些时间的时候,对于近一月,我们经常需要计算距离当前时间一个月日期,如何计算这个日期呢。
常见时间处理:
我们会经常的在网络博客上看到这种处理方法
now = datetime.now() # 获取当前时间
if now.month != 1:
last_month = now.replace(month=now.month - 1)
else:
last_month = now.replace(month=12, year=now.year - 1)
last_month = str(last_month)[:7]
log.info("last_month=[%s]" % last_month)
这样看起来也没有什么问题,而且还避免了1月份求上一个月的日期的时候 自动转换成为了上一年的12月份。
问题所在:
但在实际应用中,会发现这种问题会引发无数次报错的问题,题主这次问题出现在3月29号进行日期查询的时候,系统报错:
ValueError: day is out of range for month
很明显的告诉我们,日期超过了这个月份涵盖的。也就是说,这个月份没有这一天,仔细看着前任写下的代码=======
竟无语凝噎,除了七八月,12月1月连续起来的时候不会出现错误,其他每个月31号这里都会有问题,特别是三月份 四年一次的29年除外,30、31都会出现问题。
如何处理:
这里我使用了python 的arrow包来进行这个时间处理
arrow是一个python库,它提供了一种创建、操作、格式化和转换日期、时间和时间戳的合理且人性化的方法。
它实现并更新datetime类型,填补功能上的空白,并提供一个支持许多常见创建场景的智能模块api。简单地说,
它可以帮助您以更少的导入和更少的代码处理日期和时间。
支持版本
支持Python2.7、3.5、3.6、3.7和3.8
个人理解来说 arrow 利用了类似游标的模式,对日期计算的时候,使用游标进行左移右移操作,得到时间
pip install arrow
安装完成后:
计算当前日期前一个月:
now = arrow.now()
获取上个月时间
last_month = now.shift(months=-1)
last_month = str(last_month)[:7] # 只取日期部分
指定某个日期
parser = arrow.get(2021,1,1)
last_month = parser.shift(months=-1).format("YYYY-MM")
计算前一天
now = arrow.now()
获取昨天时间
tomorrow = now.shift(days=-1)
计算下一年
now = arrow.now()
获取明年时间
next_year = now.shift(years=1)
经过测试,如上的错误问题,可以通过arrow包更好的避免,当然arrow包所造成的bug也未必一定能避免,肯定必将一路前行,继续积累。