Skip to content

Commit 71fde7e

Browse files
committed
Improves performances
1 parent 201ef16 commit 71fde7e

File tree

3 files changed

+48
-33
lines changed

3 files changed

+48
-33
lines changed

pendulum/pendulum.py

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ def __new__(cls, year, month, day,
164164

165165
def __init__(self, year, month, day,
166166
hour=0, minute=0, second=0, microsecond=0,
167-
tzinfo='UTC'):
167+
tzinfo=UTC):
168+
self.__float_timestamp = None
169+
168170
# If a TimezoneInfo is passed we do not convert:
169171
if isinstance(tzinfo, TimezoneInfo):
170172
self._tz = tzinfo.tz
@@ -183,7 +185,7 @@ def __init__(self, year, month, day,
183185
))
184186

185187
@classmethod
186-
def instance(cls, dt, tz='UTC'):
188+
def instance(cls, dt, tz=UTC):
187189
"""
188190
Create a Carbon instance from a datetime one.
189191
@@ -197,7 +199,6 @@ def instance(cls, dt, tz='UTC'):
197199
"""
198200
tz = dt.tzinfo or tz
199201

200-
# Bypassing default constructor
201202
return cls(
202203
dt.year, dt.month, dt.day,
203204
dt.hour, dt.minute, dt.second, dt.microsecond,
@@ -349,7 +350,7 @@ def _create_datetime(cls, tz, year=None, month=None, day=None,
349350
@classmethod
350351
def create(cls, year=None, month=None, day=None,
351352
hour=None, minute=None, second=None, microsecond=None,
352-
tz='UTC'):
353+
tz=UTC):
353354
"""
354355
Create a new Carbon instance from a specific date and time.
355356
@@ -432,23 +433,23 @@ def create_from_format(cls, time, fmt, tz=UTC):
432433
return cls.instance(dt, tz)
433434

434435
@classmethod
435-
def create_from_timestamp(cls, timestamp, tz='UTC'):
436+
def create_from_timestamp(cls, timestamp, tz=UTC):
436437
"""
437438
Create a Pendulum instance from a timestamp.
438439
439440
:param timestamp: The timestamp
440441
:type timestamp: int or float
441442
442443
:param tz: The timezone
443-
:type tz: tzinfo or str or int or None
444+
:type tz: TimezoneInfo or str or int or None
444445
445446
:rtype: Pendulum
446447
"""
447448
dt = datetime.datetime.utcfromtimestamp(timestamp).replace(tzinfo=UTC)
449+
if tz is not UTC and tz != 'UTC':
450+
tz = cls._safe_create_datetime_zone(tz)
448451

449-
tz = cls._safe_create_datetime_zone(tz)
450-
451-
dt = tz.convert(dt)
452+
dt = tz.convert(dt)
452453

453454
return cls.instance(dt)
454455

@@ -552,18 +553,23 @@ def timestamp(self):
552553

553554
@property
554555
def float_timestamp(self):
556+
if self.__float_timestamp is not None:
557+
return self.__float_timestamp
558+
555559
# If Python > 3.3 we use the native function
556560
# else we emulate it
557561
if PY33:
558-
return self._datetime.timestamp()
559-
560-
if self._datetime.tzinfo is None:
561-
return _time.mktime((self.year, self.month, self.day,
562-
self.hour, self.minute, self.second,
563-
-1, -1, -1)) + self.microsecond / 1e6
562+
self.__float_timestamp = self._datetime.timestamp()
563+
elif self._datetime.tzinfo is None:
564+
self.__float_timestamp = _time.mktime(
565+
(self.year, self.month, self.day,
566+
self.hour, self.minute, self.second,
567+
-1, -1, -1)) + self.microsecond / 1e6
564568

565569
else:
566-
return (self._datetime - self._EPOCH).total_seconds()
570+
self.__float_timestamp = (self._datetime - self._EPOCH).total_seconds()
571+
572+
return self.__float_timestamp
567573

568574
@property
569575
def week_of_month(self):
@@ -712,7 +718,7 @@ def in_timezone(self, tz):
712718
"""
713719
tz = self._safe_create_datetime_zone(tz)
714720

715-
return self.instance(tz.convert(self._datetime))
721+
return tz.convert(self)
716722

717723
def in_tz(self, tz):
718724
"""

pendulum/tz/timezone.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,7 @@ def _normalize(self, dt):
110110
elif not dt < end.time:
111111
tr = end
112112
else:
113-
# For some reason, Python 2.7 does not use
114-
# the Transition comparison methods.
115-
if PY2:
116-
transitions = map(lambda t: t.time, self._transitions)
117-
else:
118-
transitions = self._transitions
119-
120-
idx = max(0, bisect_right(transitions, dt))
113+
idx = self._find_transition_index(dt)
121114
tr = self._transitions[idx]
122115

123116
if idx > 0:
@@ -188,7 +181,7 @@ def _convert(self, dt):
188181
if not self._transitions:
189182
transition_type = self._default_transition_type
190183
else:
191-
idx = max(0, bisect_right(self._transitions, unix_time) - 1)
184+
idx = max(0, self._find_transition_index(unix_time) - 1)
192185
tr = self._transitions[idx]
193186
transition_type = tr.transition_type
194187

@@ -235,6 +228,22 @@ def _get_timestamp(self, dt):
235228

236229
return t
237230

231+
def _find_transition_index(self, dt):
232+
lo, hi = 0, len(self._transitions)
233+
234+
prop = '_time'
235+
if isinstance(dt, (int, float)):
236+
prop = '_unix_time'
237+
238+
while lo < hi:
239+
mid = (lo + hi) // 2
240+
if dt < getattr(self._transitions[mid], prop):
241+
hi = mid
242+
else:
243+
lo = mid + 1
244+
245+
return lo
246+
238247
def __repr__(self):
239248
return '<Timezone [{}]>'.format(self._name)
240249

pendulum/tz/transition.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -93,18 +93,18 @@ def __ge__(self, other):
9393

9494
def _get_comparables(self, other):
9595
if isinstance(other, Transition):
96-
own = self.unix_time
97-
other = other.unix_time
96+
own = self._unix_time
97+
other = other._unix_time
9898
elif isinstance(other, datetime):
99-
own = self.time
99+
own = self._time
100100
else:
101-
own = self.unix_time
101+
own = self._unix_time
102102

103103
return own, other
104104

105105
def __repr__(self):
106106
return '<Transition [{}, {} -> {}]>'.format(
107-
self.unix_time,
108-
self.pre_time,
109-
self.time
107+
self._unix_time,
108+
self._pre_time,
109+
self._time
110110
)

0 commit comments

Comments
 (0)