Python pas中每个月的开始和结束日期12个月

Python pas中每个月的开始和结束日期12个月,python,Python,这是我当前的代码 class TimeSeries(): def year(year): today = datetime.now() start_date = today+relativedelta(years=-1) mint, maxt = datetime.min.time(), datetime.max.time() for st in rrule(MONTHLY, count=24, bymonthday=(1,

这是我当前的代码

class TimeSeries():
    def year(year):
        today = datetime.now()
        start_date = today+relativedelta(years=-1)
        mint, maxt = datetime.min.time(), datetime.max.time()
        for st in rrule(MONTHLY, count=24, bymonthday=(1,-1,), dtstart=start_date):
            yield st.combine(st, mint)
这是这个的输出:

for y in TimeSeries().year():
    print(y)

2013-01-31 00:00:00
2013-02-01 00:00:00
2013-02-28 00:00:00
2013-03-01 00:00:00
2013-03-31 00:00:00
2013-04-01 00:00:00
2013-04-30 00:00:00
2013-05-01 00:00:00
2013-05-31 00:00:00
2013-06-01 00:00:00
2013-06-30 00:00:00
2013-07-01 00:00:00
2013-07-31 00:00:00
2013-08-01 00:00:00
2013-08-31 00:00:00
2013-09-01 00:00:00
2013-09-30 00:00:00
2013-10-01 00:00:00
2013-10-31 00:00:00
2013-11-01 00:00:00
2013-11-30 00:00:00
2013-12-01 00:00:00
2013-12-31 00:00:00
2014-01-01 00:00:00
问题是我如何才能强制计数从2013-01-01 00:00:00开始,然后像2013-01-31 23:59:59这样的月末开始。 循环结束时间为2014-01-31 23:59:59,而不是2014-01-01 00:00:00

另外,我喜欢将开始日期和结束日期放在一行:

2013-03-01 00:00:00 2013-03-31 23:59:59
2013-04-01 00:00:00 2013-03-30 23:59:59
...
...
2014-01-01 00:00:00 2014-01-31 23:59:59

有什么建议吗?

首先,你真的确定你想要
2013-03-31 23:59:59
。日期间隔传统上被指定为半开间隔,就像Python中的范围一样。原因是
23:59:59
实际上并不是一天的结束

最明显的是,
23:59:59.001
比那晚,但在同一天。Python
datetime
对象包含微秒,因此这不仅仅是一个“meh,whatever”问题。如果您(例如)调用
now()
,您可能会得到一个不正确的时间,而不是当天的“结束时间”

不太明显的是,在一个有,
23:59:60
的日子也晚了,但在同一天


但如果你真的想这样做,有两种明显的方法:


您已经在迭代日期而不是日期时间,并手动组合时间。当你处理第1天与第1天的对比时,这一点很明显,因为日期的
day
成员将是
1
,或者不是。因此:

class TimeSeries():
    def year(year):
        today = datetime.now()
        start_date = today+relativedelta(years=-1)
        mint, maxt = datetime.min.time(), datetime.max.time()
        for st in rrule(MONTHLY, count=24, bymonthday=(1, -1,), dtstart=start_date):
            yield st.combine(st, mint if st.day=1 else maxt)

或者,不迭代第一天和最后一天,只迭代第一天,减去第二天即可得到上个月的最后一秒:

class TimeSeries():
    def year(year):
        today = datetime.now()
        start_date = today+relativedelta(years=-1)
        mint, maxt = datetime.min.time(), datetime.max.time()
        for st in rrule(MONTHLY, count=24, bymonthday=(1,), dtstart=start_date):                
            dt = st.combine(st, mint)
            yield dt - timedelta(seconds=1)
            yield dt

至于成对打印这些……好吧,正如我所写的,这是一个未明确说明的问题。列表中的第一个值是一对中的第二个值,但在一个月的第一天运行时除外。同样,最后一个日期是一对中的第一个值,除非您在31日运行它。那么,你想用它们做什么

如果这不明显,看看你的例子。您的第一个值是
2013-01-31 00:00:00
,但您的第一对值不是以2013-01-31开头的

这里有很多你想要的东西:

  • 从一年前的第一个月开始,而不是去年的第一个月或最后一个月。最后也是如此。因此,您的列表中会有
    2013-01-01
    ,并且始终会有对
  • 从去年开始的第一个月开始,同样地,从去年年底开始。因此,您的列表中不会出现
    2013-01-31
    ,而且始终会有对
  • 使用当前规则,如果没有对,则使用
    None
    查找缺少的值
  • 等等
你真正想要的任何规则都可以很容易地编出来。然后,您可能希望
在(开始,结束)元组中产生
,因此
打印
循环可以执行以下操作:

for start, end in TimeSeries().year():
    print(start, end)

这里有两个完全不同的问题:将两对放在一行上,并在23:59:59结束。你应该将它们作为单独的问题来提问。要在一行中打印成对,最明显的做法是将
TimeSeries
更改为
yield
成对(作为开始、停止值的元组)。相反,在
打印
中对它们进行配对非常容易,但是当你跨越一个月的开始或结束时,就没有简单的方法来检测(比如你的第一个值,
2013-01-31
,它没有
2013-01-01
)。