読者です 読者をやめる 読者になる 読者になる

星座・干支を取得

Python

datetime.date, datetime.datetimeオブジェクトから、12星座名・干支を取得する。

だいぶ昔に書いたコードなんだけれど、これで合っているのかな?

>>> zodiac
>>> from datetime import date
>>> zodiac.get_zodiac(date(1978, 12, 4))
'sagittarius'
>>> zodiac.get_chinese_zodiac(date(1978, 12, 4))
'horse'
# -*- coding: utf-8 -*-
# zodiac.py
from datetime import date, datetime, timedelta

__all__ = ['get_zodiac', 'get_chinese_zodiac']

def _init_zodiac():
    map = {}
    signs = (('aries', (3, 21), (4, 19)),
             ('taurus', (4, 20), (5, 21)),
             ('gemini', (5, 22), (6, 20)),
             ('cancer', (6, 21), (7, 23)),
             ('leo', (7, 24), (8, 23)),
             ('virgo', (8, 24), (9, 23)),
             ('libra', (9, 24), (10, 23)),
             ('scorpio', (10, 24), (11, 22)),
             ('sagittarius', (11, 23), (12, 21)),
             ('capricorn', (12, 22), (12, 31)),
             ('capricorn', (1, 1), (1, 20)),
             ('aquarius', (1, 21), (2, 19)),
             ('pisces', (2, 20), (3, 20)),
             )
    for sign, start, end in signs:
        current = date(2000, start[0], start[1])
        limit = date(2000, end[0], end[1])

        while current <= limit:
            map[(current.month, current.day)] = sign
            current += timedelta(1)

    return map

def get_zodiac(dt, _zodiac={}):
    """
    returns the zodiac for the given date.
    """
    if not isinstance(dt, (date, datetime)):
        raise ValueError, 'Invalid argument. date or datetime is expected, but %r is given' % dt

    try:
        return _zodiac[(dt.month, dt.day)]
    except KeyError:
        _zodiac.update(_init_zodiac())
        try:
            return _zodiac[(dt.month, dt.day)]
        except KeyError:
            raise RuntimeError, "Opps! something wrong, sorry!"

def get_chinese_zodiac(dt):
    """
    return the chinese zodiac for the given date.
    """
    if not isinstance(dt, (date, datetime)):
        raise ValueError, 'Invalid argument. date or datetime is expected, but %r is given' % dt

    return ('monkey',
            'rooster',
            'dog',
            'pig',
            'rat',
            'ox',
            'tiger',
            'rabbit',
            'dragon',
            'snake',
            'horse',
            'sheep')[dt.year % 12]

if __name__ == '__main__':
    dt = date(1978, 12, 4)
    for x in xrange(365):
        assert get_zodiac(dt)
        dt += timedelta(days=1)

    for y in xrange(1978, 2078):
        dt = date(y, 12, 4)
        assert get_chinese_zodiac(dt)

同じことをはてなグループに書いた気がするが、検索する時間も惜しいわ。