Dealing with "years and months" in Python

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.

Implementation

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

example

Create an instance by specifying the year and month

ym(2020, 4)  #=> ym(2020, 4)

Create an instance from the current month

ym.current()  #=> ym(2020, 7)

Create an instance from a string

ym.parse("2020-04")  #=> ym(2020, 4)

Instantiate from date object

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)

Get year, month

current = ym.current()  #=> ym(2020, 7)
current.y  #=> 2020
current.m  #=> 7

Addition and subtraction

ym(2020, 04) + 10  #=> ym(2021, 2)
ym(2020, 04) - 10  #=> ym(2019, 6)

Year / month difference

ym(2020, 7) - ym(2020, 4)  #=> 3

Comparison operation

ym(2020, 7) < ym(2020, 4)  #=> False
ym(2020, 7) > ym(2020, 4)  #=> True
ym(2020, 7) == ym(2020, 4)  #=> False

Range acquisition

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

Dealing with "years and months" in Python
[python] Calculation of months and years of difference in datetime
Until dealing with python in Atom
Tips for dealing with binaries in Python
Character encoding when dealing with files in Python 3
[Python] Dealing with multiple call errors in ray.init
Programming with Python and Tkinter
Encryption and decryption with Python
Scraping with selenium in Python
Python and hardware-Using RS232C with Python-
Scraping with chromedriver in python
Debugging with pdb in Python
Precautions when dealing with ROS MultiArray types in Python
Working with sounds in Python
Scraping with Selenium in Python
Calculate Pose and Transform differences in Python with ROS
Scraping with Tor in Python
Tweet with image in Python
Combined with permutations in Python
Stack and Queue in Python
Start numerical calculation in Python (with Homebrew and pip)
Japanese output when dealing with python in visual studio
python with pyenv and venv
Unittest and CI in Python
Works with Python and R
Consideration when you can do a good job in 10 years with Python3 and Scala3.
Design and test Verilog in Python only with Veriloggen and cocotb.
Play with Mastodon's archive in Python 2 Count replies and favourites
Install CaboCha in Ubuntu environment and call it with Python.
How to log in to AtCoder with Python and submit automatically
Communicate with FX-5204PS with Python and PyUSB
Number recognition in images with Python
Shining life with Python and OpenCV
MIDI packages in Python midi and pretty_midi
Robot running with Arduino and python
Testing with random numbers in Python
Install Python 2.7.9 and Python 3.4.x with pip.
Difference between list () and [] in Python
Neural network with OpenCV 3 and Python 3
AM modulation and demodulation with python
Difference between == and is in python
[Python] font family and font with matplotlib
Scraping with Node, Ruby and Python
View photos in Python and html
GOTO in Python with Sublime Text 3
Working with LibreOffice in Python: import
Sorting algorithm and implementation in Python
Scraping with Selenium in Python (Basic)
CSS parsing with cssutils in Python
Scraping with Python, Selenium and Chromedriver
Scraping with Python and Beautiful Soup
About dtypes in Python and Cython
Numer0n with items made in Python
Open UTF-8 with BOM in Python
Assignments and changes in Python objects
JSON encoding and decoding with python
Use rospy with virtualenv in Python3
Check and move directories in Python
Hadoop introduction and MapReduce with Python
[GUI with Python] PyQt5-Drag and drop-
Ciphertext in Python: IND-CCA2 and RSA-OAEP