Pythonで年/月/日を年間通算日に変換する


127

私はPythonのdatetimeモジュールを使用しています。

>>> import datetime
>>> today = datetime.datetime.now()
>>> print today
2009-03-06 13:24:58.857946

うるう年に敏感な年の日を計算したいと思います。たとえば、今日(2009年3月6日)は2009年の65日目です。これ がWebベースのDateTime計算機です。

とにかく、私は2つのオプションを見ます:

A. number_of_days_in_month配列= [31、28、...]を作成し、うるう年かどうかを判断し、手動で日数を合計します。

B.を使用datetime.timedeltaして、1年の正しい日を推測してからバイナリ検索します。

>>> import datetime
>>> YEAR = 2009
>>> DAY_OF_YEAR = 62
>>> d = datetime.date(YEAR, 1, 1) + datetime.timedelta(DAY_OF_YEAR - 1)

これらはどちらもかなり不格好な感じがしますが、年の計算にはより「Python的な」方法があると直感しています。アイデア/提案はありますか?

回答:


255

非常にシンプルな解決策があります:

from datetime import datetime
day_of_year = datetime.now().timetuple().tm_yday

13
非常にマイナーで議論の余地のない追加ですが、使用するのdate.today()ではなく、使用datetime.now()することで、操作の性質が少し強調されます。
ジェレミー

5
さらに良い:time.localtime().tm_yday localtime()が生成するので、datetimeをtimetupleに変換する必要はありません。
マイクエリス

14
@MikeEllisしかし、このソリューションは、日時が今日に対応していない場合の対処法を示しています。
gerrit 2014年

2
注:これは1から数え始めます
Mehdi Nellen

1
逆にしたい場合は、「2020年の26日」と言う数字があり、日付を「26-01-2020」に変換したいですか?
Sankar

43

使えませんstrftimeか?

>>> import datetime
>>> today = datetime.datetime.now()
>>> print today
2009-03-06 15:37:02.484000
>>> today.strftime('%j')
'065'

編集する

コメントに記載されているように、この数値を使用して比較または計算を行う場合は、文字列を返すint()ため、数値に変換する必要strftime()があります。その場合は、DzinXの回答を使用したほうがよいでしょう。


1
-1:気難しい。「今日から1月1日を引いた」アルゴリズムの方が優れています。strftimeの '%j'に関する雑学を調べなくても、はるかに明確で完全に明白です。
S.Lott、2009年

12
マジ?この不機嫌で1月1日を引くのはどうですか?strftimeには理由があります。私は同意しません。私の意見ではこれはずっときれいです。
Paolo Bergantino

1
strftimeの使用は、数値から文字列を生成するため、間接的です:timetuple.tm_ydayメンバー。ソースを読んでください。生成された文字列は、計算/比較の前に数値に変換する必要があります。
tzot 2009年

2
文字列で年の日が必要な場合、たとえばファイル名で使用する場合、strftimeの方がはるかにクリーンなソリューションです。
captain_M 2014年

13

DZinXの回答は、質問に対する優れた回答です。逆関数を探しているときにこの質問を見つけました。私はこれがうまくいくことを発見しました:

import datetime
datetime.datetime.strptime('1936-077T13:14:15','%Y-%jT%H:%M:%S')

>>>> datetime.datetime(1936, 3, 17, 13, 14, 15)

datetime.datetime.strptime('1936-077T13:14:15','%Y-%jT%H:%M:%S').timetuple().tm_yday

>>>> 77

この辺のエチケットはよくわかりませんが、逆関数へのポインタが私のような他の人に役立つかもしれないと思いました。


6

Python 3.4、Linux x64でのさまざまなアプローチのパフォーマンスを提示したいと思います。ラインプロファイラーからの抜粋:

      Line #      Hits         Time  Per Hit   % Time  Line Contents
      ==============================================================
         (...)
         823      1508        11334      7.5     41.6          yday = int(period_end.strftime('%j'))
         824      1508         2492      1.7      9.1          yday = period_end.toordinal() - date(period_end.year, 1, 1).toordinal() + 1
         825      1508         1852      1.2      6.8          yday = (period_end - date(period_end.year, 1, 1)).days + 1
         826      1508         5078      3.4     18.6          yday = period_end.timetuple().tm_yday
         (...)

だから最も効率的です

yday = (period_end - date(period_end.year, 1, 1)).days

1
パフォーマンスをどのように計算しましたか?私はtime.timeを使用してみましたが、これらは私の結果です:def f():(today-datetime.datetime(today.year、1、1))。days + 1 start = time.time(); f(); print( 'Lapsed {}'。format(time.time()-start)); 経過5.221366882324219e-05 def f():int(today.strftime( '%j')); start = time.time(); f(); print( 'Lapsed {}'。format(time.time()-start)); 経過時間7.462501525878906e-05
ssoto 2017

5

日付から1月1日を引くだけです。

import datetime
today = datetime.datetime.now()
day_of_year = (today - datetime.datetime(today.year, 1, 1)).days + 1

1
Paoloに対しては何もありませんが、datetime.timedeltaは日単位(もちろん、秒とマイクロ秒も同様)で
表される

1
ドキュメントによると、d.toordinal()-date(d.year、1、1).toordinal()+ 1がより標準的です。全体のタプルを生成せずに受け入れられた回答と同等です。
Dingle

5

datetimeモジュールの使用を回避する理由がある場合、これらの関数は機能します。

def is_leap_year(year):
    """ if year is a leap year return True
        else return False """
    if year % 100 == 0:
        return year % 400 == 0
    return year % 4 == 0

def doy(Y,M,D):
    """ given year, month, day return day of year
        Astronomical Algorithms, Jean Meeus, 2d ed, 1998, chap 7 """
    if is_leap_year(Y):
        K = 1
    else:
        K = 2
    N = int((275 * M) / 9.0) - K * int((M + 9) / 12.0) + D - 30
    return N

def ymd(Y,N):
    """ given year = Y and day of year = N, return year, month, day
        Astronomical Algorithms, Jean Meeus, 2d ed, 1998, chap 7 """    
    if is_leap_year(Y):
        K = 1
    else:
        K = 2
    M = int((9 * (K + N)) / 275.0 + 0.98)
    if N < 32:
        M = 1
    D = N - int((275 * M) / 9.0) + K * int((M + 9) / 12.0) + 30
    return Y, M, D

1

このコードは、入力引数として日付を取り、年間通算日を返します。

from datetime import datetime
date = raw_input("Enter date: ")  ## format is 02-02-2016
adate = datetime.datetime.strptime(date,"%d-%m-%Y")
day_of_year = adate.timetuple().tm_yday
day_of_year
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.