Python'da Yıl / Ay / Günü Yılın Gününe Dönüştür


127

Python datetime modülünü kullanıyorum, yani:

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

ve artık yıllara duyarlı olan yılın gününü hesaplamak istiyorum. örneğin bugün (6 Mart 2009) 2009'un 65. günüdür. İşte web tabanlı DateTime hesaplayıcı .

Her neyse, iki seçenek görüyorum:

A. number_of_days_in_month array = [31, 28, ...] oluşturun, artık yıl olup olmadığına karar verin, günleri manuel olarak toplayın.

B. datetime.timedeltaBir tahmin yapmak ve ardından yılın doğru günü için ikili arama yapmak için kullanın :

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

İkisi de oldukça hantal ve yılın gününü hesaplamanın daha "Pythonic" bir yolu olduğuna dair içimden bir his var. Herhangi bir fikir / öneri?

Yanıtlar:


256

Çok basit bir çözüm var:

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

13
Çok küçük ve tartışmalı bilgiçlik taslayan bir ekleme, ancak kullanmaktan date.today()çok datetime.now()işe yarıyor ve operasyonun doğasını biraz daha vurguluyor.
Jeremy

5
Daha da iyisi: time.localtime().tm_yday localtime () bunu sağladığı için, datetime'ı zaman çizelgesine dönüştürmeye gerek yoktur.
Mike Ellis

14
@MikeEllis Ancak bu çözüm, tarih saati bugüne karşılık gelmediğinde ne yapılacağını göstermektedir.
gerrit

2
not: bu 1'de saymaya başlıyor
Mehdi Nellen

1
Ya tersini yapmak istersem, sayıya sahip olsam "2020 yılının 26. günü" diyelim ve ben bunun "26-01-2020" tarihine dönüştürülmesini istiyorum?
Sankar

43

Kullanamaz strftimemısın

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

Düzenle

Açıklamalarda belirtildiği gibi bu sayı ile karşılaştırmalar veya hesaplamaları yapmak istiyorsanız, size dönüştürmek zorunda kalacak int()çünkü strftime()getiri bir dize. Eğer durum buysa, DzinX'in cevabını kullanmanız daha iyi .


1
-1: iğrenç. Daha iyisi "bugün eksi 1 Ocak" algoritmasıdır. Strftime'ın '% j' ile ilgili bir bilgi parçasına bakmadan çok daha temiz ve mükemmel bir şekilde açık.
S.Lott

12
Ciddi anlamda? Bu nasıl iğrenç ve 1 Ocak değil mi? strftime bir sebepten dolayı var. Ben sadece katılmıyorum. Bence bu YOL temizleyici.
Paolo Bergantino

1
Strftime kullanmak dolaylıdır, çünkü bir sayıdan bir dize üretir: zamanuple.tm_yday üyesi. Kaynağı okuyun. Üretilen dizge herhangi bir hesaplamadan / karşılaştırmadan önce bir sayıya dönüştürülmelidir, öyleyse neden zahmet edelim?
tzot

2
Bir dizede yılın gününe ihtiyaç duyuluyorsa, örneğin bir dosya adında kullanmak için, strftime çok daha temiz bir çözümdür.
captain_M

13

DZinX'in cevabı , soru için harika bir cevap. Ters fonksiyonu ararken bu soruyu buldum. Bunu işe yarayacak buldum:

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

Buradaki görgü kurallarından emin değilim, ancak ters işlevin bir göstericisinin benim gibi diğerleri için yararlı olabileceğini düşündüm.


6

Python 3.4, Linux x64 üzerinde farklı yaklaşımların performansını sunmak istiyorum. Hat profilleyiciden alıntı:

      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
         (...)

Yani en verimli

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

1
Performansı nasıl hesapladınız? Time.time kullanmayı denedim ve sonuçlarım şunlar: def f (): (bugün - datetime.datetime (bugün.year, 1, 1)). Days + 1 start = time.time (); f (); print ('Geçmiş {}'. format (zaman.saat () - başlangıç)); Süresi dolan 5.221366882324219e-05 def f (): int (today.strftime ('% j')); başlangıç ​​= time.time (); f (); print ('Geçmiş {}'. format (zaman.saat () - başlangıç)); Süre doldu 7.462501525878906e-05
ssoto

5

Sadece 1 Ocak'ı şu tarihten çıkarın:

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

1
Paolo aleyhinde bir şey yok, ancak datetime.timedelta gün cinsinden ifade edilir (elbette saniye ve mikrosaniye olarak), bu yüzden doğal bir seçim - kesinlikle dize biçimlendirmesinden daha doğrudan
zweiterlinde

1
d.toordinal () - tarih (g. yıl, 1, 1) .toordinal () + 1 belgelere göre daha standarttır. Tüm zaman dizisini oluşturmadan kabul edilen cevaba eşdeğerdir.
Dingle

5

datetimeModülü kullanmaktan kaçınmanız için bir nedeniniz varsa , bu işlevler çalışacaktır.

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

Bu kod, giriş bağımsız değişkeni olarak bir tarih alır ve yılın gününü döndürür.

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.