🎂

生年月日を扱いやすくするdjango-jp-birthdayというライブラリを作成

2022/02/10に公開

django-jp-birthdayというDjangoのモデル上で和暦の年号を扱いやすくするためのライブラリを開発しました。

https://pypi.org/project/django-jp-birthday/

ユーザーなどの生年月日を登録できるようにしたいと思ったときには、西暦の日にちを登録するために以下のようなbirthdayというDateField型のフィールドを持つモデルを作ると思います。

class ModelTestUser(models.Model):
    birthday = models.DateField(auto_now=True)

   def __str__(self):
        return self.name

このbirthdayという西暦の生年月日を和暦に変換したい場合は、自分で西暦から和暦に変換する処理を書くか、erajpのようなライブラリを使う必要があります。

https://github.com/recruit-mtl/erajp

インストール

以下のコマンドでpipインストールができます。

$ pip install django-jp-birthday

GitHubはこちらになります

https://github.com/shimakaze-git/django-jp-birthday

使用方法

以下のdjango-model-utilsみたいに、モデルを継承させるだけで使えるようにすることを目指しました。

from model_utils.models import StatusModel

class Article(StatusModel):
   title = models.CharField(max_length=100)

BirthdayModelというモデルが用意されているため、これをDjangoのモデルクラスに継承させてください。

from jp_birthday.models import BirthdayModel

class ModelsTest(BirthdayModel):

    class Meta:
        app_label = 'jp_birthday'
        ordering = ('pk',)

BirthdayModelを継承させたモデルクラスを作ると、自動的にbirthdayというDateField型のフィールドが内部で作られます。

モデルクラスを作成したら、通常のモデルクラス通りに以下のコマンドでマイグレーションを処理を行ってください。

$ python manage.py makemigrations
$ python manage.py migrate

生年月日の登録

birthdayフィールドはDateFiled型なので、pythonのdatetime.date型で値を入れる必要があります。

birthday = "1995-01-01"
model_test = ModelTest(
    birthday=datetime.strptime(birthday, "%Y-%m-%d").date()
)

実装されている機能

現時点では8種類のメソッドを用意しています。

和暦への変換

上記の西暦1995-01-01は、和暦にすると平成7年1月5日になります。西暦で登録したフィールドを簡単に和暦を返してくれるメソッドを呼び出してみます。

get_jp_era_birthdayというメソッドを実行すると、生年月日を自動で和暦に変換した結果を返してくれます。

# 仮にid=1のbirthdayフィールドが1995-01-01だった場合
m = ModelTest.objects.filter(id=1).first()

jp_era_birthday = m.get_jp_era_birthday()
print(jp_era_birthday)

上記を実行すると以下のような結果が出力され、西暦から和暦に変換されていることがわかります。hは平成を表しており、<年号>-<年号の年>-<月>-<日>で表示されます。

h-7-1-1

和暦の年号のアルファベットの頭文字ではなく、かたかなや漢字を取得したい場合は、引数にTrueを入れると、漢字での書き方が辞書型で返ってきます。

# 仮にid=1のbirthdayフィールドが1995-01-01だった場合
m = ModelTest.objects.filter(id=1).first()

jp_era_birthday = m.get_jp_era_birthday(True)
print(jp_era_birthday)

# {'era': 'heisei', 'era_short': 'h', 'era_kanji': '平成', 'year': 7, 'month': 1, 'day': 1}

年号毎の生年月日を取得する

例えば令和生まれの人だけ、平成生まれの人だけと行った感じで、年号毎で生年月日を絞りたいといったことがあると思います。

そういったことのためにも、get_jp_era_birthdaysというメソッドに、年号の引数を入れることで、年号毎に生年月日を絞った結果を返してくれます。

例えば以下のような年号の生年月日の人達が登録されていたとします。

# 明治 ["1905-1-2", "1905-1-1", "1905-2-1", "1905-2-2"]
# 昭和 ["1980-7-7", "1975-1-1"]
# 平成 ["2000-01-02", "2001-01-01", "2002-12-31"]

ここから平成の年号の人達に絞った生年月日を取得したい場合は、以下のようになります。get_jp_era_birthdaysの引数は、英字、ひらがな、漢字でもどれでも指定できます。

birthdays = ModelTest.objects.get_jp_era_birthdays("heisei")
# ["2001-01-01", "2000-01-02", "2002-12-31"]

birthdays = ModelTest.objects.get_jp_era_birthdays("へいせい")
# ["2001-01-01", "2000-01-02", "2002-12-31"]

birthdays = ModelTest.objects.get_jp_era_birthdays("平成")
# ["2001-01-01", "2000-01-02", "2002-12-31"]

干支の取得

生年月日から干支を取得するには、get_zodiacというのを実行します。
1995-01-5が生年月日であれば、が返ってきます。

# ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"]

# id: 1
# ["1995-01-05"]

m = ModelTest.objects.filter(id=1).first()
birthday = m.get_zodiac()
# 亥

生年月日から年齢を取得

生年月日から現時点での年齢を取得します。生年月日が1995-01-05であれば、2022-2-10時点では27歳になるため、27が返ってきます。

# id: 1
# ["1995-01-05"]

m = ModelTest.objects.filter(id=1).first()
birthday = m.get_age()
# 27

