Skip to content

Commit b19a378

Browse files
committed
Makes the constructor behave like the standard one.
1 parent cf38100 commit b19a378

File tree

9 files changed

+82
-97
lines changed

9 files changed

+82
-97
lines changed

docs/index.rst

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ Pendulum is a Python package to ease datetimes manipulation.
2525
It is heavily inspired by `Carbon <http://carbon.nesbot.com>`_ for PHP.
2626

2727
The ``Pendulum`` class is a drop-in replacement for the native ``datetime``
28-
class (it is inherited from it) with the exception that its mutable.
29-
30-
Unlike the native class, most of the methods modify the current instance
31-
of ``Pendulum`` in place. If you want to modify a copy just use the ``copy()`` method.
28+
class (it is inherited from it).
3229

3330
Special care has been taken to ensure timezones are handled correctly,
3431
and where appropriate are based on the underlying ``tzinfo`` implementation.
@@ -39,9 +36,10 @@ For example all comparisons are done in UTC or in the timezone of the datetime b
3936
dt_toronto = Pendulum.create_from_date(2012, 1, 1, 'America/Toronto')
4037
dt_vancouver = Pendulum.create_from_date(2012, 1, 1, 'America/Vancouver')
4138
42-
print(dt_vancouver.diff_in_hours(dt_toronto)) # 3
39+
print(dt_vancouver.diff_in_hours(dt_toronto))
40+
3
4341
44-
The default timezone, except when using the ``now()`` method will always be ``UTC``.
42+
The default timezone, except when using the ``now()``, method will always be ``UTC``.
4543

4644
.. note::
4745

@@ -79,20 +77,16 @@ Instantiation
7977
=============
8078

8179
There are several different methods available to create a new instance of Pendulum.
82-
First there is a constructor. It overrides the parent constructor to be more flexible.
83-
Basically, unlike ``datetime`` you can omit parameters and any omitted parameter will
84-
default to its ``now()`` value. However, if you provide the ``year``, ``month``, ``day``
85-
it will emulate the default ``datetime`` behavior.
80+
First there is a constructor. It accepts the same parameters as the standard class.
8681

8782
.. code-block:: python
8883
8984
from pendulum import Pendulum
9085
91-
dt = Pendulum() # equivalent to Pendulum.utcnow()
86+
dt = Pendulum(2015, 2, 5, tzinfo='America/Vancouver')
9287
isinstance(dt, datetime)
9388
True
9489
95-
dt = Pendulum(2015, 2, 5, tzinfo='America/Vancouver')
9690
dt = Pendulum.now(-5)
9791
9892
You'll notice above that the timezone (2nd) parameter was passed as a string and an integer
@@ -103,18 +97,20 @@ This is again shown in the next example which also introduces the ``now()`` func
10397

10498
.. code-block:: python
10599
106-
now = Pendulum.now()
100+
import pendulum
107101
108-
now_in_london_tz = Pendulum.now(pytz.timezone('Europe/London'))
102+
now = pendulum.now()
103+
104+
now_in_london_tz = pendulum.now(pytz.timezone('Europe/London'))
109105
110106
# or just pass the timezone as a string
111-
now_in_london_tz = Pendulum.now('Europe/London')
107+
now_in_london_tz = pendulum.now('Europe/London')
112108
print(now_in_london_tz.timezone_name)
113109
'Europe/London'
114110
115111
# or to create a date with a timezone of +1 to GMT
116112
# during DST then just pass an integer
117-
print(Pendulum.now(1).timezone_name))
113+
print(pendulum.now(1).timezone_name))
118114
None
119115
120116
.. note::
@@ -128,19 +124,19 @@ besides behaving as expected, all accept a timezone parameter and each has their
128124

129125
.. code-block:: python
130126
131-
now = Pendulum.now()
127+
now = pendulum.now()
132128
print(now)
133129
'2016-06-28T16:51:45.978473-05:00'
134130
135-
today = Pendulum.today()
131+
today = pendulum.today()
136132
print(today)
137133
'2016-06-28T00:00:00-05:00'
138134
139-
tomorrow = Pendulum.tomorrow('Europe/London')
135+
tomorrow = pendulum.tomorrow('Europe/London')
140136
print(tomorrow)
141137
'2016-06-29T00:00:00+01:00'
142138
143-
yesterday = Pendulum.yesterday()
139+
yesterday = pendulum.yesterday()
144140
print(yesterday)
145141
'2016-06-27T00:00:00-05:00'
146142
@@ -151,9 +147,9 @@ Generally default values are the current date, time or timezone.
151147

