【问题标题】:How would I determine zodiac / astrological star sign from a birthday in Python?我如何从 Python 中的生日确定生肖/占星术星座?
【发布时间】:2025-12-03 17:00:01
【问题描述】:

我正在用 Django / Python 构建一个约会网站。我有生日日期,需要根据生日显示此人的星座。

以前有人做过吗?实现这一目标的最有效方法是什么?

【问题讨论】:

    标签: python django date


    【解决方案1】:

    我以前做过。我最终得到的最简单的解决方案是以下键/值的数组:

    120:Cap, 218:Aqu, 320:Pis, 420:Ari, 521:Tau,
    621:Gem, 722:Can, 823:Leo, 923:Vir, 1023:Lib
    1122:Sco, 1222:Sag, 1231: Cap
    

    然后您以mdd 格式写入出生日期,即月份编号(以 1 开头的一月)和两位数的日期编号 (01-31)。遍历数组,如果日期小于或等于数组中的某一项,你就有了你的星号。

    编辑 我需要这个,所以这是一个作为工作功能的概念

    zodiacs = [(120, 'Cap'), (218, 'Aqu'), (320, 'Pis'), (420, 'Ari'), (521, 'Tau'),
               (621, 'Gem'), (722, 'Can'), (823, 'Leo'), (923, 'Vir'), (1023, 'Lib'),
               (1122, 'Sco'), (1222, 'Sag'), (1231, 'Cap')]
    def get_zodiac_of_date(date):
        date_number = int("".join((str(date.date().month), '%02d' % date.date().day)))
        for z in zodiacs:
            if date_number <= z[0]:
                return z[1]
    

    【讨论】:

    • +1 - 这看起来是无需安装新模块即可完成的最佳解决方案。
    • 对于您可以使用bisect 的查找,请参阅docs.python.org/library/bisect.html#bisect.bisect 中的示例。
    • 在不经常使用的功能中对 13 个键使用 bisect 有点过度优化,你不觉得吗?此外,log_2(13) 是 3.7,所以你只有 13/3.7 = 3.5 倍的操作。我担心 bisect 中的一项操作可能比简单循环花费 3.5 倍以上,因此您的性能甚至会更差。总而言之,bisect 是大多数搜索案例中非常好的建议形式,但可能不是这个。
    • 我也会使用字典,但像这样:d[bisect(d.keys(),121)],导致“Sag”。与其说是速度,我认为它看起来比为此编写一个循环更好。
    • 你可以用date_number = date.date().month * 100 + date.date().day代替date_number = int("".join((str(date.date().month), '%02d' % date.date().day)))
    【解决方案2】:

    您可以向他们提供有关position of the planets 和星星的更多信息。

    import ephem 
    >>> u = ephem.Uranus()
    >>> u.compute('1871/3/13')
    >>> print u.ra, u.dec, u.mag
    7:38:06.27 22:04:47.4 5.46
    >>> print ephem.constellation(u)
    ('Gem', 'Gemini')
    

    【讨论】:

    • 在完美的世界中,您可以使用ephem 库来找出黄道十二宫,只需在示例中将天王星替换为太阳即可。然而,似乎标志和星座don't match up exactly。还有一个名为 oroboros 的占星术专用 Python 库,但它可能有点矫枉过正。
    【解决方案3】:

    使用 bisect 比迭代直到找到匹配项更有效,但一年中每一天的查找表仍然更快,而且实际上并没有那么大。

    from bisect import bisect
    signs = [(1,20,"Cap"), (2,18,"Aqu"), (3,20,"Pis"), (4,20,"Ari"),
             (5,21,"Tau"), (6,21,"Gem"), (7,22,"Can"), (8,23,"Leo"),
             (9,23,"Vir"), (10,23,"Lib"), (11,22,"Sco"), (12,22,"Sag"),
             (12,31,"Cap")]
    def zodiac_sign(m,d):
        return signs[bisect(signs,(m,d))][2]
    
    assert zodiac_sign(3,9) == "Pis"
    assert zodiac_sign(6,30) == "Can"
    

    【讨论】:

      【解决方案4】:
      var ZZ=[1231,1222,1122,1023,923,823,722,621,521,420,321,220,121];
      
      var ZN=['Capricorn','Sagittarius','Scorpio','Libra','Virgo','Leo','Cancer', 'Gemini','Taurus','Aries','Pisces','Aquarius','Capricorn'];
      
      var d8=new Date();
      
      var m=d8.getMonth()+1;
      
      var d=d8.getDate();
      
      //m=1;d=1
      
      var mdd=parseInt(''+m+(d<9?'0'+d:d));
      
      var i=0;while(ZZ[i]&gt;mdd && i&lt;ZZ.length){i++}--i;
      
      var RV='Born '+m+'/'+d+' - Star Sign: '+ZN[i];RV
      

      【讨论】:

        【解决方案5】:

        这是我的算法,不使用循环(JS 逻辑:使用 js 对象)

        var zods = {
                    0:{limit:21,vals:["aqu","cap"]},
                    1:{limit:20,vals:["pis","aqu"]},
                    2:{limit:21,vals:["ari","pis"]},
                    3:{limit:21,vals:["tau","ari"]},
                    4:{limit:21,vals:["gem","tau"]},
                    5:{limit:21,vals:["can","gem"]},
                    6:{limit:22,vals:["leo","can"]},
                    7:{limit:22,vals:["vir","leo"]},
                    8:{limit:22,vals:["lib","vir"]},
                    9:{limit:22,vals:["sco","lib"]},
                    10:{limit:23,vals:["sag","sco"]},
                    11:{limit:22,vals:["cap","sag"]}
                    };
        
                var dt = new Date();
                var zodObj = zods[dt.getMonth()];
                return dt.getDate()>=zodObj.limit?zodObj.vals[0]:zodObj.vals[1];
        

        【讨论】:

          【解决方案6】:
          def zodiac(day,month):
              signs=[('Capricorn',19),('Aquarius',18),('Pisces',20),('Aries',19),('Taurus',20),('Gemini',20) ,('Cancer',22),('Leo',22) ,('Virgo',22) ,('Libra',22) ,('Scorpio',21),('Sagittarius',21),('Capricorn',)]
              if(day<=signs[month-1][1]):
                  return signs[month-1][0]
              else:
                  return signs[month][0]
          

          【讨论】: