在Python中将年/月/日转换为年份


127

我正在使用Python datetime模块,即:

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

我想计算对leap年敏感的一年中的某天。例如今天(2009年3月6日)是2009年的65日。 这是基于Web的DateTime计算器

无论如何,我看到两个选择:

A.创建一个number_of_days_in_month数组= [31,28,...],确定是否为a年,手动汇总天数。

B.用于datetime.timedelta猜测,然后二进制搜索一年中的正确日期:

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

这些都感觉很笨拙,而且我有一种直觉,觉得有一种更“ Pythonic”的方式来计算一年中的某天。有什么想法/建议吗?

Answers:


255

有一个非常简单的解决方案:

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

13
一个很小的而且可以说是书呆子的加法,但是使用date.today()而不是datetime.now()也可以起作用,并且更加强调了操作的性质。
杰里米

5
更好的是:time.localtime().tm_yday 无需将日期时间转换为时间元组,因为那是localtime()的结果。
Mike Ellis

14
@MikeEllis但是此解决方案说明了datetime与今天不对应时的处理方式。
格里特2014年

2
注意:此时间开始于1
Mehdi Nellen

1
如果我想做相反的事情,我让数字说“ 2020年第26天”,然后将其转换为日期“ 26-01-2020”怎么办?
桑卡尔

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日”算法。无需查找有关strftime的'%j'的琐事,就可以使它更干净,更明显。
S.Lott

12
认真吗 1月1日这个糟糕透顶的日子如何?strftime之所以存在是有原因的。我只是不同意。我认为这更清洁。
Paolo Bergantino,2009年

1
使用strftime是间接的,因为它从一个数字生成一个字符串:timetuple.tm_yday成员。阅读源代码。在进行任何计算/比较之前,应将生成的字符串转换为数字,那么为什么要打扰呢?
tzot

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():(今天-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')); 开始= time.time(); F(); print('Lapsed {}'。format(time.time()-start)); 失效7.462501525878906e-05
ssoto

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是以天为单位(当然还有秒和微秒),因此这是一种自然的选择-比字符串格式肯定更直接
zweiterlinde

1
d.toordinal()-date(d.year,1,1)。根据文档,toordinal()+ 1更标准。它等效于接受的答案,而不会产生整个时间元组。
Dingle 2010年

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.