152148
.. code-block:: python
153149
154-
Pendulum.create_from_date(year, month, day, tz)
155-
Pendulum.create_from_time(hour, minute, second, microsecond, tz)
156-
Pendulum.create(year, month, day, hour, minute, second, microsecond, tz)
150+
pendulum.from_date(year, month, day, tz)
151+
pendulum.from_time(hour, minute, second, microsecond, tz)
152+
pendulum.create(year, month, day, hour, minute, second, microsecond, tz)
157153
158154
``create_from_date()`` will default the time to now. ``create_from_time()`` will default the date to today.
159155
``create()`` will default any null parameter to the current respective value.
@@ -163,58 +159,62 @@ is specified but no minutes or seconds, they will get defaulted to ``0``.
163159

164160
.. code-block:: python
165161
166-
xmas_this_year = Pendulum.create_from_date(None, 12, 25) # Year defaults to current year
167-
y2k = Pendulum.create(2000, 1, 1, 0, 0, 0)
168-
noon_london_tz = Pendulum.create_from_time(12, 0, 0, tz='Europe/London')
162+
xmas_this_year = pendulum._from_date(None, 12, 25) # Year defaults to current year
163+
y2k = pendulum.create(2000, 1, 1, 0, 0, 0)
164+
noon_london_tz = pendulum.from_time(12, 0, 0, tz='Europe/London')
169165
170166
.. code-block:: python
171167
172-
Pendulum.create_from_format(time, format, tz)
168+
pendulum.from_format(time, format, tz)
173169
174170
``create_from_format()`` is mostly a wrapper for the base Python function ``datetime.strptime()``.
175171
The difference being the addition the ``tz`` argument that can be a ``tzinfo`` instance or a string timezone value
176172
(defaults to ``UTC``).
177173

178174
.. code-block:: python
179175
180-
Pendulum.create_from_format('1975-05-21 22', '%Y-%m-%d %H').to_datetime_string()
176+
pendulum.from_format('1975-05-21 22', '%Y-%m-%d %H').to_datetime_string()
181177
'1975-05-21 22:00:00'
182-
Pendulum.create_from_format('1975-05-21 22', '%Y-%m-%d %H', 'Europe/London').isoformat()
178+
pendulum.from_format('1975-05-21 22', '%Y-%m-%d %H', 'Europe/London').isoformat()
183179
'1975-05-21T22:00:00+01:00'
184180
185181
# Using strptime is also possible (the timezone will be UTC)
186-
Pendulum.strptime('1975-05-21 22', '%Y-%m-%d %H').isoformat()
182+
pendulum.strptime('1975-05-21 22', '%Y-%m-%d %H').isoformat()
187183
188184
The final ``create`` function is for working with unix timestamps.
189185
``create_from_timestamp()`` will create a Pendulum instance equal to the given timestamp
190186
and will set the timezone as well or default it to ``UTC``.
191187

192188
.. code-block:: python
193189
194-
Pendulum.create_from_timestamp(-1).to_datetime_string()
190+
pendulum.from_timestamp(-1).to_datetime_string()
195191
'1969-12-31 23:59:59'
196192
197-
Pendulum.create_from_timestamp(-1, 'Europe/London').to_datetime_string()
193+
pendulum.from_timestamp(-1, 'Europe/London').to_datetime_string()
198194
'1970-01-01 00:59:59'
199195
196+
# Using the standard fromtimestamp is also possible
197+
pendulum.fromtimestamp(-1).to_datetime_string()
198+
'1969-12-31 23:59:59'
199+
200200
You can also create a ``copy()`` of an existing Pendulum instance.
201201
As expected the date, time and timezone values are all copied to the new instance.
202202

203203
.. code-block:: python
204204
205-
dt = Pendulum.now()
206-
print(dt.diff_in_years(dt.copy().add_year()))
205+
dt = pendulum.now()
206+
print(dt.diff(dt.copy().add_year()).in_years())
207207
1
208208
209-
# dt was unchanged and still holds the value of Pendulum.now()
209+
# dt was unchanged and still holds the value of pendulum.now()
210210
211211
Finally, if you find yourself inheriting a ``datetime`` instance,
212-
you can create a Pendulum instance via the ``instance()`` function.
212+
you can create a ``Pendulum`` instance via the ``instance()`` function.
213213

214214
.. code-block:: python
215215
216216
dt = datetime(2008, 1, 1)
217-
p = Pendulum.instance(dt)
217+
p = pendulum.instance(dt)
218218
print(p.to_datetime_string())
219219
'2008-01-01 00:00:00'
220220

