Skip to content

Commit e807ca0

Browse files
Improve inheritance of pendulum objects
Co-Authored-By: Chase Sterling <chase.sterling@gmail.com>
1 parent 91fa82d commit e807ca0

File tree

3 files changed

+61
-39
lines changed

3 files changed

+61
-39
lines changed

pendulum/__init__.py

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -239,24 +239,10 @@ def instance(
239239
if isinstance(obj, _datetime.date) and not isinstance(obj, _datetime.datetime):
240240
return date(obj.year, obj.month, obj.day)
241241

242-
tz = obj.tzinfo or tz
243-
244-
if tz is not None:
245-
tz = _safe_timezone(tz, dt=obj if isinstance(obj, _datetime.datetime) else None)
246-
247242
if isinstance(obj, _datetime.time):
248-
return Time(obj.hour, obj.minute, obj.second, obj.microsecond, tzinfo=tz)
243+
return Time.instance(obj, tz=tz)
249244

250-
return datetime(
251-
obj.year,
252-
obj.month,
253-
obj.day,
254-
obj.hour,
255-
obj.minute,
256-
obj.second,
257-
obj.microsecond,
258-
tz=cast(Union[str, int, Timezone, FixedTimezone, None], tz),
259-
)
245+
return DateTime.instance(obj, tz=tz)
260246

261247

262248
def now(tz: str | Timezone | None = None) -> DateTime:

pendulum/datetime.py

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,29 @@ def create(
122122
fold=dt.fold,
123123
)
124124

125+
@classmethod
126+
def instance(
127+
cls,
128+
dt: datetime.datetime,
129+
tz: str | Timezone | FixedTimezone | datetime.tzinfo | None = UTC,
130+
) -> Self:
131+
tz = dt.tzinfo or tz
132+
133+
if tz is not None:
134+
tz = pendulum._safe_timezone(tz, dt=dt)
135+
136+
return cls.create(
137+
dt.year,
138+
dt.month,
139+
dt.day,
140+
dt.hour,
141+
dt.minute,
142+
dt.second,
143+
dt.microsecond,
144+
tz=tz,
145+
fold=dt.fold,
146+
)
147+
125148
@overload
126149
@classmethod
127150
def now(cls, tz: datetime.tzinfo | None = None) -> Self:
@@ -172,8 +195,8 @@ def today(cls) -> Self:
172195
return cls.now()
173196

174197
@classmethod
175-
def strptime(cls, time: str, fmt: str) -> DateTime:
176-
return pendulum.instance(datetime.datetime.strptime(time, fmt))
198+
def strptime(cls, time: str, fmt: str) -> Self:
199+
return cls.instance(datetime.datetime.strptime(time, fmt))
177200

178201
# Getters/Setters
179202

@@ -472,19 +495,19 @@ def __repr__(self) -> str:
472495
)
473496

474497
# Comparisons
475-
def closest(self, *dts: datetime.datetime) -> DateTime: # type: ignore[override]
498+
def closest(self, *dts: datetime.datetime) -> Self: # type: ignore[override]
476499
"""
477500
Get the farthest date from the instance.
478501
"""
479-
pdts = [pendulum.instance(x) for x in dts]
502+
pdts = [self.instance(x) for x in dts]
480503

481504
return min((abs(self - dt), dt) for dt in pdts)[1]
482505

483-
def farthest(self, *dts: datetime.datetime) -> DateTime: # type: ignore[override]
506+
def farthest(self, *dts: datetime.datetime) -> Self: # type: ignore[override]
484507
"""
485508
Get the farthest date from the instance.
486509
"""
487-
pdts = [pendulum.instance(x) for x in dts]
510+
pdts = [self.instance(x) for x in dts]
488511

489512
return max((abs(self - dt), dt) for dt in pdts)[1]
490513

