Python 从整数开始的日期和月份
有人能告诉我如何从一个代表一年中某一天的整数中得到日和月吗?例如,32应该是2月1日,308应该是11月11日 我编写了一个返回值的代码,但是很长,不能同时返回两个值,月和日Python 从整数开始的日期和月份,python,Python,有人能告诉我如何从一个代表一年中某一天的整数中得到日和月吗?例如,32应该是2月1日,308应该是11月11日 我编写了一个返回值的代码,但是很长,不能同时返回两个值,月和日 def normyear(fix): if fix > 31 : if fix > 59 : if fix > 90 : if fix > 120 : if fix > 15
def normyear(fix):
if fix > 31 :
if fix > 59 :
if fix > 90 :
if fix > 120 :
if fix > 151 :
if fix > 181 :
if fix > 212 :
if fix > 243 :
if fix > 273 :
if fix > 304 :
if fix > 334 :
if fix > 365 :
print "Invalid id number please try again"
else :
day = (fix - 334)
month = 12
else :
day = (fix - 304)
month = 11
else :
day = (fix - 273)
month = 10
else :
day = (fix - 243)
month = 9
else :
day = (fix - 212)
month = 8
else :
day = (fix - 181)
month = 7
else :
day = (fix - 151)
month = 6
else :
day = (fix - 120)
month = 5
else :
day = (fix - 90)
month = 4
else :
day = (fix - 59)
month = 3
else :
day = (fix - 31)
month = 2
else :
day = mid
month = 1
return day
return month
您只需使用以下命令即可解析:
>>> from datetime import datetime
>>> dayOfYear = 64
>>> d = datetime.strptime('{} 2015'.format(dayOfYear), '%j %Y')
>>> d.day
5
>>> d.month
3
请注意,您需要提供一年,以便正确处理闰年。在本例中,我将当前2015年硬编码到其中
如果您想亲自去那里,而不使用datetime模块来处理此问题,您也可以这样解决:
>>> months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
>>> dayOfYear = 64
>>> for month, monthDays in enumerate(months):
if dayOfYear - monthDays > 0:
dayOfYear -= monthDays
else:
print('Month:', month + 1) # +1 because it’s zero-indexed
print('Day:', dayOfYear)
break
Month: 3
Day: 5
除了一个更简单的逻辑之外,这与您的代码做了类似的事情:只要还有比当前月份更多的天数,它就会不断减去一个月的天数。在执行此操作时,它使用enumerate here计算经过的月份。因此,最后,剩余的天是一个月中的一天,而过去的月数是一个月。由于闰年的原因,您不仅需要一年中的一天,还需要一年中的一天。也就是说:
from datetime import datetime
from datetime import timedelta
def month_and_day_from_year_day(year, day):
date = datetime(year, 1, 1) + timedelta(day - 1)
return (date.month, date.day)
下面的代码比较了各种日数算法与日和月算法的速度。它还有两个用于测试这些算法的函数。除了Poke和Cyphase的算法外,我还包括了一个使用奥术运算的算法 我将不详细介绍,但算术算法的工作原理是将日历旋转到年底的二月。旋转日历比普通日历规则得多:它由5个月的重复块组成。每个街区有153天,月长从长到短交替
#!/usr/bin/env python
''' daynum tests
Time various algorithms to compute the day & month
given the year and the day number
From http://stackoverflow.com/q/32047520/4014959
Typical timing results:
daynum_to_daymon0: Poke 1
[3.0101921558380127, 3.058804988861084, 3.0825381278991699]
daynum_to_daymon1: PM 2Ring
[0.1977241039276123, 0.20353794097900391, 0.20514988899230957]
daynum_to_daymon2: Cyphase
[0.28950190544128418, 0.29159307479858398, 0.31502914428710938]
daynum_to_daymon3: Poke 2
[0.36095499992370605, 0.38256311416625977, 0.4053041934967041]
'''
from datetime import datetime, timedelta
from timeit import Timer
def is_leap(year):
return (year % 4 == 0) and (year % 100 != 0) or (year % 400 == 0)
def daynum_to_daymon0(daynum, year):
''' Poke 1'''
dy = '{0} {1}'.format(daynum, year)
d = datetime.strptime(dy, '%j %Y')
return d.day, d.month
def daynum_to_daymon1(daynum, year):
''' PM 2Ring '''
isleap = is_leap(year)
d = (daynum - 60 - isleap) % (365 + isleap)
mon, day = divmod(d * 5 + 2, 153)
return day // 5 + 1, (mon + 2) % 12 + 1
def daynum_to_daymon2(day, year):
''' Cyphase '''
date = datetime(year, 1, 1) + timedelta(day - 1)
return date.day, date.month
def daynum_to_daymon3(dayOfYear, year):
''' Poke 2 '''
months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
months[1] += is_leap(year)
for month, monthDays in enumerate(months):
if dayOfYear - monthDays > 0:
dayOfYear -= monthDays
else:
break
return dayOfYear, month + 1
funcs = (
daynum_to_daymon0,
daynum_to_daymon1,
daynum_to_daymon2,
daynum_to_daymon3,
)
def dump_year(daynum_to_daymon, year):
''' Print a list of days for each month of the year '''
isleap = is_leap(year)
print daynum_to_daymon.func_name
print year, ('!=', '==')[isleap], 'leap year'
oldm = ''
for daynum in range(1, 1 + 365 + isleap):
d, m = daynum_to_daymon(daynum, year)
if m != oldm:
if oldm:
print oldm, buff
oldm = m
buff = []
buff.append(d)
if buff:
print oldm, buff
def compare(func0, func1, y0, y1):
''' Verify that 2 functions produce the same results
for years in the range(y0, y1)
'''
print 'Comparing %s and %s' % (func0.func_name, func1.func_name)
print 'Testing %d to %d (inclusive)' % (y0, y1)
for year in range(y0, y1+1):
isleap = is_leap(year)
for daynum in range(1, 1 + 365 + isleap):
t0 = func0(daynum, year)
t1 = func1(daynum, year)
assert t0 == t1, (t0, t1)
print 'OK'
def test(daynum_to_daymon, y0, y1):
''' Compute day & month for all days in the given (inclusive) year range
No output is generated because this function is used to perform
timeit tests
'''
for year in range(y0, y1+1):
for daynum in range(1, 366 + is_leap(year)):
t = daynum_to_daymon(daynum, year)
def time_test():
reps, loops = 3, 60
for func in funcs:
fname = func.func_name
print '%s: %s' % (fname, func.__doc__)
setup = 'from __main__ import test, %s' % fname
t = Timer('test(%s, 1995, 1996)' % fname, setup)
r = t.repeat(reps, loops)
r.sort()
print r
if __name__ == "__main__":
dump_year(daynum_to_daymon1, 2015)
compare(daynum_to_daymon0, daynum_to_daymon1, 1995, 2015)
time_test()
典型输出
daynum_至_daymon1
2015 != 闰年
1 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
2 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28]
3 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
4 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
5 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
6 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
7 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
8 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
9 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
10 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
11 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
12 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
比较daynum_和daymon0以及daynum_和daymon1
测试1995年至2015年(含)
好啊
daynum_to_daymon0:1
[2.8590669631958008, 2.9910919666290283, 3.0923340320587158]
daynum_to_daymon1:PM 2Ring
[0.20377802848815918, 0.20526909828186035, 0.21576380729675293]
daynum_至_daymon2:cPhase
[0.29232597351074219, 0.29248213768005371, 0.2969820499420166]
daynum_to_daymon3:Poke 2
[0.34156394004821777, 0.34333705902099609, 0.34701800346374512]
虽然算术算法是最快的,但我建议使用Cyphase的算法,除非您真的需要速度,在这种情况下,您使用Python做什么?。Cyphase的算法更易于阅读和理解;算术算法确实需要大量的文档来解释它的工作原理。使用这样聪明的算法不利于:
每个人都知道调试的难度是用计算机编写程序的两倍
第一位。所以如果你在写作时尽可能聪明的话
它,你将如何调试它
我的眼睛!Protip:如果你发现自己写的梯形图代码是这样的,那你就大错特错了,有一种更简单的方法来表达你的想法。如果fix>365:打印无效的id号闰年呢?@Tim更一般地说,二月之后,闰年的事情会变得很奇怪……应该有人开个箭头玩笑。我对python有点陌生,我的想法是嵌套if比else if更容易让pc处理@TimCastelijns,我为闰年做了一个类似的代码,但后来发现这个代码是不必要的,因为我的本地id系统在计算闰年时考虑了这两个因素。Thanx peeps:你忘了闰年了。@cPhase到底在哪里?我确实明确地提到了闰年,对吧
e、 但我的意思是在非日期时间方法中。@cPhase我的解决方案使用了一个灵活的每月天数列表,如果您想使用闰年的数字,您可以轻松地进行调整。这是一个“硬编码”值,就像2015年一样,你可以很容易地调整。当然,在第一种方法中,使年份动态也很简单,而在第二种方法中,你必须编写闰年检查代码。只是说说而已。IMO使用datetime总比手动操作好。您可能希望在return语句中切换月和日的顺序,以反映方法名称中的顺序,反之亦然@福尔科,谢谢你指出这一点。也很好地抓住了额外的帕伦斯;我本来打算去约会的,但我改变了主意。因为它们对任何事情都没有影响,所以我错过了它们:。FWIW,这种方法比使用.strtime.In d=daynum-60-isleap%365+isleap快10倍左右,对于任何可能的一年中的某一天,d都将始终是daynum-60-isleap。@cPhase:当daynum<60+isleap时,即1月或2月的几天,该怎么办?模数运算确保这些天的d为正。low,d=daynum-60-isleap%365+isleap循环日历,将1月和2月放在年底,允许我们利用我上面提到的5个月模式。这也让我们忽略了一个事实,二月是一个超短的月份。。忘了那些吧:P。