Skip to content

Commit fd6c6df

Browse files
fix timestamp replace
1 parent d4a5536 commit fd6c6df

File tree

6 files changed

+58
-30
lines changed

6 files changed

+58
-30
lines changed

pandas/_libs/tslibs/conversion.pxd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit,
3535

3636
cdef _TSObject convert_datetime_to_tsobject(datetime ts, tzinfo tz,
3737
int32_t nanos=*,
38-
NPY_DATETIMEUNIT reso=*)
38+
NPY_DATETIMEUNIT reso=*,
39+
NPY_DATETIMEUNIT best_reso=*)
3940

4041
cdef _TSObject convert_str_to_tsobject(str ts, tzinfo tz,
4142
bint dayfirst=*,

pandas/_libs/tslibs/conversion.pyx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -423,10 +423,9 @@ cdef _TSObject convert_to_tsobject(object ts, tzinfo tz, str unit,
423423
return convert_datetime_to_tsobject(ts, tz, nanos, reso=reso)
424424
elif PyDate_Check(ts):
425425
# Keep the converter same as PyDateTime's
426-
# For date object we give the lowest supported resolution, i.e. "s"
427426
ts = datetime.combine(ts, time())
428427
return convert_datetime_to_tsobject(
429-
ts, tz, nanos=0, reso=NPY_DATETIMEUNIT.NPY_FR_s
428+
ts, tz, nanos=0, reso=NPY_DATETIMEUNIT.NPY_FR_us
430429
)
431430
else:
432431
from .period import Period
@@ -454,7 +453,8 @@ cdef _TSObject convert_datetime_to_tsobject(
454453
datetime ts,
455454
tzinfo tz,
456455
int32_t nanos=0,
457-
NPY_DATETIMEUNIT reso=NPY_FR_ns,
456+
NPY_DATETIMEUNIT reso=NPY_DATETIMEUNIT.NPY_FR_GENERIC,
457+
NPY_DATETIMEUNIT best_reso=NPY_DATETIMEUNIT.NPY_FR_GENERIC,
458458
):
459459
"""
460460
Convert a datetime (or Timestamp) input `ts`, along with optional timezone
@@ -481,7 +481,6 @@ cdef _TSObject convert_datetime_to_tsobject(
481481
_TSObject obj = _TSObject()
482482
int64_t pps
483483

484-
obj.creso = reso
485484
obj.fold = ts.fold
486485
if tz is not None:
487486

@@ -508,7 +507,8 @@ cdef _TSObject convert_datetime_to_tsobject(
508507
if nanos:
509508
obj.dts.ps = nanos * 1000
510509

511-
reso = get_supported_reso_for_dts(reso, &obj.dts)
510+
if reso == NPY_DATETIMEUNIT.NPY_FR_GENERIC:
511+
reso = get_supported_reso_for_dts(best_reso, &obj.dts)
512512
obj.creso = reso
513513

514514
try:
@@ -664,8 +664,13 @@ cdef _TSObject convert_str_to_tsobject(str ts, tzinfo tz,
664664
out_bestunit=&out_bestunit,
665665
nanos=&nanos,
666666
)
667-
reso = get_supported_reso(out_bestunit)
668-
return convert_datetime_to_tsobject(dt, tz, nanos=nanos, reso=reso)
667+
return convert_datetime_to_tsobject(
668+
dt,
669+
tz,
670+
nanos=nanos,
671+
reso=NPY_DATETIMEUNIT.NPY_FR_GENERIC,
672+
best_reso=out_bestunit
673+
)
669674

670675

671676
cdef check_overflows(_TSObject obj, NPY_DATETIMEUNIT reso=NPY_FR_ns):

pandas/_libs/tslibs/dtypes.pyx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,15 @@ cdef NPY_DATETIMEUNIT get_supported_reso_for_dts(
530530
# defaulting to 'us' if possible.
531531
if reso == NPY_DATETIMEUNIT.NPY_FR_GENERIC:
532532
return NPY_DATETIMEUNIT.NPY_FR_ns
533+
# if dts.ps != 0:
534+
# return NPY_DATETIMEUNIT.NPY_FR_ns
535+
# elif (
536+
# cmp_dtstructs(dts, &dts_us_min, Py_GE)
537+
# and cmp_dtstructs(dts, &dts_us_max, Py_LE)
538+
# ):
539+
# return NPY_DATETIMEUNIT.NPY_FR_us
540+
# else:
541+
# return NPY_DATETIMEUNIT.NPY_FR_s
533542
if reso < NPY_DATETIMEUNIT.NPY_FR_us:
534543
if (
535544
cmp_dtstructs(dts, &dts_us_min, Py_GE)

pandas/tests/indexes/datetimes/test_constructors.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,19 @@ def test_dti_constructor_with_dtype_object_int_matches_int_dtype(self, dtype):
10931093
tm.assert_index_equal(res3, expected)
10941094
tm.assert_index_equal(res4, expected)
10951095

1096+
@pytest.mark.parametrize("tz", [None, "US/Eastern"])
1097+
def test_constructor_from_timestamp_objects(self, unit, tz):
1098+
result = DatetimeIndex(
1099+
[
1100+
Timestamp("2012-01-01 00:00:00", tz=tz).as_unit(unit),
1101+
Timestamp("2012-01-02 00:00:00", tz=tz).as_unit(unit),
1102+
],
1103+
)
1104+
expected = (
1105+
DatetimeIndex(["2012-01-01", "2012-01-02"]).as_unit(unit).tz_localize(tz)
1106+
)
1107+
tm.assert_index_equal(result, expected)
1108+
10961109

10971110
class TestTimeSeries:
10981111
def test_dti_constructor_preserve_dti_freq(self):

pandas/tests/scalar/timestamp/methods/test_tz_localize.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def test_tz_localize_ambiguous(self):
7272
ts_dst = ts.tz_localize("US/Eastern", ambiguous=True)
7373
ts_no_dst = ts.tz_localize("US/Eastern", ambiguous=False)
7474

75-
assert ts_no_dst._value - ts_dst._value == 3600
75+
assert ts_no_dst._value - ts_dst._value == 3600_000_000
7676
msg = re.escape(
7777
"'ambiguous' parameter must be one of: "
7878
"True, False, 'NaT', 'raise' (default)"
@@ -140,7 +140,7 @@ def test_tz_localize_nonexistent(self, stamp, tz):
140140
def test_tz_localize_nonexistent_shift(
141141
self, stamp, tz, forward_expected, backward_expected
142142
):
143-
ts = Timestamp(stamp)
143+
ts = Timestamp(stamp).as_unit("s")
144144
forward_ts = ts.tz_localize(tz, nonexistent="shift_forward")
145145
assert forward_ts == Timestamp(forward_expected, tz=tz)
146146
backward_ts = ts.tz_localize(tz, nonexistent="shift_backward")
@@ -198,7 +198,7 @@ def test_tz_localize_ambiguous_compat(self):
198198
result_pytz = naive.tz_localize(pytz_zone, ambiguous=False)
199199
result_dateutil = naive.tz_localize(dateutil_zone, ambiguous=False)
200200
assert result_pytz._value == result_dateutil._value
201-
assert result_pytz._value == 1382835600
201+
assert result_pytz._value == 1382835600000000
202202

203203
# fixed ambiguous behavior
204204
# see gh-14621, GH#45087
@@ -210,7 +210,7 @@ def test_tz_localize_ambiguous_compat(self):
210210
result_pytz = naive.tz_localize(pytz_zone, ambiguous=True)
211211
result_dateutil = naive.tz_localize(dateutil_zone, ambiguous=True)
212212
assert result_pytz._value == result_dateutil._value
213-
assert result_pytz._value == 1382832000
213+
assert result_pytz._value == 1382832000000000
214214

215215
# see gh-14621
216216
assert str(result_pytz) == str(result_dateutil)

pandas/tests/scalar/timestamp/test_constructors.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -424,31 +424,31 @@ class TestTimestampResolutionInference:
424424
def test_construct_from_time_unit(self):
425425
# GH#54097 only passing a time component, no date
426426
ts = Timestamp("01:01:01.111")
427-
assert ts.unit == "ms"
427+
assert ts.unit == "us"
428428

429429
def test_constructor_str_infer_reso(self):
430430
# non-iso8601 path
431431

432432
# _parse_delimited_date path
433433
ts = Timestamp("01/30/2023")
434-
assert ts.unit == "s"
434+
assert ts.unit == "us"
435435

436436
# _parse_dateabbr_string path
437437
ts = Timestamp("2015Q1")
438-
assert ts.unit == "s"
438+
assert ts.unit == "us"
439439

440440
# dateutil_parse path
441441
ts = Timestamp("2016-01-01 1:30:01 PM")
442-
assert ts.unit == "s"
442+
assert ts.unit == "us"
443443

444444
ts = Timestamp("2016 June 3 15:25:01.345")
445-
assert ts.unit == "ms"
445+
assert ts.unit == "us"
446446

447447
ts = Timestamp("300-01-01")
448-
assert ts.unit == "s"
448+
assert ts.unit == "us"
449449

450450
ts = Timestamp("300 June 1:30:01.300")
451-
assert ts.unit == "ms"
451+
assert ts.unit == "us"
452452

453453
# dateutil path -> don't drop trailing zeros
454454
ts = Timestamp("01-01-2013T00:00:00.000000000+0000")
@@ -464,10 +464,10 @@ def test_constructor_str_infer_reso(self):
464464

465465
# GH#56208 minute reso through the ISO8601 path with tz offset
466466
ts = Timestamp("2020-01-01 00:00+00:00")
467-
assert ts.unit == "s"
467+
assert ts.unit == "us"
468468

469469
ts = Timestamp("2020-01-01 00+00:00")
470-
assert ts.unit == "s"
470+
assert ts.unit == "us"
471471

472472
@pytest.mark.parametrize("method", ["now", "today"])
473473
def test_now_today_unit(self, method):
@@ -504,10 +504,10 @@ def test_construct_from_string_invalid_raises(self):
504504
def test_constructor_from_iso8601_str_with_offset_reso(self):
505505
# GH#49737
506506
ts = Timestamp("2016-01-01 04:05:06-01:00")
507-
assert ts.unit == "s"
507+
assert ts.unit == "us"
508508

509509
ts = Timestamp("2016-01-01 04:05:06.000-01:00")
510-
assert ts.unit == "ms"
510+
assert ts.unit == "us"
511511

512512
ts = Timestamp("2016-01-01 04:05:06.000000-01:00")
513513
assert ts.unit == "us"
@@ -520,7 +520,7 @@ def test_constructor_from_date_second_reso(self):
520520
# reso, i.e. seconds
521521
obj = date(2012, 9, 1)
522522
ts = Timestamp(obj)
523-
assert ts.unit == "s"
523+
assert ts.unit == "us"
524524

525525
def test_constructor_datetime64_with_tz(self):
526526
# GH#42288, GH#24559
@@ -820,10 +820,10 @@ def test_out_of_bounds_string(self):
820820
Timestamp("2263-01-01").as_unit("ns")
821821

822822
ts = Timestamp("2263-01-01")
823-
assert ts.unit == "s"
823+
assert ts.unit == "us"
824824

825825
ts = Timestamp("1676-01-01")
826-
assert ts.unit == "s"
826+
assert ts.unit == "us"
827827

828828
def test_barely_out_of_bounds(self):
829829
# GH#19529
@@ -874,7 +874,7 @@ def test_out_of_bounds_string_consistency(self, arg):
874874
Timestamp(arg).as_unit("ns")
875875

876876
ts = Timestamp(arg)
877-
assert ts.unit == "s"
877+
assert ts.unit == "us"
878878
assert ts.year == ts.month == ts.day == 1
879879

880880
def test_min_valid(self):
@@ -1067,22 +1067,22 @@ def test_timestamp_nano_range(nano):
10671067

10681068
def test_non_nano_value():
10691069
# https://github.com/pandas-dev/pandas/issues/49076
1070-
result = Timestamp("1800-01-01", unit="s").value
1070+
result = Timestamp("1800-01-01").value
10711071
# `.value` shows nanoseconds, even though unit is 's'
10721072
assert result == -5364662400000000000
10731073

10741074
# out-of-nanoseconds-bounds `.value` raises informative message
10751075
msg = (
10761076
r"Cannot convert Timestamp to nanoseconds without overflow. "
10771077
r"Use `.asm8.view\('i8'\)` to cast represent Timestamp in its "
1078-
r"own unit \(here, s\).$"
1078+
r"own unit \(here, us\).$"
10791079
)
10801080
ts = Timestamp("0300-01-01")
10811081
with pytest.raises(OverflowError, match=msg):
10821082
ts.value
10831083
# check that the suggested workaround actually works
10841084
result = ts.asm8.view("i8")
1085-
assert result == -52700112000
1085+
assert result == -52700112000000000
10861086

10871087

10881088
@pytest.mark.parametrize("na_value", [None, np.nan, np.datetime64("NaT"), NaT, NA])

0 commit comments

Comments
 (0)