@@ -516,7 +539,7 @@ def is_same_day(self, dt: datetime.datetime) -> bool: # type: ignore[override]
516539
Checks if the passed in date is the same day
517540
as the instance current day.
518541
"""
519-
dt = pendulum.instance(dt)
542+
dt = self.instance(dt)
520543

521544
return self.to_date_string() == dt.to_date_string()
522545

@@ -530,7 +553,7 @@ def is_anniversary( # type: ignore[override]
530553
if dt is None:
531554
dt = self.now(self.tz)
532555

533-
instance = pendulum.instance(dt)
556+
instance = self.instance(dt)
534557

535558
return (self.month, self.day) == (instance.month, instance.day)
536559

@@ -1192,7 +1215,7 @@ def __sub__(self, other: datetime.datetime | datetime.timedelta) -> Self | Inter
11921215
other.microsecond,
11931216
)
11941217
else:
1195-
other = pendulum.instance(other)
1218+
other = self.instance(other)
11961219

11971220
return other.diff(self, False)
11981221

@@ -1212,7 +1235,7 @@ def __rsub__(self, other: datetime.datetime) -> Interval:
12121235
other.microsecond,
12131236
)
12141237
else:
1215-
other = pendulum.instance(other)
1238+
other = self.instance(other)
12161239

12171240
return self.diff(other, False)
12181241

@@ -1236,29 +1259,27 @@ def __radd__(self, other: datetime.timedelta) -> Self:
12361259
# Native methods override
12371260

12381261
@classmethod
1239-
def fromtimestamp(cls, t: float, tz: datetime.tzinfo | None = None) -> DateTime:
1262+
def fromtimestamp(cls, t: float, tz: datetime.tzinfo | None = None) -> Self:
12401263
tzinfo = pendulum._safe_timezone(tz)
12411264

1242-
return pendulum.instance(
1243-
datetime.datetime.fromtimestamp(t, tz=tzinfo), tz=tzinfo
1244-
)
1265+
return cls.instance(datetime.datetime.fromtimestamp(t, tz=tzinfo), tz=tzinfo)
12451266

12461267
@classmethod
1247-
def utcfromtimestamp(cls, t: float) -> DateTime:
1248-
return pendulum.instance(datetime.datetime.utcfromtimestamp(t), tz=None)
1268+
def utcfromtimestamp(cls, t: float) -> Self:
1269+
return cls.instance(datetime.datetime.utcfromtimestamp(t), tz=None)
12491270

12501271
@classmethod
1251-
def fromordinal(cls, n: int) -> DateTime:
1252-
return pendulum.instance(datetime.datetime.fromordinal(n), tz=None)
1272+
def fromordinal(cls, n: int) -> Self:
1273+
return cls.instance(datetime.datetime.fromordinal(n), tz=None)
12531274

12541275
@classmethod
12551276
def combine(
12561277
cls,
12571278
date: datetime.date,
12581279
time: datetime.time,
12591280
tzinfo: datetime.tzinfo | None = None,
1260-
) -> DateTime:
1261-
return pendulum.instance(datetime.datetime.combine(date, time), tz=tzinfo)
1281+
) -> Self:
1282+
return cls.instance(datetime.datetime.combine(date, time), tz=tzinfo)
12621283

12631284
def astimezone(self, tz: datetime.tzinfo | None = None) -> Self:
12641285
dt = super().astimezone(tz)
@@ -1321,7 +1342,7 @@ def replace(
13211342
fold=fold,
13221343
)
13231344

1324-
def __getnewargs__(self) -> tuple[DateTime]:
1345+
def __getnewargs__(self) -> tuple[Self]:
13251346
return (self,)
13261347

13271348
def _getstate(
@@ -1341,14 +1362,14 @@ def _getstate(
13411362
def __reduce__(
13421363
self,
13431364
) -> tuple[
1344-
type[DateTime], tuple[int, int, int, int, int, int, int, datetime.tzinfo | None]
1365+
type[Self], tuple[int, int, int, int, int, int, int, datetime.tzinfo | None]
13451366
]:
13461367
return self.__reduce_ex__(2)
13471368

13481369
def __reduce_ex__(
13491370
self, protocol: SupportsIndex
13501371
) -> tuple[
1351-
type[DateTime], tuple[int, int, int, int, int, int, int, datetime.tzinfo | None]
1372+
type[Self], tuple[int, int, int, int, int, int, int, datetime.tzinfo | None]
13521373
]:
13531374
return self.__class__, self._getstate(protocol)
13541375

pendulum/time.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,34 @@
1717
from pendulum.duration import AbsoluteDuration
1818
from pendulum.duration import Duration
1919
from pendulum.mixins.default import FormattableMixin
20+
from pendulum.tz.timezone import UTC
2021

2122

2223
if TYPE_CHECKING:
2324
from typing_extensions import Literal
2425
from typing_extensions import Self
2526
from typing_extensions import SupportsIndex
2627

28+
from pendulum.tz.timezone import FixedTimezone
29+
from pendulum.tz.timezone import Timezone
30+
2731

2832
class Time(FormattableMixin, time):
2933
"""
3034
Represents a time instance as hour, minute, second, microsecond.
3135
"""
3236

37+
@classmethod
38+
def instance(
39+
cls, t: time, tz: str | Timezone | FixedTimezone | datetime.tzinfo | None = UTC
40+
) -> Self:
41+
tz = t.tzinfo or tz
42+
43+
if tz is not None:
44+
tz = pendulum._safe_timezone(tz)
45+
46+
return cls(t.hour, t.minute, t.second, t.microsecond, tzinfo=tz, fold=t.fold)
47+
3348
# String formatting
3449
def __repr__(self) -> str:
3550
us = ""

0 commit comments

Comments
 (0)