Python 从整数开始的日期和月份

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

有人能告诉我如何从一个代表一年中某一天的整数中得到日和月吗?例如,32应该是2月1日,308应该是11月11日

我编写了一个返回值的代码,但是很长,不能同时返回两个值,月和日

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。