Skip to content

Commit

Permalink
feat: [add] mes_por_extenso
Browse files Browse the repository at this point in the history
refactor: simplifica o código
doc: documenta essa simplificação
  • Loading branch information
kelsoncm committed Feb 12, 2024
1 parent 03e6373 commit 2fc62bd
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 32 deletions.
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ Competencia.get_instance(date(2023, 12, 25)).last_timestamp == 1704077999.0
# Para validar datas mínimas, todas linhas
class CompetenciaComMinimo(Competencia):
MIN_DATE = date(2023, 11, 1)
MIN_DATETIME = datetime(2023, 11, 1, 23, 59, 59)
MIN_INT = 1700530519
MIN_FLOAT = 1700530519.0

# Agora todas as linhas abaixo vão lançar um exception
CompetenciaComMinimo.get_instance(date(2023, 12, 1))
Expand All @@ -84,9 +81,7 @@ CompetenciaComMinimo.get_instance(1800530519.0)

class CompetenciaComMinimo(Competencia):
MIN_DATE = date(2023, 11, 1)
MIN_DATETIME = datetime(2023, 11, 1, 23, 59, 59)
MIN_INT = 1700530519
MIN_FLOAT = 1700530519.0


# Agora todas as linhas abaixo vão lançar um exception
CompetenciaComMinimo.get_instance(date(2023, 12, 1))
Expand Down
64 changes: 39 additions & 25 deletions competencias/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
from typing import List, Optional, Union, TypeVar
from datetime import date, datetime
from typing import List, Optional, Union, TypeVar, Any
from datetime import date, datetime, timezone
import calendar
from dateutil.rrule import rrule, MONTHLY
from dateutil.relativedelta import relativedelta
Expand All @@ -10,12 +10,23 @@


class Competencia(object):
FIRST_MOMENT = dict(day=1, hour=0, minute=0, second=0)
MIN_DATE = None
MIN_DATETIME = None
MIN_INT = None
MIN_FLOAT = None
TIMEZONE = timezone.utc
__instances = {}
MESES = {
1: "Janeiro",
2: "Fevereiro",
3: "Março",
4: "Abril",
5: "Maio",
6: "Junho",
7: "Julho",
8: "Agosto",
9: "Setembro",
10: "Outubro",
11: "Novembro",
12: "Dezembro",
}

