Skip to content

Commit fe09833

Browse files
committed
3.14小节完成
1 parent a5e1b78 commit fe09833

File tree

2 files changed

+131
-6
lines changed

2 files changed

+131
-6
lines changed

cookbook/c03/p14_month_range.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
"""
4+
Topic: 计算当前月份的日期范围
5+
Desc :
6+
"""
7+
from datetime import datetime, date, timedelta
8+
import calendar
9+
10+
11+
def get_month_range(start_date=None):
12+
if start_date is None:
13+
start_date = date.today().replace(day=1)
14+
_, days_in_month = calendar.monthrange(start_date.year, start_date.month)
15+
end_date = start_date + timedelta(days=days_in_month)
16+
return (start_date, end_date)
17+
18+
19+
def date_range(start, stop, step):
20+
while start < stop:
21+
yield start
22+
start += step
23+
24+
25+
def month_range():
26+
a_day = timedelta(days=1)
27+
first_day, last_day = get_month_range()
28+
while first_day < last_day:
29+
print(first_day)
30+
first_day += a_day
31+
32+
# 使用生成器
33+
for d in date_range(datetime(2012, 9, 1), datetime(2012, 10, 1),
34+
timedelta(hours=6)):
35+
print(d)
36+
37+
38+
if __name__ == '__main__':
39+
month_range()
40+
Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,103 @@
1-
============================
2-
3.14 寻找当前月份的某个日期范围
3-
============================
1+
==========================
2+
3.14 计算当前月份的日期范围
3+
==========================
44

55
----------
66
问题
77
----------
8-
todo...
8+
你的代码需要在当前月份中循环每一天,想找到一个计算这个日期范围的高效方法。
9+
10+
|
911
1012
----------
1113
解决方案
1214
----------
13-
todo...
15+
在这样的日期上循环并需要事先构造一个包含所有日期的列表。
16+
你可以先计算出开始日期和结束日期,然后在你步进的时候使用datetime.timedelta对象递增这个日期变量即可。
17+
18+
下面是一个接受任意datetime对象并返回一个由当前月份开始日和下个月开始日组成的元组对象。
19+
20+
.. code-block:: python
21+
22+
from datetime import datetime, date, timedelta
23+
import calendar
24+
25+
def get_month_range(start_date=None):
26+
if start_date is None:
27+
start_date = date.today().replace(day=1)
28+
_, days_in_month = calendar.monthrange(start_date.year, start_date.month)
29+
end_date = start_date + timedelta(days=days_in_month)
30+
return (start_date, end_date)
31+
32+
有了这个就可以很容易的在返回的日期范围上面做循环操作了:
33+
34+
.. code-block:: python
35+
36+
>>> a_day = timedelta(days=1)
37+
>>> first_day, last_day = get_month_range()
38+
>>> while first_day < last_day:
39+
... print(first_day)
40+
... first_day += a_day
41+
...
42+
2012-08-01
43+
2012-08-02
44+
2012-08-03
45+
2012-08-04
46+
2012-08-05
47+
2012-08-06
48+
2012-08-07
49+
2012-08-08
50+
2012-08-09
51+
#... and so on...
52+
53+
|
1454
1555
----------
1656
讨论
1757
----------
18-
todo...
58+
上面的代码先计算出一个对应月份第一天的日期。
59+
一个快速的方法就是使用date或datetime对象的replace()方法简单的将days属性设置成1即可。
60+
replace()方法一个好处就是它会创建和你开始传入对象类型相同的对象。
61+
所以,如果输入参数是一个date实例,那么结果也是一个date实例。
62+
同样的,如果输入是一个datetime实例,那么你得到的就是一个datetime实例。
63+
64+
然后,使用calendar.monthrange()函数来找出该月的总天数。
65+
任何时候只要你想获得日历信息,那么calendar模块就非常有用了。
66+
monthrange()函数会返回包含星期和该月天数的元组。
67+
68+
一旦该月的天数已知了,那么结束日期就可以通过在开始日期上面加上这个天数获得。
69+
有个需要注意的是结束日期并不包含在这个日期范围内(事实上它是下个月的开始日期)。
70+
这个和Python的slice与range操作行为保持一致,同样也不包含结尾。
71+
72+
为了在日期范围上循环,要使用到标准的数学和比较操作。
73+
比如,可以利用timedelta实例来递增日期,小于号<用来检查一个日期是否在结束日期之前。
74+
75+
理想情况下,如果能为日期迭代创建一个同内置的range()函数一样的函数就好了。
76+
幸运的是,可以使用一个生成器来很容易的实现这个目标:
77+
78+
.. code-block:: python
79+
80+
def date_range(start, stop, step):
81+
while start < stop:
82+
yield start
83+
start += step
84+
85+
下面是使用这个生成器的例子:
86+
87+
.. code-block:: python
88+
89+
>>> for d in date_range(datetime(2012, 9, 1), datetime(2012,10,1),
90+
timedelta(hours=6)):
91+
... print(d)
92+
...
93+
2012-09-01 00:00:00
94+
2012-09-01 06:00:00
95+
2012-09-01 12:00:00
96+
2012-09-01 18:00:00
97+
2012-09-02 00:00:00
98+
2012-09-02 06:00:00
99+
...
100+
>>>
101+
102+
这种实现之所以这么简单,还得归功于Python中的日期和时间能够使用标准的数学和比较操作符来进行运算。
103+

0 commit comments

Comments
 (0)