pendulum/pendulum.py

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ def _local_timezone(cls):
136136

137137
return tzlocal.get_localzone()
138138

139-
def __new__(cls, year=1970, month=1, day=1,
140-
hour=0, minute=0, second=0, microsecond=0,
141-
tzinfo=None):
139+
def __new__(cls, year, month, day,
140+
hour=0, minute=0, second=0, microsecond=0,
141+
tzinfo=None):
142142
"""
143143
Constructor.
144144
@@ -151,34 +151,11 @@ def __new__(cls, year=1970, month=1, day=1,
151151

152152
return obj
153153

154-
def __init__(self, year=None, month=None, day=None,
155-
hour=None, minute=None, second=None, microsecond=None,
154+
def __init__(self, year, month, day,
155+
hour=0, minute=0, second=0, microsecond=0,
156156
tzinfo=pytz.UTC):
157-
# If the class has a test now set and we are trying to create a now()
158-
# instance then override as required
159-
if (self.has_test_now()
160-
and all([year is None, month is None, day is None, hour is None,
161-
minute is None, second is None, microsecond is None])):
162-
test_instance = self._test_now
163-
164-
if tzinfo is not None and tzinfo != self._test_now.timezone:
165-
test_instance = test_instance.in_timezone(tzinfo)
166-
else:
167-
tzinfo = test_instance.timezone
168-
169-
year, month, day = test_instance.year, test_instance.month, test_instance.day
170-
hour, minute, second = test_instance.hour, test_instance.minute, test_instance.second
171-
microsecond = test_instance.microsecond
172-
173157
self._tz = self._safe_create_datetime_zone(tzinfo)
174158

175-
# Default datetime behavior
176-
if year is not None and month is not None and day is not None:
177-
hour = 0 if hour is None else hour
178-
minute = 0 if minute is None else minute
179-
second = 0 if second is None else second
180-
microsecond = 0 if microsecond is None else microsecond
181-
182159
self._datetime = self._create_datetime(
183160
self._tz, year, month, day,
184161
hour, minute, second, microsecond
@@ -240,7 +217,17 @@ def now(cls, tz=None):
240217
241218
:rtype: Pendulum
242219
"""
243-
return cls(tzinfo=tz)
220+
# If the class has a test now set and we are trying to create a now()
221+
# instance then override as required
222+
if (cls.has_test_now()):
223+
test_instance = cls._test_now
224+
225+
if tz is not None and tz != cls._test_now.timezone:
226+
test_instance = test_instance.in_timezone(tz)
227+
228+
return test_instance.copy()
229+
230+
return cls.create(tz=tz)
244231