def __init__(self, year: int, month: int):
"""Never create a Competencia directly, allways use get_instance.
Expand All @@ -30,30 +41,29 @@ def __str__(self):
return f"{self.date.year}/{self.date.month}"

@classmethod
def validate(cls, value: Union[int, date, datetime, float]) -> Union[date, datetime]:
if type(value) not in [int, date, datetime, float]:
raise ValueError(
f"Deve ser informado um date, datetime, int ou float, mas você informou {type(value)}={value}."
)
def _validate(cls, value: date, datetype: Any) -> date:
if cls.MIN_DATE is not None and value < cls.MIN_DATE:
raise ValueError(f"Para {datetype} a menor data é {cls.MIN_DATE}, mas você informou {value}.")
return value

def __validate(minvalue):
if minvalue is not None and value < minvalue:
raise ValueError(f"Para {type(value)} a menor data é {minvalue}, mas você informou {value}.")
return True
@classmethod
def validate(cls, value: Union[int, date, datetime, float, str]) -> date:
if value is None:
raise ValueError("Deve ser informada alguma date, mas você informou None.")

if isinstance(value, datetime) and __validate(cls.MIN_DATETIME):
return date(value.year, value.month, 1)
if type(value) not in [int, date, datetime, float, str]:
raise ValueError(
f"Deve ser informado um date, datetime, int, float ou str (AAAAMM), mas você informou {type(value)}={value}."
)

if isinstance(value, date) and __validate(cls.MIN_DATE):
return date(value.year, value.month, 1)
if isinstance(value, datetime) or isinstance(value, date):
return cls._validate(date(value.year, value.month, 1), value.__class__)

if isinstance(value, int) and __validate(cls.MIN_INT):
_value = datetime.fromtimestamp(value)
return date(_value.year, _value.month, 1)
if isinstance(value, int) or isinstance(value, float):
return cls._validate(datetime.fromtimestamp(value).date().replace(day=1), value.__class__)

if isinstance(value, float) and __validate(cls.MIN_FLOAT):
_value = datetime.fromtimestamp(int(value))
return date(_value.year, _value.month, 1)
if isinstance(value, str):
return cls._validate(date(int(value[0:4]), int(value[4:6]), 1), value.__class__)

@classmethod
def get_instance(cls, value: Union[date, datetime, int, float]) -> Competencia:
Expand Down Expand Up @@ -135,3 +145,7 @@ def first_timestamp(self) -> float:
def last_timestamp(self) -> float:
"Return POSIX timestamp as float"
return self.last_datetime.timestamp()

@property
def mes_por_extenso(self):
return self.__class__.MESES.get(self.date.month, "-")
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import sys
from setuptools import setup, find_packages

version = "1.0.3"
version = "1.0.4"
if len(sys.argv) >= 3 and sys.argv[1] == "validate_tag":
if sys.argv[2] != version:
raise Exception(f"A versão TAG [{sys.argv[2]}] é diferente da versão no arquivo setup.py [{version}].")
Expand Down
16 changes: 16 additions & 0 deletions tests/test_competencias.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import unittest
from datetime import date, datetime
from competencias import Competencia
from dateutil.zoneinfo import gettz


class TestCompetencias(unittest.TestCase):
Expand Down Expand Up @@ -28,6 +29,7 @@ class CompetenciaSemMinimo(Competencia):
self.assertEqual(CompetenciaSemMinimo.validate(datetime(2023, 11, 1, 23, 59, 59)), date(2023, 11, 1))
self.assertEqual(CompetenciaSemMinimo.validate(1700530519), date(2023, 11, 1))
self.assertEqual(CompetenciaSemMinimo.validate(1700530519.0), date(2023, 11, 1))
self.assertEqual(CompetenciaSemMinimo.validate("202311"), date(2023, 11, 1))

def test_validate_com_minimo(self):
class CompetenciaComMinimo(Competencia):
Expand Down Expand Up @@ -60,6 +62,12 @@ class CompetenciaComMinimo(Competencia):
with self.assertRaisesRegex(ValueError, ".*'float'.*"):
CompetenciaComMinimo.validate(1700530519.0)

with self.assertRaisesRegex(ValueError, ".*'list'.*"):
CompetenciaComMinimo.validate([])

with self.assertRaisesRegex(ValueError, ".* None\."):
CompetenciaComMinimo.validate(None)

def test_init(self):
self.assertIsInstance(Competencia(2023, 11), Competencia)
self.assertEqual(Competencia(2023, 11).date, date(2023, 11, 1))
Expand All @@ -68,6 +76,10 @@ def test_get_instance(self):
self.assertIsInstance(Competencia.get_instance(1700530519.0), Competencia)
self.assertEqual(Competencia.get_instance(date(2023, 11, 1)).date, date(2023, 11, 1))
self.assertEqual(Competencia.get_instance(datetime(2023, 11, 1, 23, 59, 59)).date, date(2023, 11, 1))
self.assertEqual(
Competencia.get_instance(datetime(2023, 11, 1, 23, 59, 59, tzinfo=gettz("America/Fortaleza"))).date,
date(2023, 11, 1),
)
self.assertEqual(Competencia.get_instance(1700530519).date, date(2023, 11, 1))
self.assertEqual(Competencia.get_instance(1700530519.0).date, date(2023, 11, 1))

Expand Down Expand Up @@ -128,3 +140,7 @@ def test_last_timestamp(self):

def test_str(self):
self.assertEqual(Competencia.get_instance(date(2023, 12, 25)).__str__(), "2023/12")

def test_mes_por_extenso(self):
c = Competencia.get_instance(date(2023, 12, 25))
self.assertEqual(c.mes_por_extenso, "Dezembro")

0 comments on commit 2fc62bd

Please sign in to comment.