I wrote a class to handle "years and months" in Python, but later realized that it could be done by using dateutil, so it was a memorial service. I wrote it with momentum and there is no test, so use it at your own risk.
import re
from datetime import date
class ym:
"""Data type that handles the year and month"""
def __init__(self, y: int, m: int = None):
if type(y) is date:
y, m = y.year, y.month
if not (0 <= y <= 10000 and 1 <= m <= 12):
raise ValueError()
self.x = y * 12 + m - 1
@classmethod
def current(cls):
return cls(date.today())
@classmethod
def parse(cls, s: str):
matched = re.match(r"^(\d+)-(\d+)$", s)
if not matched:
raise ValueError()
return cls(int(matched[1]), int(matched[2]))
@property
def y(self):
return self.x // 12
@property
def m(self):
return self.x % 12 + 1
def to(self, y, m=None) -> list:
target = y if type(y) is self.__class__ else self.__class__(y, m)
return [self + i for i in range(target - self)] if self < target else []
def __repr__(self):
cls = self.__class__
return f"{cls.__module__}.{cls.__name__}({self.y}, {self.m})"
def __str__(self):
return f"{self.y:04d}-{self.m:02d}"
def __add__(self, n: int):
if type(n) is int:
return self.__class__((self.x + n) // 12, (self.x + n) % 12 + 1)
raise TypeError()
def __sub__(self, n):
if type(n) is int:
return self + (-1 * n)
if type(n) is self.__class__:
return self.x - n.x
raise TypeError()
def __eq__(self, other):
return self.x == other.x
def __ne__(self, other):
return self.x != other.x
def __lt__(self, other):
return self.x < other.x
def __gt__(self, other):
return self.x > other.x
ym(2020, 4) #=> ym(2020, 4)
ym.current() #=> ym(2020, 7)
ym.parse("2020-04") #=> ym(2020, 4)
from datetime import date
ym.parse(date.today()) #=> ym(2020, 7)
from datetime import datetime
dt = dateime.now()
ym.parse(dt.date()) #=> ym(2020, 7)
current = ym.current() #=> ym(2020, 7)
current.y #=> 2020
current.m #=> 7
ym(2020, 04) + 10 #=> ym(2021, 2)
ym(2020, 04) - 10 #=> ym(2019, 6)
ym(2020, 7) - ym(2020, 4) #=> 3
ym(2020, 7) < ym(2020, 4) #=> False
ym(2020, 7) > ym(2020, 4) #=> True
ym(2020, 7) == ym(2020, 4) #=> False
ym(2020, 4).to(2020, 7) #=> [ym(2020, 4), ym(2020, 5), ym(2020, 6)]
current = ym.current() #=> ym(2020, 7)
current.to(current + 6) #=> [ym(2020, 7), ym(2020, 8), ym(2020, 9), ym(2020, 10), ym(2020, 11), ym(2020, 12)]
Recommended Posts