245232
@classmethod
246233
def utcnow(cls):
@@ -345,14 +332,12 @@ def create(cls, year=None, month=None, day=None,
345332
"""
346333
tz = cls._safe_create_datetime_zone(tz)
347334

348-
self = cls()
349-
self._tz = tz
350-
self._datetime = cls._create_datetime(
335+
dt = cls._create_datetime(
351336
tz, year, month, day,
352337
hour, minute, second, microsecond
353338
)
354339

355-
return self
340+
return cls.instance(dt)
356341

357342
@classmethod
358343
def create_from_date(cls, year=None, month=None, day=None, tz=pytz.UTC):

tests/pendulum_tests/test_add.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,28 @@
99
class AddTest(AbstractTestCase):
1010

1111
def test_add_years_positive(self):
12-
self.assertEqual(1976, Pendulum(1975).add_years(1).year)
12+
self.assertEqual(1976, Pendulum.create(1975).add_years(1).year)
1313

1414
def test_add_years_zero(self):
15-
self.assertEqual(1975, Pendulum(1975).add_years(0).year)
15+
self.assertEqual(1975, Pendulum.create(1975).add_years(0).year)
1616

1717
def test_add_years_negative(self):
18-
self.assertEqual(1974, Pendulum(1975).add_years(-1).year)
18+
self.assertEqual(1974, Pendulum.create(1975).add_years(-1).year)
1919

2020
def test_add_year(self):
21-
self.assertEqual(1976, Pendulum(1975).add_year().year)
21+
self.assertEqual(1976, Pendulum.create(1975).add_year().year)
2222

2323
def test_add_months_positive(self):
24-
self.assertEqual(1, Pendulum(1975, 12).add_months(1).month)
24+
self.assertEqual(1, Pendulum.create(1975, 12).add_months(1).month)
2525

2626
def test_add_months_zero(self):
27-
self.assertEqual(12, Pendulum(1975, 12).add_months(0).month)
27+
self.assertEqual(12, Pendulum.create(1975, 12).add_months(0).month)
2828

2929
def test_add_months_negative(self):
30-
self.assertEqual(11, Pendulum(1975, 12).add_months(-1).month)
30+
self.assertEqual(11, Pendulum.create(1975, 12).add_months(-1).month)
3131

3232
def test_add_month(self):
33-
self.assertEqual(1, Pendulum(1975, 12).add_month().month)
33+
self.assertEqual(1, Pendulum.create(1975, 12).add_month().month)
3434

3535
def test_add_month_with_overflow(self):
3636
self.assertEqual(2, Pendulum(2012, 1, 31).add_month().month)

tests/pendulum_tests/test_construct.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ def tearDown(self):
1616
del os.environ['TZ']
1717

1818
def test_creates_an_instance_default_to_utcnow(self):
19-
p = Pendulum()
2019
now = Pendulum.utcnow()
20+
p = Pendulum(now.year, now.month, now.day, now.hour, now.minute, now.second)
2121
self.assertIsInstanceOfPendulum(p)
2222
self.assertEqual(p.timezone_name, now.timezone_name)
2323

@@ -41,7 +41,7 @@ def test_setting_timezone(self):
4141
dt = datetime.utcnow()
4242
offset = dtz.utcoffset(dt).total_seconds() / 3600
4343

44-
p = Pendulum(tzinfo=dtz)
44+
p = Pendulum(dt.year, dt.month, dt.day, tzinfo=dtz)
4545
self.assertEqual(timezone, p.timezone_name)
4646
self.assertEqual(int(offset), p.offset_hours)
4747

@@ -61,7 +61,7 @@ def test_setting_timezone_with_string(self):
6161
dt = datetime.utcnow()
6262
offset = dtz.utcoffset(dt).total_seconds() / 3600
6363

64-
p = Pendulum(tzinfo=timezone)
64+
p = Pendulum(dt.year, dt.month, dt.day, tzinfo=timezone)
6565
self.assertEqual(timezone, p.timezone_name)
6666
self.assertEqual(int(offset), p.offset_hours)
6767

tests/pendulum_tests/test_create_from_date.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class CreateFromDateTest(AbstractTestCase):
99

1010
def test_create_from_date_with_defaults(self):
1111
d = Pendulum.create_from_date()
12-
self.assertEqual(d.timestamp, Pendulum().timestamp)
12+
self.assertEqual(d.timestamp, Pendulum.now().timestamp)
1313

1414
def test_create_from_date(self):
1515
d = Pendulum.create_from_date(1975, 12, 25)

tests/pendulum_tests/test_create_from_time.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class CreateFromTimeTest(AbstractTestCase):
1010

1111
def test_create_from_time_with_defaults(self):
1212
d = Pendulum.create_from_time()
13-
self.assertEqual(d.timestamp, Pendulum().timestamp)
13+
self.assertEqual(d.timestamp, Pendulum.now().timestamp)
1414
self.assertEqual('UTC', d.timezone_name)
1515

1616
def test_create_from_time(self):

tests/pendulum_tests/test_strings.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@
77
class StringsTest(AbstractTestCase):
88

99
def test_to_string(self):
10-
d = Pendulum(microsecond=0)
11-
self.assertEqual(Pendulum(microsecond=0).to_iso8601_string(), str(d))
12-
d = Pendulum(microsecond=123456)
13-
self.assertEqual(Pendulum(microsecond=123456).to_iso8601_string(True), str(d))
10+
d = Pendulum.create(microsecond=0)
11+
self.assertEqual(Pendulum.create(microsecond=0).to_iso8601_string(), str(d))
12+
d = Pendulum.create(microsecond=123456)
13+
self.assertEqual(Pendulum.create(microsecond=123456).to_iso8601_string(True), str(d))
1414

1515
def test_set_to_string_format(self):
1616
Pendulum.set_to_string_format('%a, %d %b %y %H:%M:%S %z')
1717
d = Pendulum(2016, 6, 27, 15, 39, 30)
1818
self.assertEqual('Mon, 27 Jun 16 15:39:30 +0000', str(d))
1919

2020
def test_reset_to_string_format(self):
21-
d = Pendulum(microsecond=0)
21+
d = Pendulum.create(microsecond=0)
2222
Pendulum.set_to_string_format('123')
2323
Pendulum.reset_to_string_format()
2424
self.assertEqual(d.to_iso8601_string(), str(d))

0 commit comments

Comments
 (0)