-
-
Notifications
You must be signed in to change notification settings - Fork 18.7k
API/COMPAT: add pydatetime-style positional args to Timestamp constructor #12482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
0d6884b
5c34c04
6fad30b
9c1e2dc
a334eab
0ac786f
79d63d4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…ctor
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -180,6 +180,36 @@ def test_constructor_invalid(self): | |
with tm.assertRaisesRegexp(ValueError, 'Cannot convert Period'): | ||
Timestamp(Period('1000-01-01')) | ||
|
||
def test_constructor_positional(self): | ||
# GH 10758 | ||
with tm.assertRaises(TypeError): | ||
Timestamp(2000, 1) | ||
with tm.assertRaises(ValueError): | ||
Timestamp(2000, 0, 1) | ||
with tm.assertRaises(ValueError): | ||
Timestamp(2000, 13, 1) | ||
with tm.assertRaises(ValueError): | ||
Timestamp(2000, 1, 0) | ||
with tm.assertRaises(ValueError): | ||
Timestamp(2000, 1, 32) | ||
with tm.assertRaises(TypeError): | ||
Timestamp(2000, 1, 1, None) | ||
with tm.assertRaises(TypeError): | ||
Timestamp(2000, 1, 1, None, None) | ||
with tm.assertRaises(TypeError): | ||
Timestamp(2000, 1, 1, None, None, None) | ||
|
||
ts = Timestamp(2000, 1, 2) | ||
|
||
actual = ts.to_pydatetime() | ||
expected = datetime.datetime(2000, 1, 2) | ||
self.assertEqual(actual, expected) | ||
self.assertEqual(type(actual), type(expected)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the purpose of this test here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To test for equivalence. Let me know if I should use a different pattern. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand but that's not part of this PR (and its already tested), so not necessary. |
||
|
||
pos_args = [2000, 1, 2, 3, 4, 5, 999999] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can u also add another with and another with kwargs as well. |
||
self.assertEqual(Timestamp(*pos_args).to_pydatetime(), | ||
datetime.datetime(*pos_args)) | ||
|
||
def test_conversion(self): | ||
# GH 9255 | ||
ts = Timestamp('2000-01-01') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -216,6 +216,7 @@ cdef inline bint _is_fixed_offset(object tz): | |
|
||
|
||
_zero_time = datetime_time(0, 0) | ||
_no_unit = object() | ||
|
||
# Python front end to C extension type _Timestamp | ||
# This serves as the box for datetime64 | ||
|
@@ -288,10 +289,36 @@ class Timestamp(_Timestamp): | |
def combine(cls, date, time): | ||
return cls(datetime.combine(date, time)) | ||
|
||
def __new__(cls, object ts_input, object offset=None, tz=None, unit=None): | ||
def __new__(cls, | ||
object ts_input, object offset=None, tz=None, unit=_no_unit, | ||
minute=0, second=0, microsecond=0, tzinfo=None): | ||
# The parameter list folds together legacy parameter names (the first | ||
# four) and positional parameter names from pydatetime (starting with | ||
# `minute`). | ||
# | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good, this is a nice way to do this. |
||
# When using the pydatetime form, the first three parameters are | ||
# required, but the fourth (called `unit` but standing in for `hour`) | ||
# is optional. However, when using the legacy form, only the first | ||
# parameter is required and the fourth parameter defaults to `None`. | ||
# We use a special non-`None` constant to distinguish when callers | ||
# pass `None` as the fourth pydatetime parameter. | ||
|
||
cdef _TSObject ts | ||
cdef _Timestamp ts_base | ||
|
||
if offset is not None and is_integer_object(offset): | ||
# User passed positional arguments: | ||
# Timestamp(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]) | ||
# When using the positional form, the first three parameters are | ||
# required. Assign defaults to the rest. | ||
if unit is _no_unit: | ||
unit = 0 | ||
# Forward positional arguments to datetime constructor. | ||
return Timestamp(datetime(ts_input, offset, tz, unit, minute, second, microsecond, tzinfo), | ||
tz=tzinfo) | ||
elif unit is _no_unit: | ||
unit = None | ||
|
||
ts = convert_to_tsobject(ts_input, tz, unit, 0, 0) | ||
|
||
if ts.value == NPY_NAT: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you use
assertRaisesRegexp
here to check for thingsdoesn't have to be an exact checking, but need to make sure that it is raising the
datetime.datetime
constructor error message and not something else.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the cases where not enough parameters are passed to
Timestamp
, the error will bean integer is required (got NoneType)
instead ofRequired argument not found
. Matching thedatetime
exception exactly requires 3 additional checks and calls:which seems ugly. Do we really want that?