2016-02-26 17 views
10

私はこのようにフォーマットリストとして、今と2010年8月の間にすべての月を取得したい:Python:すべての月間を取得できますか?

['2010-08-01', '2010-09-01', .... , '2016-02-01'] 

今これは私が持っているものです。

へのより良い方法だろう何
months = [] 
for y in range(2010, 2016): 
    for m in range(1, 13): 
     if (y == 2010) and m < 8: 
      continue 
     if (y == 2016) and m > 2: 
      continue 
     month = '%s-%s-01' % (y, ('0%s' % (m)) if m < 10 else m) 
     months.append(month) 

これを行う?

答えて

14

(最長数ヶ月は31日あり)ここにはdateutil.relativedeltaが便利です。

私は演習として書式設定を残しました。

from dateutil.relativedelta import relativedelta 
import datetime 

result = [] 

today = datetime.date.today() 
current = datetime.date(2010, 8, 1)  

while current <= today: 
    result.append(current) 
    current += relativedelta(months=1) 
+0

Ani、これはほぼ正しいですが、ISO形式で表示されるようにdatetimeをフォーマットする必要があります。 isoformatを追加することでこれを行うことができます。あなたは 'result.append(current.isoformat())'に行を変更する必要があります - [EDIT:書式を練習として残しているのを見たことはありませんでした...しかし、まあ。] –

+0

ありがとう、 result.append(datetime.strftime(current、 '%Y-%m-01')) '私が望む形式を得るために。 – Richard

0

以前if文を使用して同じことを二ifのステートメントを持つことが少し冗長であるため、次の2つのラインの代わりに、4つのラインにif文の数を減らすことができます。

if (y == 2010 and m < 8) or (y == 2016 and m > 2): 
    continue 
4

使用datetimetimedelta標準Pythonのモジュール - 私は新しい月ごとに時間を入力する32日を追加している任意の新しいライブラリ

from datetime import datetime, timedelta 

now = datetime(datetime.now().year, datetime.now().month, 1) 
ctr = datetime(2010, 8, 1) 
list = [ctr.strftime('%Y-%m-%d')] 

while ctr <= now: 
    ctr += timedelta(days=32) 
    list.append(datetime(ctr.year, ctr.month, 1).strftime('%Y-%m-%d')) 

をインストールせずに

+0

これは素晴らしいソリューションですが、 '' CTR =はtimedelta(日= 32) '後ctr.replace(日= 1)を追加し、' CTR =なければならない、そうでなければ、スキップしますよより長い期間にこのシーケンスを見てみましょう:[2018-10-28,2018-11-29,2018-12-31,2019-02-01、2019-03-05] - > 1月はここではスキップされました。 1日を1に設定すると、この問題は回避されます。 – jps

0

私はそれが良くのかどうか分かりませんが、以下のようなアプローチは、より「ニシキヘビ」とみなされる可能性があります

months = [ 
    '{}-{:0>2}-01'.format(year, month) 
     for year in xrange(2010, 2016 + 1) 
     for month in xrange(1, 12 + 1) 
     if not (year <= 2010 and month < 8 or year >= 2016 and month > 2) 
] 

ここでの主な違いは以下のとおりです。

  • 反復でリストを生成したいので、forループ内のリスト要素を集める代わりにlist comprehensionを使用します。
  • 代わりに明示的に10と数10と上記下の数字の間の区別を行うの、
  • xrangeの代わりにrangeは、リストの代わりにジェネレータを返します。これにより、消費されているときに反復値が生成され、メモリに保持する必要はありません。 注::Python 3では、xrangeがなく、range関数はすでにリストの代わりにジェネレータを返しています。
  • 上限のために+ 1を明示してください。これにより、コードの読者は、上限を排他的として扱うメソッド(rangeまたはxrange)に包括的にバインドすることを指定することを認識しやすくなります。それ以外の場合は、番号13の取引が不思議に思うかもしれません。
+0

さらにPythonは、[Aniの答え](http://stackoverflow.com/a/35651063/674064)のように、日付と時刻の違いを扱うのに 'dateutil'と' datetime'を使っています。 –

3

私はdateutilのドキュメントを見ました。それはdateutil.relativedeltaを使用するよりも、より便利な方法を提供してい判明:recurrence rulesexamples

当面の作業のために、それは我々がいる細かい印刷

from dateutil.rrule import * 
from datetime import date 

months = map(
    date.isoformat, 
    rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today()) 
) 

と同じくらい簡単ですここでちょっと騙されている。 dateutil.rrule.rrule要素は、上記のようにdatetime.dateタイプのdtstartuntilを渡したとしても、タイプdatetime.datetimeです。私はmapdateisoformat関数に送ります。ちょうど時刻情報がないまさに日付であるかのように文字列に変換すると分かります。

したがって、一見同等のリスト内包

[day.isoformat() 
    for day in rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())] 

は、私たちが代わりにmapのリストの内包表記を使用したい場合はこのように、私たちはのような何かをしなければならない

['2010-08-01T00:00:00', 
'2010-09-01T00:00:00', 
'2010-10-01T00:00:00', 
'2010-11-01T00:00:00', 
⋮ 
'2015-12-01T00:00:00', 
'2016-01-01T00:00:00', 
'2016-02-01T00:00:00'] 

のようなリストを返します

[dt.date().isoformat() 
    for dt in rrule(MONTHLY, dtstart=date(2010, 8, 1), until=date.today())] 

+0

最初のリストの理解の反復変数 'day'は_deliberate_の誤称であることに注意してください。説明したように、 'datetime'ではなく' date'を保持します。 –

0

私はdatetime、timedeltaそしてカレンダー:

from calendar import monthrange 
from datetime import datetime, timedelta 

def monthdelta(d1, d2): 
    delta = 0 
    while True: 
     mdays = monthrange(d1.year, d1.month)[1] 
     d1 += timedelta(days=mdays) 
     if d1 <= d2: 
      delta += 1 
     else: 
      break 
    return delta 

start_date = datetime(2016, 1, 1) 
end_date = datetime(2016, 12, 1) 

num_months = [i-12 if i>12 else i for i in range(start_date.month, monthdelta(start_date, end_date)+start_date.month+1)] 
monthly_daterange = [datetime(start_date.year,i, start_date.day, start_date.hour) for i in num_months] 
関連する問題