見出し画像

Djangoで生年月日を扱いやすくするライブラリを作成しました

ここ1年くらいはもくもく会だとかOSS関連の活動ができていませんでしたが、最近になって時間ができてきたので、以前作り始めていたけど放置していたDjangoのライブラリの開発を行っていましたので、そちらの紹介になります。

作ったライブラリはdjango-jp-birthdayというもので、pypiにも公開しましたので開発した経緯や使い方についても軽くご紹介します。

和暦の生年月日を扱う人にとってはオススメのライブラリだと思います。

開発した経緯

自分でも何かOSSでも作っていみたいなと考えていた時、Djangoに組み込めるようなライブラリを作れないかと思い、他のライブラリを探してみてはそれらを参考にしてみました。

しばらくリポジトリを作って放置していましたが、最近になって時間が取れたので、開発を再開してpypiにも公開しました。

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

以下のようなbirthdayというDatefield型のフィールドを持つモデルです。

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

   def __str__(self):
        return self.name

仮にこのbirthdayという西暦の生年月日を和暦に変換したい場合はどうしたら良いでしょうか。

以下のようにbirthdayというフィールドを取得してから、和暦に変換する処理を自分で書かなければいけません

m = ModelTestUser.objects.filter(id=1).first()
birthday = m.birthday

print(birthday)
# 1995-01-05
# datetime.date型の値


# 何らかの手段で西暦を和暦に変換
jp_era_birthday = convert_to_jp_era(birthday)
# h-7-01-05

例えば1995-01-05というdatetime.date型の値を取得したとして、それを何らかの方法で和暦に変換して、「平成7年-01月-05日」となるようにしなければいけません。

以前、西暦を和暦にする方法についての記事を書きました。

以下の方法のようにerajpというパッケージを用いて、変換するやり方もあります。

上記のように西暦から和暦に変換する処理を自分で書かなければいけないのは少し面倒です。

このように日本人であれば生年月日で和暦に関することは必ずつきまとう問題だと思います。

他にも平成や昭和世代の人達だけに絞りたいといった、年号毎に生年月日を絞りたい場合の処理などを以下のように自分で書かなければいけません。

# 平成世代の生年月日の人達だけに絞る

birthdays = ModelTestUser.objects.filter(
   birthday__range=["1998-01-08", "2019-04-30"]
)

平成は1989-01-08 〜 2019-04-30まで続いたので、上記のようにbirthday__rangeに範囲を入れます。

和暦は西暦と違って考慮しなければいけないことがたくさんあると思います。

和暦のことを考慮した用途のためのライブラリとして、django-jp-birthdayというのを開発しました。

使い方

pipでインストールができます。

$ pip install django-jp-birthday

django-birthdayというライブラリが別にあり、そちらをかなり参考にしました。ただし、django-model-utilsdjango-ordered-modelみたいにベースとなるモデルを継承すれば、簡単に扱えるようになってはいませんでした。

以下がdjango-birthdayのREADMEにも掲載されているサンプルコードです。FieldとManagerを自分で加えなければいけないのが不便です。

from django.db import models
from django.conf import settings

from birthday import BirthdayField, BirthdayManager


class UserProfile(models.Model):
   user = models.ForeignKey(settings.AUTH_USER_MODEL)
   birthday = BirthdayField()

   objects = BirthdayManager()

以下のdjango-model-utilsのようにStatusModelやSoftDeletableModelを継承すれば簡単に扱えるようにしたいです。

from model_utils.models import StatusModel

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

django-jp-birthdayでも同様にBirthdayModelというクラスを継承すれば簡単に使えるようにしました。

後は通常通りにmakemigrationsして、migrateすれば大丈夫です。モデルにはbirthdayというフィールドが自動的に付与されます。

from jp_birthday.models import BirthdayModel

class ModelsTest(BirthdayModel):

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

次に用意されているメソッド類について紹介していきます。

和暦への変換

メインとなる機能です。西暦の値であるbirthdayから、和暦に変換して取得するには以下を実行します。

birthdayには1995-01-5の値が入っているとします。

# id: 1
# birthday: 1995-01-05
m = ModelsTest.objects.filter(id=1).first()

m.get_jp_era_birthday()
# h-7-1-5

実行すると和暦でh-7-1-5が返ってきます。<年号>-<年>-<月>-<日>の形式で返ってきます。

漢字の「平成」、ひらがなの「へいせい」と行った文字列を取り出したい時は、以下のように引数にTrueを加えてください。

辞書型で以下のように値が返ってきます。

# id: 1
# birthday: 1995-01-05
m = ModelsTest.objects.filter(id=1).first()

m.get_jp_era_birthday(True)
# {'era': 'heisei', 'era_short': 'h', 'era_jp': 'へいせい', 'era_kanji': '平成', 'year': 13, 'month': 1, 'day': 1})

年号で絞った生年月日を全て取得

次に上記の冒頭でも紹介したように年号で生年月日を絞りたい場合は、以下のような処理を実行します。

# 以下のような生年月日が登録されているとする
# ["2001-01-01", "2000-01-02", "2002-12-31", "1980-03-01", "1970-12-10"]

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"]

上記であれば平成年代の生年月日が取得できています。引数に入れる年号は英字でも漢字でも取得できます。

その他便利な機能

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

2つだけ紹介します。

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

以下の例では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(days=30, after=jan1)
# ["2001-01-01", "2000-01-02", "1995-01-05"]


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

以下の例では本日が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"]


実装済みの機能の一覧

黒く塗られている所がこの記事で紹介した機能になります。この記事で紹介していない他の機能についてはGitHubのREADMEか以下のZenn.devで投稿した記事を参照してください。


誕生日を和暦で表示
年号で絞った生年月日を全て取得
・誕生日から年齢を表示
・誕生日の干支を表示
・誕生日年の元号がどれくらい続いたかの年数を表示

指定した日付以内の誕生日のユーザーを取得
指定した日が誕生日のユーザーを全て取得
・生まれた年は関係なく生年月日を誕生日順に並べる

今後開発予定の機能は以下になります

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

こういった機能が欲しいなどの要望や提案があれば、以下のIssueで気軽にコメントをお願いいたします。

その他、バグ等があればIssueやtwitterのDM等で報告いただければ幸いです。

リンク




この記事が気に入ったらサポートをしてみませんか?