test_strptime.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. from datetime import (
  2. datetime,
  3. timezone,
  4. )
  5. import numpy as np
  6. import pytest
  7. from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
  8. from pandas._libs.tslibs.strptime import array_strptime
  9. from pandas import (
  10. NaT,
  11. Timestamp,
  12. )
  13. import pandas._testing as tm
  14. creso_infer = NpyDatetimeUnit.NPY_FR_GENERIC.value
  15. class TestArrayStrptimeResolutionInference:
  16. def test_array_strptime_resolution_all_nat(self):
  17. arr = np.array([NaT, np.nan], dtype=object)
  18. fmt = "%Y-%m-%d %H:%M:%S"
  19. res, _ = array_strptime(arr, fmt=fmt, utc=False, creso=creso_infer)
  20. assert res.dtype == "M8[s]"
  21. res, _ = array_strptime(arr, fmt=fmt, utc=True, creso=creso_infer)
  22. assert res.dtype == "M8[s]"
  23. @pytest.mark.parametrize("tz", [None, timezone.utc])
  24. def test_array_strptime_resolution_inference_homogeneous_strings(self, tz):
  25. dt = datetime(2016, 1, 2, 3, 4, 5, 678900, tzinfo=tz)
  26. fmt = "%Y-%m-%d %H:%M:%S"
  27. dtstr = dt.strftime(fmt)
  28. arr = np.array([dtstr] * 3, dtype=object)
  29. expected = np.array([dt.replace(tzinfo=None)] * 3, dtype="M8[s]")
  30. res, _ = array_strptime(arr, fmt=fmt, utc=False, creso=creso_infer)
  31. tm.assert_numpy_array_equal(res, expected)
  32. fmt = "%Y-%m-%d %H:%M:%S.%f"
  33. dtstr = dt.strftime(fmt)
  34. arr = np.array([dtstr] * 3, dtype=object)
  35. expected = np.array([dt.replace(tzinfo=None)] * 3, dtype="M8[us]")
  36. res, _ = array_strptime(arr, fmt=fmt, utc=False, creso=creso_infer)
  37. tm.assert_numpy_array_equal(res, expected)
  38. fmt = "ISO8601"
  39. res, _ = array_strptime(arr, fmt=fmt, utc=False, creso=creso_infer)
  40. tm.assert_numpy_array_equal(res, expected)
  41. @pytest.mark.parametrize("tz", [None, timezone.utc])
  42. def test_array_strptime_resolution_mixed(self, tz):
  43. dt = datetime(2016, 1, 2, 3, 4, 5, 678900, tzinfo=tz)
  44. ts = Timestamp(dt).as_unit("ns")
  45. arr = np.array([dt, ts], dtype=object)
  46. expected = np.array(
  47. [Timestamp(dt).as_unit("ns").asm8, ts.asm8],
  48. dtype="M8[ns]",
  49. )
  50. fmt = "%Y-%m-%d %H:%M:%S"
  51. res, _ = array_strptime(arr, fmt=fmt, utc=False, creso=creso_infer)
  52. tm.assert_numpy_array_equal(res, expected)
  53. fmt = "ISO8601"
  54. res, _ = array_strptime(arr, fmt=fmt, utc=False, creso=creso_infer)
  55. tm.assert_numpy_array_equal(res, expected)
  56. def test_array_strptime_resolution_todaynow(self):
  57. # specifically case where today/now is the *first* item
  58. vals = np.array(["today", np.datetime64("2017-01-01", "us")], dtype=object)
  59. now = Timestamp("now").asm8
  60. res, _ = array_strptime(vals, fmt="%Y-%m-%d", utc=False, creso=creso_infer)
  61. res2, _ = array_strptime(
  62. vals[::-1], fmt="%Y-%m-%d", utc=False, creso=creso_infer
  63. )
  64. # 1s is an arbitrary cutoff for call overhead; in local testing the
  65. # actual difference is about 250us
  66. tolerance = np.timedelta64(1, "s")
  67. assert res.dtype == "M8[us]"
  68. assert abs(res[0] - now) < tolerance
  69. assert res[1] == vals[1]
  70. assert res2.dtype == "M8[us]"
  71. assert abs(res2[1] - now) < tolerance * 2
  72. assert res2[0] == vals[1]
  73. def test_array_strptime_str_outside_nano_range(self):
  74. vals = np.array(["2401-09-15"], dtype=object)
  75. expected = np.array(["2401-09-15"], dtype="M8[s]")
  76. fmt = "ISO8601"
  77. res, _ = array_strptime(vals, fmt=fmt, creso=creso_infer)
  78. tm.assert_numpy_array_equal(res, expected)
  79. # non-iso -> different path
  80. vals2 = np.array(["Sep 15, 2401"], dtype=object)
  81. expected2 = np.array(["2401-09-15"], dtype="M8[s]")
  82. fmt2 = "%b %d, %Y"
  83. res2, _ = array_strptime(vals2, fmt=fmt2, creso=creso_infer)
  84. tm.assert_numpy_array_equal(res2, expected2)