PageRenderTime 64ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/pandas/tests/indexes/datetimes/test_misc.py

https://github.com/pydata/pandas
Python | 308 lines | 247 code | 41 blank | 20 comment | 19 complexity | 8cf04d6c4dee14f26de60df75a257627 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. import calendar
  2. from datetime import datetime
  3. import locale
  4. import unicodedata
  5. import numpy as np
  6. import pytest
  7. import pandas as pd
  8. from pandas import (
  9. DatetimeIndex,
  10. Index,
  11. Timedelta,
  12. Timestamp,
  13. date_range,
  14. offsets,
  15. )
  16. import pandas._testing as tm
  17. from pandas.core.arrays import DatetimeArray
  18. class TestDatetime64:
  19. def test_no_millisecond_field(self):
  20. msg = "type object 'DatetimeIndex' has no attribute 'millisecond'"
  21. with pytest.raises(AttributeError, match=msg):
  22. DatetimeIndex.millisecond
  23. msg = "'DatetimeIndex' object has no attribute 'millisecond'"
  24. with pytest.raises(AttributeError, match=msg):
  25. DatetimeIndex([]).millisecond
  26. def test_datetimeindex_accessors(self):
  27. dti_naive = date_range(freq="D", start=datetime(1998, 1, 1), periods=365)
  28. # GH#13303
  29. dti_tz = date_range(
  30. freq="D", start=datetime(1998, 1, 1), periods=365, tz="US/Eastern"
  31. )
  32. for dti in [dti_naive, dti_tz]:
  33. assert dti.year[0] == 1998
  34. assert dti.month[0] == 1
  35. assert dti.day[0] == 1
  36. assert dti.hour[0] == 0
  37. assert dti.minute[0] == 0
  38. assert dti.second[0] == 0
  39. assert dti.microsecond[0] == 0
  40. assert dti.dayofweek[0] == 3
  41. assert dti.dayofyear[0] == 1
  42. assert dti.dayofyear[120] == 121
  43. assert dti.isocalendar().week[0] == 1
  44. assert dti.isocalendar().week[120] == 18
  45. assert dti.quarter[0] == 1
  46. assert dti.quarter[120] == 2
  47. assert dti.days_in_month[0] == 31
  48. assert dti.days_in_month[90] == 30
  49. assert dti.is_month_start[0]
  50. assert not dti.is_month_start[1]
  51. assert dti.is_month_start[31]
  52. assert dti.is_quarter_start[0]
  53. assert dti.is_quarter_start[90]
  54. assert dti.is_year_start[0]
  55. assert not dti.is_year_start[364]
  56. assert not dti.is_month_end[0]
  57. assert dti.is_month_end[30]
  58. assert not dti.is_month_end[31]
  59. assert dti.is_month_end[364]
  60. assert not dti.is_quarter_end[0]
  61. assert not dti.is_quarter_end[30]
  62. assert dti.is_quarter_end[89]
  63. assert dti.is_quarter_end[364]
  64. assert not dti.is_year_end[0]
  65. assert dti.is_year_end[364]
  66. assert len(dti.year) == 365
  67. assert len(dti.month) == 365
  68. assert len(dti.day) == 365
  69. assert len(dti.hour) == 365
  70. assert len(dti.minute) == 365
  71. assert len(dti.second) == 365
  72. assert len(dti.microsecond) == 365
  73. assert len(dti.dayofweek) == 365
  74. assert len(dti.dayofyear) == 365
  75. assert len(dti.isocalendar()) == 365
  76. assert len(dti.quarter) == 365
  77. assert len(dti.is_month_start) == 365
  78. assert len(dti.is_month_end) == 365
  79. assert len(dti.is_quarter_start) == 365
  80. assert len(dti.is_quarter_end) == 365
  81. assert len(dti.is_year_start) == 365
  82. assert len(dti.is_year_end) == 365
  83. dti.name = "name"
  84. # non boolean accessors -> return Index
  85. for accessor in DatetimeArray._field_ops:
  86. if accessor in ["week", "weekofyear"]:
  87. # GH#33595 Deprecate week and weekofyear
  88. continue
  89. res = getattr(dti, accessor)
  90. assert len(res) == 365
  91. assert isinstance(res, Index)
  92. assert res.name == "name"
  93. # boolean accessors -> return array
  94. for accessor in DatetimeArray._bool_ops:
  95. res = getattr(dti, accessor)
  96. assert len(res) == 365
  97. assert isinstance(res, np.ndarray)
  98. # test boolean indexing
  99. res = dti[dti.is_quarter_start]
  100. exp = dti[[0, 90, 181, 273]]
  101. tm.assert_index_equal(res, exp)
  102. res = dti[dti.is_leap_year]
  103. exp = DatetimeIndex([], freq="D", tz=dti.tz, name="name")
  104. tm.assert_index_equal(res, exp)
  105. def test_datetimeindex_accessors2(self):
  106. dti = date_range(freq="BQ-FEB", start=datetime(1998, 1, 1), periods=4)
  107. assert sum(dti.is_quarter_start) == 0
  108. assert sum(dti.is_quarter_end) == 4
  109. assert sum(dti.is_year_start) == 0
  110. assert sum(dti.is_year_end) == 1
  111. def test_datetimeindex_accessors3(self):
  112. # Ensure is_start/end accessors throw ValueError for CustomBusinessDay,
  113. bday_egypt = offsets.CustomBusinessDay(weekmask="Sun Mon Tue Wed Thu")
  114. dti = date_range(datetime(2013, 4, 30), periods=5, freq=bday_egypt)
  115. msg = "Custom business days is not supported by is_month_start"
  116. with pytest.raises(ValueError, match=msg):
  117. dti.is_month_start
  118. def test_datetimeindex_accessors4(self):
  119. dti = DatetimeIndex(["2000-01-01", "2000-01-02", "2000-01-03"])
  120. assert dti.is_month_start[0] == 1
  121. def test_datetimeindex_accessors5(self):
  122. with tm.assert_produces_warning(FutureWarning, match="The 'freq' argument"):
  123. tests = [
  124. (Timestamp("2013-06-01", freq="M").is_month_start, 1),
  125. (Timestamp("2013-06-01", freq="BM").is_month_start, 0),
  126. (Timestamp("2013-06-03", freq="M").is_month_start, 0),
  127. (Timestamp("2013-06-03", freq="BM").is_month_start, 1),
  128. (Timestamp("2013-02-28", freq="Q-FEB").is_month_end, 1),
  129. (Timestamp("2013-02-28", freq="Q-FEB").is_quarter_end, 1),
  130. (Timestamp("2013-02-28", freq="Q-FEB").is_year_end, 1),
  131. (Timestamp("2013-03-01", freq="Q-FEB").is_month_start, 1),
  132. (Timestamp("2013-03-01", freq="Q-FEB").is_quarter_start, 1),
  133. (Timestamp("2013-03-01", freq="Q-FEB").is_year_start, 1),
  134. (Timestamp("2013-03-31", freq="QS-FEB").is_month_end, 1),
  135. (Timestamp("2013-03-31", freq="QS-FEB").is_quarter_end, 0),
  136. (Timestamp("2013-03-31", freq="QS-FEB").is_year_end, 0),
  137. (Timestamp("2013-02-01", freq="QS-FEB").is_month_start, 1),
  138. (Timestamp("2013-02-01", freq="QS-FEB").is_quarter_start, 1),
  139. (Timestamp("2013-02-01", freq="QS-FEB").is_year_start, 1),
  140. (Timestamp("2013-06-30", freq="BQ").is_month_end, 0),
  141. (Timestamp("2013-06-30", freq="BQ").is_quarter_end, 0),
  142. (Timestamp("2013-06-30", freq="BQ").is_year_end, 0),
  143. (Timestamp("2013-06-28", freq="BQ").is_month_end, 1),
  144. (Timestamp("2013-06-28", freq="BQ").is_quarter_end, 1),
  145. (Timestamp("2013-06-28", freq="BQ").is_year_end, 0),
  146. (Timestamp("2013-06-30", freq="BQS-APR").is_month_end, 0),
  147. (Timestamp("2013-06-30", freq="BQS-APR").is_quarter_end, 0),
  148. (Timestamp("2013-06-30", freq="BQS-APR").is_year_end, 0),
  149. (Timestamp("2013-06-28", freq="BQS-APR").is_month_end, 1),
  150. (Timestamp("2013-06-28", freq="BQS-APR").is_quarter_end, 1),
  151. (Timestamp("2013-03-29", freq="BQS-APR").is_year_end, 1),
  152. (Timestamp("2013-11-01", freq="AS-NOV").is_year_start, 1),
  153. (Timestamp("2013-10-31", freq="AS-NOV").is_year_end, 1),
  154. (Timestamp("2012-02-01").days_in_month, 29),
  155. (Timestamp("2013-02-01").days_in_month, 28),
  156. ]
  157. for ts, value in tests:
  158. assert ts == value
  159. def test_datetimeindex_accessors6(self):
  160. # GH 6538: Check that DatetimeIndex and its TimeStamp elements
  161. # return the same weekofyear accessor close to new year w/ tz
  162. dates = ["2013/12/29", "2013/12/30", "2013/12/31"]
  163. dates = DatetimeIndex(dates, tz="Europe/Brussels")
  164. expected = [52, 1, 1]
  165. assert dates.isocalendar().week.tolist() == expected
  166. assert [d.weekofyear for d in dates] == expected
  167. # GH 12806
  168. # error: Unsupported operand types for + ("List[None]" and "List[str]")
  169. @pytest.mark.parametrize(
  170. "time_locale", [None] + (tm.get_locales() or []) # type: ignore[operator]
  171. )
  172. def test_datetime_name_accessors(self, time_locale):
  173. # Test Monday -> Sunday and January -> December, in that sequence
  174. if time_locale is None:
  175. # If the time_locale is None, day-name and month_name should
  176. # return the english attributes
  177. expected_days = [
  178. "Monday",
  179. "Tuesday",
  180. "Wednesday",
  181. "Thursday",
  182. "Friday",
  183. "Saturday",
  184. "Sunday",
  185. ]
  186. expected_months = [
  187. "January",
  188. "February",
  189. "March",
  190. "April",
  191. "May",
  192. "June",
  193. "July",
  194. "August",
  195. "September",
  196. "October",
  197. "November",
  198. "December",
  199. ]
  200. else:
  201. with tm.set_locale(time_locale, locale.LC_TIME):
  202. expected_days = calendar.day_name[:]
  203. expected_months = calendar.month_name[1:]
  204. # GH#11128
  205. dti = date_range(freq="D", start=datetime(1998, 1, 1), periods=365)
  206. english_days = [
  207. "Monday",
  208. "Tuesday",
  209. "Wednesday",
  210. "Thursday",
  211. "Friday",
  212. "Saturday",
  213. "Sunday",
  214. ]
  215. for day, name, eng_name in zip(range(4, 11), expected_days, english_days):
  216. name = name.capitalize()
  217. assert dti.day_name(locale=time_locale)[day] == name
  218. assert dti.day_name(locale=None)[day] == eng_name
  219. ts = Timestamp(datetime(2016, 4, day))
  220. assert ts.day_name(locale=time_locale) == name
  221. dti = dti.append(DatetimeIndex([pd.NaT]))
  222. assert np.isnan(dti.day_name(locale=time_locale)[-1])
  223. ts = Timestamp(pd.NaT)
  224. assert np.isnan(ts.day_name(locale=time_locale))
  225. # GH#12805
  226. dti = date_range(freq="M", start="2012", end="2013")
  227. result = dti.month_name(locale=time_locale)
  228. expected = Index([month.capitalize() for month in expected_months])
  229. # work around different normalization schemes
  230. # https://github.com/pandas-dev/pandas/issues/22342
  231. result = result.str.normalize("NFD")
  232. expected = expected.str.normalize("NFD")
  233. tm.assert_index_equal(result, expected)
  234. for date, expected in zip(dti, expected_months):
  235. result = date.month_name(locale=time_locale)
  236. expected = expected.capitalize()
  237. result = unicodedata.normalize("NFD", result)
  238. expected = unicodedata.normalize("NFD", result)
  239. assert result == expected
  240. dti = dti.append(DatetimeIndex([pd.NaT]))
  241. assert np.isnan(dti.month_name(locale=time_locale)[-1])
  242. def test_nanosecond_field(self):
  243. dti = DatetimeIndex(np.arange(10))
  244. tm.assert_index_equal(dti.nanosecond, Index(np.arange(10, dtype=np.int64)))
  245. def test_iter_readonly():
  246. # GH#28055 ints_to_pydatetime with readonly array
  247. arr = np.array([np.datetime64("2012-02-15T12:00:00.000000000")])
  248. arr.setflags(write=False)
  249. dti = pd.to_datetime(arr)
  250. list(dti)
  251. def test_week_and_weekofyear_are_deprecated():
  252. # GH#33595 Deprecate week and weekofyear
  253. idx = date_range(start="2019-12-29", freq="D", periods=4)
  254. with tm.assert_produces_warning(FutureWarning):
  255. idx.week
  256. with tm.assert_produces_warning(FutureWarning):
  257. idx.weekofyear
  258. def test_add_timedelta_preserves_freq():
  259. # GH#37295 should hold for any DTI with freq=None or Tick freq
  260. tz = "Canada/Eastern"
  261. dti = date_range(
  262. start=Timestamp("2019-03-26 00:00:00-0400", tz=tz),
  263. end=Timestamp("2020-10-17 00:00:00-0400", tz=tz),
  264. freq="D",
  265. )
  266. result = dti + Timedelta(days=1)
  267. assert result.freq == dti.freq