誕生日年の元号がどれくらい続いたかの年数を取得

生年月日から、その人の年号が何年間続いたのかの年数を取得します。平成生まれの人であれば、31という数字が返ってきます。

平成は1989-1-8〜2019-4-30まで続いており、平成31年が最後の年になります。

# id: 1
# ["1995-01-05"]

m = ModelTest.objects.filter(id=1).first()
birthday = m.get_jp_era_years()
# 31

他の便利な機能

django-birthdayという別なライブラリを元にして作っているため、元のライブラリで用意されていたメソッドは全て実装されています。

和暦を扱う以外にもdjango-jp-birthdayに実装されていた下記のメソッドはかなり便利です。

  • get_upcoming_birthdays
  • get_birthdays
  • order_by_birthday

指定した日付以内の誕生日のユーザーを取得

例えば指定した日付から30日以内の誕生日のユーザーを取得したいと行った場合は、get_upcoming_birthdaysを使用します。

引数はかなり多いですが、基本的には第一引数と第二引数の2つを使用します。

  • days : 日数
  • after : 基準となる日付

daysはデフォルトでは30になっており、afterだけは必ず指定する必要があります。

※以下の例では1月1日から30日以内が誕生日のユーザーを取得

# ["2001-01-01", "2000-01-02", "1995-01-05", "2002-12-31", "1980-03-01", "1970-12-10"]

jan1 = date(year=2010, month=1, day=1)
birthdays = ModelsTest.objects.get_upcoming_birthdays(after=jan1)
# ["2001-01-01", "2000-01-02", "1995-01-05"]

birthdays = ModelsTest.objects.get_upcoming_birthdays(days=30, after=jan1)
# ["2001-01-01", "2000-01-02", "1995-01-05"]

# 上記2つとも同じ結果になる

その他、以下の5つの引数があります。

  • days : 日数 (デフォルトは30)
  • after : 基準となる日付
  • include_day : 基準となる日付も含めるか (デフォルトはTrue)
  • order : 生年月日の並び替え (デフォルトはTrue)
  • reverse : 昇順か降順 (デフォルトはFalseで昇順)

include_dayをFalseにした場合

include_dayをFalseにすると、基準となる1/1が含まれません。

# ["2001-01-01", "2000-01-02", "1995-01-05", "2002-12-31", "1980-03-01", "1970-12-10"]

jan1 = date(year=2010, month=1, day=1)
birthdays = ModelsTest.objects.get_upcoming_birthdays(after=jan1, include_day=False)
# ["2000-01-02", "1995-01-05"]

reverseをTrueにした場合

reverseをTrueにすると降順になります。

# ["2001-01-01", "2000-01-02", "1995-01-05", "2002-12-31", "1980-03-01", "1970-12-10"]

jan1 = date(year=2010, month=1, day=1)
birthdays = ModelsTest.objects.get_upcoming_birthdays(after=jan1, reverse=False)
# ["1995-01-05", "2000-01-02", "2001-01-01"]

指定した日付が誕生日のユーザーを全て取得

指定した日付が誕生日のユーザーを年は関係なく、全て取得したい場合はget_birthdaysというメソッドを実行します。

※以下の例では本日が1/1であれば、1/1の誕生日のユーザを取得。

# ["2001-01-01", "2000-01-02", "2002-12-31", "1990-03-01", "1990-01-01"]

jan1 = date(year=2010, month=1, day=1)
birthdays = ModelsTest.objects.get_birthdays(jan1)
# ["2001-01-01", "1990-01-01"]

生まれた年は関係なく生年月日を誕生日順に並べる

order_by_birthdayメソッドを使うことで、年は関係なく1月1日を基準として生年月日順に並び替えます。同じ日付であれば、古い年の方を優先します。

# ["2001-01-01", "2000-01-02", "1995-01-05", "2002-12-31", "1980-03-01", "1970-12-10"]

jan1 = date(year=2010, month=1, day=1)
birthdays = ModelsTest.objects.order_by_birthday()
# ["2001-01-01", "2000-01-02", "1995-01-05", "1990-03-01", "1970-12-10", "2002-12-31"]

reverseという引数が一つだけあり、デフォルトではFalseになっていますが、Trueにすると逆順で並び替えます。

# ["2001-01-01", "2000-01-02", "1995-01-05", "2002-12-31", "1980-03-01", "1970-12-10"]

jan1 = date(year=2010, month=1, day=1)
birthdays = ModelsTest.objects.order_by_birthday(True)
# ["2002-12-31", "1970-12-10", "1990-03-01", "1995-01-05", "2000-01-02", "2001-01-01"]

今後実装予定の機能

  • 指定した年(和暦でも西暦でも)の誕生日が祝日であるかを表示
  • 和暦で誕生日を登録できるようにする
  • 元号毎の天皇陛下をフルネームを表示する
  • 和暦が何時代(江戸時代、安土桃山、平安、鎌倉)なのかを表示
  • 干支で生年月日を絞る

GitHubの以下のリンクのIssueで今後実装予定の機能などをまとめています。欲しい機能などの要望や提案があれば、気軽にコメントをお願いいたします。

https://github.com/shimakaze-git/django-jp-birthday/issues/1

Discussion