Skip to content

Commit

Permalink
Add native datetime to pendulum_dt (#176)
Browse files Browse the repository at this point in the history
Co-authored-by: pepe-rtmlab <pepe@wont_share.com>
  • Loading branch information
07pepa and pepe-rtmlab authored May 31, 2024
1 parent b30de59 commit 1da3155
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 12 deletions.
12 changes: 12 additions & 0 deletions pydantic_extra_types/pendulum_dt.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
CoreSchema implementation. This allows Pydantic to validate the DateTime object.
"""

import pendulum

try:
from pendulum import Date as _Date
from pendulum import DateTime as _DateTime
Expand All @@ -12,6 +14,7 @@
raise RuntimeError(
'The `pendulum_dt` module requires "pendulum" to be installed. You can install it with "pip install pendulum".'
)
from datetime import date, datetime, timedelta
from typing import Any, List, Type

from pydantic import GetCoreSchemaHandler
Expand Down Expand Up @@ -68,6 +71,9 @@ def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler
if isinstance(value, _DateTime):
return handler(value)

if isinstance(value, datetime):
return handler(DateTime.instance(value))

# otherwise, parse it.
try:
data = parse(value)
Expand Down Expand Up @@ -126,6 +132,9 @@ def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler
if isinstance(value, _Date):
return handler(value)

if isinstance(value, date):
return handler(pendulum.instance(value))

# otherwise, parse it.
try:
data = parse(value)
Expand Down Expand Up @@ -184,6 +193,9 @@ def _validate(cls, value: Any, handler: core_schema.ValidatorFunctionWrapHandler
if isinstance(value, _Duration):
return handler(value)

if isinstance(value, timedelta):
return handler(_Duration(seconds=value.total_seconds()))

# otherwise, parse it.
try:
data = parse(value)
Expand Down
74 changes: 62 additions & 12 deletions tests/test_pendulum_dt.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from datetime import date, datetime, timedelta
from datetime import timezone as tz

import pendulum
import pytest
from pydantic import BaseModel, ValidationError

from pydantic_extra_types.pendulum_dt import Date, DateTime, Duration

UTC = tz.utc


class DtModel(BaseModel):
dt: DateTime
Expand All @@ -17,32 +22,77 @@ class DurationModel(BaseModel):
delta_t: Duration


def test_pendulum_dt_existing_instance():
@pytest.mark.parametrize(
'instance',
[
pendulum.now(),
datetime.now(),
datetime.now(UTC),
],
)
def test_existing_instance(instance):
"""
Verifies that constructing a model with an existing pendulum dt doesn't throw.
"""
now = pendulum.now()
model = DtModel(dt=now)
assert model.dt == now
model = DtModel(dt=instance)
if isinstance(instance, datetime):
assert model.dt == pendulum.instance(instance)
if instance.tzinfo is None and isinstance(instance, datetime):
instance = model.dt.replace(tzinfo=UTC) # pendulum defaults to UTC
dt = model.dt
else:
assert model.dt == instance
dt = model.dt

assert dt.day == instance.day
assert dt.month == instance.month
assert dt.year == instance.year
assert dt.hour == instance.hour
assert dt.minute == instance.minute
assert dt.second == instance.second
assert dt.microsecond == instance.microsecond
if dt.tzinfo != instance.tzinfo:
assert dt.tzinfo.utcoffset(dt) == instance.tzinfo.utcoffset(instance)


def test_pendulum_date_existing_instance():
@pytest.mark.parametrize(
'instance',
[
pendulum.today(),
date.today(),
],
)
def test_pendulum_date_existing_instance(instance):
"""
Verifies that constructing a model with an existing pendulum date doesn't throw.
"""
today = pendulum.today().date()
model = DateModel(d=today)
assert model.d == today
model = DateModel(d=instance)
if isinstance(instance, datetime):
assert model.d == pendulum.instance(instance).date()
else:
assert model.d == instance
d = model.d
assert d.day == instance.day
assert d.month == instance.month
assert d.year == instance.year


def test_pendulum_duration_existing_instance():
@pytest.mark.parametrize(
'instance',
[
pendulum.duration(days=42, hours=13, minutes=37),
pendulum.duration(days=-42, hours=13, minutes=37),
timedelta(days=42, hours=13, minutes=37),
timedelta(days=-42, hours=13, minutes=37),
],
)
def test_duration_timedelta__existing_instance(instance):
"""
Verifies that constructing a model with an existing pendulum duration doesn't throw.
"""
delta_t = pendulum.duration(days=42, hours=13, minutes=37)
model = DurationModel(delta_t=delta_t)
model = DurationModel(delta_t=instance)

assert model.delta_t.total_seconds() == delta_t.total_seconds()
assert model.delta_t.total_seconds() == instance.total_seconds()


@pytest.mark.parametrize(
Expand Down

0 comments on commit 1da3155

Please sign in to comment.