timestamps.pyx 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382
  1. """
  2. _Timestamp is a c-defined subclass of datetime.datetime
  3. _Timestamp is PITA. Because we inherit from datetime, which has very specific
  4. construction requirements, we need to do object instantiation in python
  5. (see Timestamp class below). This will serve as a C extension type that
  6. shadows the python class, where we do any heavy lifting.
  7. """
  8. import warnings
  9. cimport cython
  10. import numpy as np
  11. cimport numpy as cnp
  12. from numpy cimport (
  13. int64_t,
  14. ndarray,
  15. uint8_t,
  16. )
  17. cnp.import_array()
  18. from cpython.datetime cimport ( # alias bc `tzinfo` is a kwarg below
  19. PyDate_Check,
  20. PyDateTime_Check,
  21. PyDelta_Check,
  22. PyTZInfo_Check,
  23. datetime,
  24. import_datetime,
  25. time as dt_time,
  26. tzinfo as tzinfo_type,
  27. )
  28. from cpython.object cimport (
  29. Py_EQ,
  30. Py_GE,
  31. Py_GT,
  32. Py_LE,
  33. Py_LT,
  34. Py_NE,
  35. PyObject_RichCompare,
  36. PyObject_RichCompareBool,
  37. )
  38. import_datetime()
  39. from pandas._libs.tslibs cimport ccalendar
  40. from pandas._libs.tslibs.base cimport ABCTimestamp
  41. from pandas.util._exceptions import find_stack_level
  42. from pandas._libs.tslibs.conversion cimport (
  43. _TSObject,
  44. convert_datetime_to_tsobject,
  45. convert_to_tsobject,
  46. maybe_localize_tso,
  47. )
  48. from pandas._libs.tslibs.dtypes cimport (
  49. npy_unit_to_abbrev,
  50. periods_per_day,
  51. periods_per_second,
  52. )
  53. from pandas._libs.tslibs.util cimport (
  54. is_array,
  55. is_datetime64_object,
  56. is_integer_object,
  57. )
  58. from pandas._libs.tslibs.fields import (
  59. RoundTo,
  60. get_date_name_field,
  61. get_start_end_field,
  62. round_nsint64,
  63. )
  64. from pandas._libs.tslibs.nattype cimport (
  65. NPY_NAT,
  66. c_NaT as NaT,
  67. )
  68. from pandas._libs.tslibs.np_datetime cimport (
  69. NPY_DATETIMEUNIT,
  70. NPY_FR_ns,
  71. check_dts_bounds,
  72. cmp_dtstructs,
  73. cmp_scalar,
  74. convert_reso,
  75. get_datetime64_unit,
  76. get_datetime64_value,
  77. get_unit_from_dtype,
  78. npy_datetimestruct,
  79. npy_datetimestruct_to_datetime,
  80. pandas_datetime_to_datetimestruct,
  81. pydatetime_to_dtstruct,
  82. )
  83. from pandas._libs.tslibs.np_datetime import (
  84. OutOfBoundsDatetime,
  85. OutOfBoundsTimedelta,
  86. )
  87. from pandas._libs.tslibs.offsets cimport to_offset
  88. from pandas._libs.tslibs.timedeltas cimport (
  89. _Timedelta,
  90. delta_to_nanoseconds,
  91. is_any_td_scalar,
  92. )
  93. from pandas._libs.tslibs.timedeltas import Timedelta
  94. from pandas._libs.tslibs.timezones cimport (
  95. get_timezone,
  96. is_utc,
  97. maybe_get_tz,
  98. treat_tz_as_pytz,
  99. utc_stdlib as UTC,
  100. )
  101. from pandas._libs.tslibs.tzconversion cimport (
  102. tz_convert_from_utc_single,
  103. tz_localize_to_utc_single,
  104. )
  105. # ----------------------------------------------------------------------
  106. # Constants
  107. _zero_time = dt_time(0, 0)
  108. _no_input = object()
  109. # ----------------------------------------------------------------------
  110. cdef _Timestamp create_timestamp_from_ts(
  111. int64_t value,
  112. npy_datetimestruct dts,
  113. tzinfo tz,
  114. bint fold,
  115. NPY_DATETIMEUNIT reso=NPY_FR_ns,
  116. ):
  117. """ convenience routine to construct a Timestamp from its parts """
  118. cdef:
  119. _Timestamp ts_base
  120. int64_t pass_year = dts.year
  121. # We pass year=1970/1972 here and set year below because with non-nanosecond
  122. # resolution we may have datetimes outside of the stdlib pydatetime
  123. # implementation bounds, which would raise.
  124. # NB: this means the C-API macro PyDateTime_GET_YEAR is unreliable.
  125. if 1 <= pass_year <= 9999:
  126. # we are in-bounds for pydatetime
  127. pass
  128. elif ccalendar.is_leapyear(dts.year):
  129. pass_year = 1972
  130. else:
  131. pass_year = 1970
  132. ts_base = _Timestamp.__new__(Timestamp, pass_year, dts.month,
  133. dts.day, dts.hour, dts.min,
  134. dts.sec, dts.us, tz, fold=fold)
  135. ts_base._value = value
  136. ts_base.year = dts.year
  137. ts_base.nanosecond = dts.ps // 1000
  138. ts_base._creso = reso
  139. return ts_base
  140. def _unpickle_timestamp(value, freq, tz, reso=NPY_FR_ns):
  141. # GH#41949 dont warn on unpickle if we have a freq
  142. ts = Timestamp._from_value_and_reso(value, reso, tz)
  143. return ts
  144. # ----------------------------------------------------------------------
  145. def integer_op_not_supported(obj):
  146. # GH#22535 add/sub of integers and int-arrays is no longer allowed
  147. # Note we return rather than raise the exception so we can raise in
  148. # the caller; mypy finds this more palatable.
  149. cls = type(obj).__name__
  150. # GH#30886 using an fstring raises SystemError
  151. int_addsub_msg = (
  152. f"Addition/subtraction of integers and integer-arrays with {cls} is "
  153. "no longer supported. Instead of adding/subtracting `n`, "
  154. "use `n * obj.freq`"
  155. )
  156. return TypeError(int_addsub_msg)
  157. class MinMaxReso:
  158. """
  159. We need to define min/max/resolution on both the Timestamp _instance_
  160. and Timestamp class. On an instance, these depend on the object's _reso.
  161. On the class, we default to the values we would get with nanosecond _reso.
  162. See also: timedeltas.MinMaxReso
  163. """
  164. def __init__(self, name):
  165. self._name = name
  166. def __get__(self, obj, type=None):
  167. cls = Timestamp
  168. if self._name == "min":
  169. val = np.iinfo(np.int64).min + 1
  170. elif self._name == "max":
  171. val = np.iinfo(np.int64).max
  172. else:
  173. assert self._name == "resolution"
  174. val = 1
  175. cls = Timedelta
  176. if obj is None:
  177. # i.e. this is on the class, default to nanos
  178. return cls(val)
  179. elif self._name == "resolution":
  180. return Timedelta._from_value_and_reso(val, obj._creso)
  181. else:
  182. return Timestamp._from_value_and_reso(val, obj._creso, tz=None)
  183. def __set__(self, obj, value):
  184. raise AttributeError(f"{self._name} is not settable.")
  185. # ----------------------------------------------------------------------
  186. cdef class _Timestamp(ABCTimestamp):
  187. # higher than np.ndarray and np.matrix
  188. __array_priority__ = 100
  189. dayofweek = _Timestamp.day_of_week
  190. dayofyear = _Timestamp.day_of_year
  191. min = MinMaxReso("min")
  192. max = MinMaxReso("max")
  193. resolution = MinMaxReso("resolution") # GH#21336, GH#21365
  194. @property
  195. def value(self) -> int:
  196. try:
  197. return convert_reso(self._value, self._creso, NPY_FR_ns, False)
  198. except OverflowError:
  199. raise OverflowError(
  200. "Cannot convert Timestamp to nanoseconds without overflow. "
  201. "Use `.asm8.view('i8')` to cast represent Timestamp in its own "
  202. f"unit (here, {self.unit})."
  203. )
  204. @property
  205. def unit(self) -> str:
  206. """
  207. The abbreviation associated with self._creso.
  208. Examples
  209. --------
  210. >>> pd.Timestamp("2020-01-01 12:34:56").unit
  211. 's'
  212. >>> pd.Timestamp("2020-01-01 12:34:56.123").unit
  213. 'ms'
  214. >>> pd.Timestamp("2020-01-01 12:34:56.123456").unit
  215. 'us'
  216. >>> pd.Timestamp("2020-01-01 12:34:56.123456789").unit
  217. 'ns'
  218. """
  219. return npy_unit_to_abbrev(self._creso)
  220. # -----------------------------------------------------------------
  221. # Constructors
  222. @classmethod
  223. def _from_value_and_reso(cls, int64_t value, NPY_DATETIMEUNIT reso, tzinfo tz):
  224. cdef:
  225. _TSObject obj = _TSObject()
  226. if value == NPY_NAT:
  227. return NaT
  228. if reso < NPY_DATETIMEUNIT.NPY_FR_s or reso > NPY_DATETIMEUNIT.NPY_FR_ns:
  229. raise NotImplementedError(
  230. "Only resolutions 's', 'ms', 'us', 'ns' are supported."
  231. )
  232. obj.value = value
  233. obj.creso = reso
  234. pandas_datetime_to_datetimestruct(value, reso, &obj.dts)
  235. maybe_localize_tso(obj, tz, reso)
  236. return create_timestamp_from_ts(
  237. value, obj.dts, tz=obj.tzinfo, fold=obj.fold, reso=reso
  238. )
  239. @classmethod
  240. def _from_dt64(cls, dt64: np.datetime64):
  241. # construct a Timestamp from a np.datetime64 object, keeping the
  242. # resolution of the input.
  243. # This is herely mainly so we can incrementally implement non-nano
  244. # (e.g. only tznaive at first)
  245. cdef:
  246. int64_t value
  247. NPY_DATETIMEUNIT reso
  248. reso = get_datetime64_unit(dt64)
  249. value = get_datetime64_value(dt64)
  250. return cls._from_value_and_reso(value, reso, None)
  251. # -----------------------------------------------------------------
  252. def __hash__(_Timestamp self):
  253. if self.nanosecond:
  254. return hash(self._value)
  255. if not (1 <= self.year <= 9999):
  256. # out of bounds for pydatetime
  257. return hash(self._value)
  258. if self.fold:
  259. return datetime.__hash__(self.replace(fold=0))
  260. return datetime.__hash__(self)
  261. def __richcmp__(_Timestamp self, object other, int op):
  262. cdef:
  263. _Timestamp ots
  264. if isinstance(other, _Timestamp):
  265. ots = other
  266. elif other is NaT:
  267. return op == Py_NE
  268. elif is_datetime64_object(other):
  269. ots = Timestamp(other)
  270. elif PyDateTime_Check(other):
  271. if self.nanosecond == 0:
  272. val = self.to_pydatetime()
  273. return PyObject_RichCompareBool(val, other, op)
  274. try:
  275. ots = type(self)(other)
  276. except ValueError:
  277. return self._compare_outside_nanorange(other, op)
  278. elif is_array(other):
  279. # avoid recursion error GH#15183
  280. if other.dtype.kind == "M":
  281. if self.tz is None:
  282. return PyObject_RichCompare(self.asm8, other, op)
  283. elif op == Py_NE:
  284. return np.ones(other.shape, dtype=np.bool_)
  285. elif op == Py_EQ:
  286. return np.zeros(other.shape, dtype=np.bool_)
  287. raise TypeError(
  288. "Cannot compare tz-naive and tz-aware timestamps"
  289. )
  290. elif other.dtype.kind == "O":
  291. # Operate element-wise
  292. return np.array(
  293. [PyObject_RichCompare(self, x, op) for x in other],
  294. dtype=bool,
  295. )
  296. elif op == Py_NE:
  297. return np.ones(other.shape, dtype=np.bool_)
  298. elif op == Py_EQ:
  299. return np.zeros(other.shape, dtype=np.bool_)
  300. return NotImplemented
  301. elif PyDate_Check(other):
  302. # returning NotImplemented defers to the `date` implementation
  303. # which incorrectly drops tz and normalizes to midnight
  304. # before comparing
  305. # We follow the stdlib datetime behavior of never being equal
  306. if op == Py_EQ:
  307. return False
  308. elif op == Py_NE:
  309. return True
  310. raise TypeError(
  311. "Cannot compare Timestamp with datetime.date. "
  312. "Use ts == pd.Timestamp(date) or ts.date() == date instead."
  313. )
  314. else:
  315. return NotImplemented
  316. if not self._can_compare(ots):
  317. if op == Py_NE or op == Py_EQ:
  318. return NotImplemented
  319. raise TypeError(
  320. "Cannot compare tz-naive and tz-aware timestamps"
  321. )
  322. if self._creso == ots._creso:
  323. return cmp_scalar(self._value, ots._value, op)
  324. return self._compare_mismatched_resos(ots, op)
  325. # TODO: copied from Timedelta; try to de-duplicate
  326. cdef bint _compare_mismatched_resos(self, _Timestamp other, int op):
  327. # Can't just dispatch to numpy as they silently overflow and get it wrong
  328. cdef:
  329. npy_datetimestruct dts_self
  330. npy_datetimestruct dts_other
  331. # dispatch to the datetimestruct utils instead of writing new ones!
  332. pandas_datetime_to_datetimestruct(self._value, self._creso, &dts_self)
  333. pandas_datetime_to_datetimestruct(other._value, other._creso, &dts_other)
  334. return cmp_dtstructs(&dts_self, &dts_other, op)
  335. cdef bint _compare_outside_nanorange(_Timestamp self, datetime other,
  336. int op) except -1:
  337. cdef:
  338. datetime dtval = self.to_pydatetime(warn=False)
  339. if not self._can_compare(other):
  340. return NotImplemented
  341. if self.nanosecond == 0:
  342. return PyObject_RichCompareBool(dtval, other, op)
  343. # otherwise we have dtval < self
  344. if op == Py_NE:
  345. return True
  346. if op == Py_EQ:
  347. return False
  348. if op == Py_LE or op == Py_LT:
  349. return self.year <= other.year
  350. if op == Py_GE or op == Py_GT:
  351. return self.year >= other.year
  352. cdef bint _can_compare(self, datetime other):
  353. if self.tzinfo is not None:
  354. return other.tzinfo is not None
  355. return other.tzinfo is None
  356. @cython.overflowcheck(True)
  357. def __add__(self, other):
  358. cdef:
  359. int64_t nanos = 0
  360. if is_any_td_scalar(other):
  361. other = Timedelta(other)
  362. # TODO: share this with __sub__, Timedelta.__add__
  363. # Matching numpy, we cast to the higher resolution. Unlike numpy,
  364. # we raise instead of silently overflowing during this casting.
  365. if self._creso < other._creso:
  366. self = (<_Timestamp>self)._as_creso(other._creso, round_ok=True)
  367. elif self._creso > other._creso:
  368. other = (<_Timedelta>other)._as_creso(self._creso, round_ok=True)
  369. nanos = other._value
  370. try:
  371. new_value = self._value+ nanos
  372. result = type(self)._from_value_and_reso(
  373. new_value, reso=self._creso, tz=self.tzinfo
  374. )
  375. except OverflowError as err:
  376. # TODO: don't hard-code nanosecond here
  377. new_value = int(self._value) + int(nanos)
  378. raise OutOfBoundsDatetime(
  379. f"Out of bounds nanosecond timestamp: {new_value}"
  380. ) from err
  381. return result
  382. elif is_integer_object(other):
  383. raise integer_op_not_supported(self)
  384. elif is_array(other):
  385. if other.dtype.kind in ["i", "u"]:
  386. raise integer_op_not_supported(self)
  387. if other.dtype.kind == "m":
  388. if self.tz is None:
  389. return self.asm8 + other
  390. return np.asarray(
  391. [self + other[n] for n in range(len(other))],
  392. dtype=object,
  393. )
  394. elif not isinstance(self, _Timestamp):
  395. # cython semantics, args have been switched and this is __radd__
  396. # TODO(cython3): remove this it moved to __radd__
  397. return other.__add__(self)
  398. return NotImplemented
  399. def __radd__(self, other):
  400. # Have to duplicate checks to avoid infinite recursion due to NotImplemented
  401. if is_any_td_scalar(other) or is_integer_object(other) or is_array(other):
  402. return self.__add__(other)
  403. return NotImplemented
  404. def __sub__(self, other):
  405. if other is NaT:
  406. return NaT
  407. elif is_any_td_scalar(other) or is_integer_object(other):
  408. neg_other = -other
  409. return self + neg_other
  410. elif is_array(other):
  411. if other.dtype.kind in ["i", "u"]:
  412. raise integer_op_not_supported(self)
  413. if other.dtype.kind == "m":
  414. if self.tz is None:
  415. return self.asm8 - other
  416. return np.asarray(
  417. [self - other[n] for n in range(len(other))],
  418. dtype=object,
  419. )
  420. return NotImplemented
  421. # coerce if necessary if we are a Timestamp-like
  422. if (PyDateTime_Check(self)
  423. and (PyDateTime_Check(other) or is_datetime64_object(other))):
  424. # both_timestamps is to determine whether Timedelta(self - other)
  425. # should raise the OOB error, or fall back returning a timedelta.
  426. # TODO(cython3): clean out the bits that moved to __rsub__
  427. both_timestamps = (isinstance(other, _Timestamp) and
  428. isinstance(self, _Timestamp))
  429. if isinstance(self, _Timestamp):
  430. other = type(self)(other)
  431. else:
  432. self = type(other)(self)
  433. if (self.tzinfo is None) ^ (other.tzinfo is None):
  434. raise TypeError(
  435. "Cannot subtract tz-naive and tz-aware datetime-like objects."
  436. )
  437. # Matching numpy, we cast to the higher resolution. Unlike numpy,
  438. # we raise instead of silently overflowing during this casting.
  439. if self._creso < other._creso:
  440. self = (<_Timestamp>self)._as_creso(other._creso, round_ok=True)
  441. elif self._creso > other._creso:
  442. other = (<_Timestamp>other)._as_creso(self._creso, round_ok=True)
  443. # scalar Timestamp/datetime - Timestamp/datetime -> yields a
  444. # Timedelta
  445. try:
  446. res_value = self._value- other._value
  447. return Timedelta._from_value_and_reso(res_value, self._creso)
  448. except (OverflowError, OutOfBoundsDatetime, OutOfBoundsTimedelta) as err:
  449. if isinstance(other, _Timestamp):
  450. if both_timestamps:
  451. raise OutOfBoundsDatetime(
  452. "Result is too large for pandas.Timedelta. Convert inputs "
  453. "to datetime.datetime with 'Timestamp.to_pydatetime()' "
  454. "before subtracting."
  455. ) from err
  456. # We get here in stata tests, fall back to stdlib datetime
  457. # method and return stdlib timedelta object
  458. pass
  459. elif is_datetime64_object(self):
  460. # GH#28286 cython semantics for __rsub__, `other` is actually
  461. # the Timestamp
  462. # TODO(cython3): remove this, this moved to __rsub__
  463. return type(other)(self) - other
  464. return NotImplemented
  465. def __rsub__(self, other):
  466. if PyDateTime_Check(other):
  467. try:
  468. return type(self)(other) - self
  469. except (OverflowError, OutOfBoundsDatetime) as err:
  470. # We get here in stata tests, fall back to stdlib datetime
  471. # method and return stdlib timedelta object
  472. pass
  473. elif is_datetime64_object(other):
  474. return type(self)(other) - self
  475. return NotImplemented
  476. # -----------------------------------------------------------------
  477. cdef int64_t _maybe_convert_value_to_local(self):
  478. """Convert UTC i8 value to local i8 value if tz exists"""
  479. cdef:
  480. int64_t val
  481. tzinfo own_tz = self.tzinfo
  482. npy_datetimestruct dts
  483. if own_tz is not None and not is_utc(own_tz):
  484. pydatetime_to_dtstruct(self, &dts)
  485. val = npy_datetimestruct_to_datetime(self._creso, &dts) + self.nanosecond
  486. else:
  487. val = self._value
  488. return val
  489. @cython.boundscheck(False)
  490. cdef bint _get_start_end_field(self, str field, freq):
  491. cdef:
  492. int64_t val
  493. dict kwds
  494. ndarray[uint8_t, cast=True] out
  495. int month_kw
  496. if freq:
  497. kwds = freq.kwds
  498. month_kw = kwds.get("startingMonth", kwds.get("month", 12))
  499. freqstr = freq.freqstr
  500. else:
  501. month_kw = 12
  502. freqstr = None
  503. val = self._maybe_convert_value_to_local()
  504. out = get_start_end_field(np.array([val], dtype=np.int64),
  505. field, freqstr, month_kw, self._creso)
  506. return out[0]
  507. @property
  508. def is_month_start(self) -> bool:
  509. """
  510. Check if the date is the first day of the month.
  511. Returns
  512. -------
  513. bool
  514. True if the date is the first day of the month.
  515. See Also
  516. --------
  517. Timestamp.is_month_end : Similar property indicating the last day of the month.
  518. Examples
  519. --------
  520. >>> ts = pd.Timestamp(2020, 3, 14)
  521. >>> ts.is_month_start
  522. False
  523. >>> ts = pd.Timestamp(2020, 1, 1)
  524. >>> ts.is_month_start
  525. True
  526. """
  527. return self.day == 1
  528. @property
  529. def is_month_end(self) -> bool:
  530. """
  531. Check if the date is the last day of the month.
  532. Returns
  533. -------
  534. bool
  535. True if the date is the last day of the month.
  536. See Also
  537. --------
  538. Timestamp.is_month_start : Similar property indicating month start.
  539. Examples
  540. --------
  541. >>> ts = pd.Timestamp(2020, 3, 14)
  542. >>> ts.is_month_end
  543. False
  544. >>> ts = pd.Timestamp(2020, 12, 31)
  545. >>> ts.is_month_end
  546. True
  547. """
  548. return self.day == self.days_in_month
  549. @property
  550. def is_quarter_start(self) -> bool:
  551. """
  552. Check if the date is the first day of the quarter.
  553. Returns
  554. -------
  555. bool
  556. True if date is first day of the quarter.
  557. See Also
  558. --------
  559. Timestamp.is_quarter_end : Similar property indicating the quarter end.
  560. Timestamp.quarter : Return the quarter of the date.
  561. Examples
  562. --------
  563. >>> ts = pd.Timestamp(2020, 3, 14)
  564. >>> ts.is_quarter_start
  565. False
  566. >>> ts = pd.Timestamp(2020, 4, 1)
  567. >>> ts.is_quarter_start
  568. True
  569. """
  570. return self.day == 1 and self.month % 3 == 1
  571. @property
  572. def is_quarter_end(self) -> bool:
  573. """
  574. Check if date is last day of the quarter.
  575. Returns
  576. -------
  577. bool
  578. True if date is last day of the quarter.
  579. See Also
  580. --------
  581. Timestamp.is_quarter_start : Similar property indicating the quarter start.
  582. Timestamp.quarter : Return the quarter of the date.
  583. Examples
  584. --------
  585. >>> ts = pd.Timestamp(2020, 3, 14)
  586. >>> ts.is_quarter_end
  587. False
  588. >>> ts = pd.Timestamp(2020, 3, 31)
  589. >>> ts.is_quarter_end
  590. True
  591. """
  592. return (self.month % 3) == 0 and self.day == self.days_in_month
  593. @property
  594. def is_year_start(self) -> bool:
  595. """
  596. Return True if date is first day of the year.
  597. Returns
  598. -------
  599. bool
  600. See Also
  601. --------
  602. Timestamp.is_year_end : Similar property indicating the end of the year.
  603. Examples
  604. --------
  605. >>> ts = pd.Timestamp(2020, 3, 14)
  606. >>> ts.is_year_start
  607. False
  608. >>> ts = pd.Timestamp(2020, 1, 1)
  609. >>> ts.is_year_start
  610. True
  611. """
  612. return self.day == self.month == 1
  613. @property
  614. def is_year_end(self) -> bool:
  615. """
  616. Return True if date is last day of the year.
  617. Returns
  618. -------
  619. bool
  620. See Also
  621. --------
  622. Timestamp.is_year_start : Similar property indicating the start of the year.
  623. Examples
  624. --------
  625. >>> ts = pd.Timestamp(2020, 3, 14)
  626. >>> ts.is_year_end
  627. False
  628. >>> ts = pd.Timestamp(2020, 12, 31)
  629. >>> ts.is_year_end
  630. True
  631. """
  632. return self.month == 12 and self.day == 31
  633. @cython.boundscheck(False)
  634. cdef _get_date_name_field(self, str field, object locale):
  635. cdef:
  636. int64_t val
  637. object[::1] out
  638. val = self._maybe_convert_value_to_local()
  639. out = get_date_name_field(np.array([val], dtype=np.int64),
  640. field, locale=locale, reso=self._creso)
  641. return out[0]
  642. def day_name(self, locale=None) -> str:
  643. """
  644. Return the day name of the Timestamp with specified locale.
  645. Parameters
  646. ----------
  647. locale : str, default None (English locale)
  648. Locale determining the language in which to return the day name.
  649. Returns
  650. -------
  651. str
  652. Examples
  653. --------
  654. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  655. >>> ts.day_name()
  656. 'Saturday'
  657. Analogous for ``pd.NaT``:
  658. >>> pd.NaT.day_name()
  659. nan
  660. """
  661. return self._get_date_name_field("day_name", locale)
  662. def month_name(self, locale=None) -> str:
  663. """
  664. Return the month name of the Timestamp with specified locale.
  665. Parameters
  666. ----------
  667. locale : str, default None (English locale)
  668. Locale determining the language in which to return the month name.
  669. Returns
  670. -------
  671. str
  672. Examples
  673. --------
  674. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  675. >>> ts.month_name()
  676. 'March'
  677. Analogous for ``pd.NaT``:
  678. >>> pd.NaT.month_name()
  679. nan
  680. """
  681. return self._get_date_name_field("month_name", locale)
  682. @property
  683. def is_leap_year(self) -> bool:
  684. """
  685. Return True if year is a leap year.
  686. Returns
  687. -------
  688. bool
  689. Examples
  690. --------
  691. >>> ts = pd.Timestamp(2020, 3, 14)
  692. >>> ts.is_leap_year
  693. True
  694. """
  695. return bool(ccalendar.is_leapyear(self.year))
  696. @property
  697. def day_of_week(self) -> int:
  698. """
  699. Return day of the week.
  700. Returns
  701. -------
  702. int
  703. Examples
  704. --------
  705. >>> ts = pd.Timestamp(2020, 3, 14)
  706. >>> ts.day_of_week
  707. 5
  708. """
  709. return self.weekday()
  710. @property
  711. def day_of_year(self) -> int:
  712. """
  713. Return the day of the year.
  714. Returns
  715. -------
  716. int
  717. Examples
  718. --------
  719. >>> ts = pd.Timestamp(2020, 3, 14)
  720. >>> ts.day_of_year
  721. 74
  722. """
  723. return ccalendar.get_day_of_year(self.year, self.month, self.day)
  724. @property
  725. def quarter(self) -> int:
  726. """
  727. Return the quarter of the year.
  728. Returns
  729. -------
  730. int
  731. Examples
  732. --------
  733. >>> ts = pd.Timestamp(2020, 3, 14)
  734. >>> ts.quarter
  735. 1
  736. """
  737. return ((self.month - 1) // 3) + 1
  738. @property
  739. def week(self) -> int:
  740. """
  741. Return the week number of the year.
  742. Returns
  743. -------
  744. int
  745. Examples
  746. --------
  747. >>> ts = pd.Timestamp(2020, 3, 14)
  748. >>> ts.week
  749. 11
  750. """
  751. return ccalendar.get_week_of_year(self.year, self.month, self.day)
  752. @property
  753. def days_in_month(self) -> int:
  754. """
  755. Return the number of days in the month.
  756. Returns
  757. -------
  758. int
  759. Examples
  760. --------
  761. >>> ts = pd.Timestamp(2020, 3, 14)
  762. >>> ts.days_in_month
  763. 31
  764. """
  765. return ccalendar.get_days_in_month(self.year, self.month)
  766. # -----------------------------------------------------------------
  767. # Transformation Methods
  768. def normalize(self) -> "Timestamp":
  769. """
  770. Normalize Timestamp to midnight, preserving tz information.
  771. Examples
  772. --------
  773. >>> ts = pd.Timestamp(2020, 3, 14, 15, 30)
  774. >>> ts.normalize()
  775. Timestamp('2020-03-14 00:00:00')
  776. """
  777. cdef:
  778. local_val = self._maybe_convert_value_to_local()
  779. int64_t normalized
  780. int64_t ppd = periods_per_day(self._creso)
  781. _Timestamp ts
  782. normalized = normalize_i8_stamp(local_val, ppd)
  783. ts = type(self)._from_value_and_reso(normalized, reso=self._creso, tz=None)
  784. return ts.tz_localize(self.tzinfo)
  785. # -----------------------------------------------------------------
  786. # Pickle Methods
  787. def __reduce_ex__(self, protocol):
  788. # python 3.6 compat
  789. # https://bugs.python.org/issue28730
  790. # now __reduce_ex__ is defined and higher priority than __reduce__
  791. return self.__reduce__()
  792. def __setstate__(self, state):
  793. self._value= state[0]
  794. self.tzinfo = state[2]
  795. if len(state) == 3:
  796. # pre-non-nano pickle
  797. # TODO: no tests get here 2022-05-10
  798. reso = NPY_FR_ns
  799. else:
  800. reso = state[4]
  801. self._creso = reso
  802. def __reduce__(self):
  803. object_state = self._value, None, self.tzinfo, self._creso
  804. return (_unpickle_timestamp, object_state)
  805. # -----------------------------------------------------------------
  806. # Rendering Methods
  807. def isoformat(self, sep: str = "T", timespec: str = "auto") -> str:
  808. """
  809. Return the time formatted according to ISO 8610.
  810. The full format looks like 'YYYY-MM-DD HH:MM:SS.mmmmmmnnn'.
  811. By default, the fractional part is omitted if self.microsecond == 0
  812. and self.nanosecond == 0.
  813. If self.tzinfo is not None, the UTC offset is also attached, giving
  814. giving a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmmnnn+HH:MM'.
  815. Parameters
  816. ----------
  817. sep : str, default 'T'
  818. String used as the separator between the date and time.
  819. timespec : str, default 'auto'
  820. Specifies the number of additional terms of the time to include.
  821. The valid values are 'auto', 'hours', 'minutes', 'seconds',
  822. 'milliseconds', 'microseconds', and 'nanoseconds'.
  823. Returns
  824. -------
  825. str
  826. Examples
  827. --------
  828. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  829. >>> ts.isoformat()
  830. '2020-03-14T15:32:52.192548651'
  831. >>> ts.isoformat(timespec='microseconds')
  832. '2020-03-14T15:32:52.192548'
  833. """
  834. base_ts = "microseconds" if timespec == "nanoseconds" else timespec
  835. base = super(_Timestamp, self).isoformat(sep=sep, timespec=base_ts)
  836. # We need to replace the fake year 1970 with our real year
  837. base = f"{self.year:04d}-" + base.split("-", 1)[1]
  838. if self.nanosecond == 0 and timespec != "nanoseconds":
  839. return base
  840. if self.tzinfo is not None:
  841. base1, base2 = base[:-6], base[-6:]
  842. else:
  843. base1, base2 = base, ""
  844. if timespec == "nanoseconds" or (timespec == "auto" and self.nanosecond):
  845. if self.microsecond:
  846. base1 += f"{self.nanosecond:03d}"
  847. else:
  848. base1 += f".{self.nanosecond:09d}"
  849. return base1 + base2
  850. def __repr__(self) -> str:
  851. stamp = self._repr_base
  852. zone = None
  853. if self.tzinfo is not None:
  854. try:
  855. stamp += self.strftime("%z")
  856. except ValueError:
  857. year2000 = self.replace(year=2000)
  858. stamp += year2000.strftime("%z")
  859. zone = get_timezone(self.tzinfo)
  860. try:
  861. stamp += zone.strftime(" %%Z")
  862. except AttributeError:
  863. # e.g. tzlocal has no `strftime`
  864. pass
  865. tz = f", tz='{zone}'" if zone is not None else ""
  866. return f"Timestamp('{stamp}'{tz})"
  867. @property
  868. def _repr_base(self) -> str:
  869. return f"{self._date_repr} {self._time_repr}"
  870. @property
  871. def _date_repr(self) -> str:
  872. # Ideal here would be self.strftime("%Y-%m-%d"), but
  873. # the datetime strftime() methods require year >= 1900 and is slower
  874. return f"{self.year}-{self.month:02d}-{self.day:02d}"
  875. @property
  876. def _time_repr(self) -> str:
  877. result = f"{self.hour:02d}:{self.minute:02d}:{self.second:02d}"
  878. if self.nanosecond != 0:
  879. result += f".{self.nanosecond + 1000 * self.microsecond:09d}"
  880. elif self.microsecond != 0:
  881. result += f".{self.microsecond:06d}"
  882. return result
  883. @property
  884. def _short_repr(self) -> str:
  885. # format a Timestamp with only _date_repr if possible
  886. # otherwise _repr_base
  887. if (self.hour == 0 and
  888. self.minute == 0 and
  889. self.second == 0 and
  890. self.microsecond == 0 and
  891. self.nanosecond == 0):
  892. return self._date_repr
  893. return self._repr_base
  894. # -----------------------------------------------------------------
  895. # Conversion Methods
  896. @cython.cdivision(False)
  897. cdef _Timestamp _as_creso(self, NPY_DATETIMEUNIT creso, bint round_ok=True):
  898. cdef:
  899. int64_t value
  900. if creso == self._creso:
  901. return self
  902. try:
  903. value = convert_reso(self._value, self._creso, creso, round_ok=round_ok)
  904. except OverflowError as err:
  905. unit = npy_unit_to_abbrev(creso)
  906. raise OutOfBoundsDatetime(
  907. f"Cannot cast {self} to unit='{unit}' without overflow."
  908. ) from err
  909. return type(self)._from_value_and_reso(value, reso=creso, tz=self.tzinfo)
  910. def as_unit(self, str unit, bint round_ok=True):
  911. """
  912. Convert the underlying int64 representaton to the given unit.
  913. Parameters
  914. ----------
  915. unit : {"ns", "us", "ms", "s"}
  916. round_ok : bool, default True
  917. If False and the conversion requires rounding, raise.
  918. Returns
  919. -------
  920. Timestamp
  921. """
  922. dtype = np.dtype(f"M8[{unit}]")
  923. reso = get_unit_from_dtype(dtype)
  924. try:
  925. return self._as_creso(reso, round_ok=round_ok)
  926. except OverflowError as err:
  927. raise OutOfBoundsDatetime(
  928. f"Cannot cast {self} to unit='{unit}' without overflow."
  929. ) from err
  930. @property
  931. def asm8(self) -> np.datetime64:
  932. """
  933. Return numpy datetime64 format in nanoseconds.
  934. Examples
  935. --------
  936. >>> ts = pd.Timestamp(2020, 3, 14, 15)
  937. >>> ts.asm8
  938. numpy.datetime64('2020-03-14T15:00:00.000000')
  939. """
  940. return self.to_datetime64()
  941. def timestamp(self):
  942. """
  943. Return POSIX timestamp as float.
  944. Examples
  945. --------
  946. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548')
  947. >>> ts.timestamp()
  948. 1584199972.192548
  949. """
  950. # GH 17329
  951. # Note: Naive timestamps will not match datetime.stdlib
  952. denom = periods_per_second(self._creso)
  953. return round(self._value/ denom, 6)
  954. cpdef datetime to_pydatetime(_Timestamp self, bint warn=True):
  955. """
  956. Convert a Timestamp object to a native Python datetime object.
  957. If warn=True, issue a warning if nanoseconds is nonzero.
  958. Examples
  959. --------
  960. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548')
  961. >>> ts.to_pydatetime()
  962. datetime.datetime(2020, 3, 14, 15, 32, 52, 192548)
  963. Analogous for ``pd.NaT``:
  964. >>> pd.NaT.to_pydatetime()
  965. NaT
  966. """
  967. if self.nanosecond != 0 and warn:
  968. warnings.warn("Discarding nonzero nanoseconds in conversion.",
  969. UserWarning, stacklevel=find_stack_level())
  970. return datetime(self.year, self.month, self.day,
  971. self.hour, self.minute, self.second,
  972. self.microsecond, self.tzinfo, fold=self.fold)
  973. cpdef to_datetime64(self):
  974. """
  975. Return a numpy.datetime64 object with 'ns' precision.
  976. """
  977. # TODO: find a way to construct dt64 directly from _reso
  978. abbrev = npy_unit_to_abbrev(self._creso)
  979. return np.datetime64(self._value, abbrev)
  980. def to_numpy(self, dtype=None, copy=False) -> np.datetime64:
  981. """
  982. Convert the Timestamp to a NumPy datetime64.
  983. This is an alias method for `Timestamp.to_datetime64()`. The dtype and
  984. copy parameters are available here only for compatibility. Their values
  985. will not affect the return value.
  986. Returns
  987. -------
  988. numpy.datetime64
  989. See Also
  990. --------
  991. DatetimeIndex.to_numpy : Similar method for DatetimeIndex.
  992. Examples
  993. --------
  994. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  995. >>> ts.to_numpy()
  996. numpy.datetime64('2020-03-14T15:32:52.192548651')
  997. Analogous for ``pd.NaT``:
  998. >>> pd.NaT.to_numpy()
  999. numpy.datetime64('NaT')
  1000. """
  1001. if dtype is not None or copy is not False:
  1002. raise ValueError(
  1003. "Timestamp.to_numpy dtype and copy arguments are ignored."
  1004. )
  1005. return self.to_datetime64()
  1006. def to_period(self, freq=None):
  1007. """
  1008. Return an period of which this timestamp is an observation.
  1009. Examples
  1010. --------
  1011. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  1012. >>> # Year end frequency
  1013. >>> ts.to_period(freq='Y')
  1014. Period('2020', 'A-DEC')
  1015. >>> # Month end frequency
  1016. >>> ts.to_period(freq='M')
  1017. Period('2020-03', 'M')
  1018. >>> # Weekly frequency
  1019. >>> ts.to_period(freq='W')
  1020. Period('2020-03-09/2020-03-15', 'W-SUN')
  1021. >>> # Quarter end frequency
  1022. >>> ts.to_period(freq='Q')
  1023. Period('2020Q1', 'Q-DEC')
  1024. """
  1025. from pandas import Period
  1026. if self.tz is not None:
  1027. # GH#21333
  1028. warnings.warn(
  1029. "Converting to Period representation will drop timezone information.",
  1030. UserWarning,
  1031. stacklevel=find_stack_level(),
  1032. )
  1033. return Period(self, freq=freq)
  1034. # ----------------------------------------------------------------------
  1035. # Python front end to C extension type _Timestamp
  1036. # This serves as the box for datetime64
  1037. class Timestamp(_Timestamp):
  1038. """
  1039. Pandas replacement for python datetime.datetime object.
  1040. Timestamp is the pandas equivalent of python's Datetime
  1041. and is interchangeable with it in most cases. It's the type used
  1042. for the entries that make up a DatetimeIndex, and other timeseries
  1043. oriented data structures in pandas.
  1044. Parameters
  1045. ----------
  1046. ts_input : datetime-like, str, int, float
  1047. Value to be converted to Timestamp.
  1048. year, month, day : int
  1049. hour, minute, second, microsecond : int, optional, default 0
  1050. tzinfo : datetime.tzinfo, optional, default None
  1051. nanosecond : int, optional, default 0
  1052. tz : str, pytz.timezone, dateutil.tz.tzfile or None
  1053. Time zone for time which Timestamp will have.
  1054. unit : str
  1055. Unit used for conversion if ts_input is of type int or float. The
  1056. valid values are 'D', 'h', 'm', 's', 'ms', 'us', and 'ns'. For
  1057. example, 's' means seconds and 'ms' means milliseconds.
  1058. For float inputs, the result will be stored in nanoseconds, and
  1059. the unit attribute will be set as ``'ns'``.
  1060. fold : {0, 1}, default None, keyword-only
  1061. Due to daylight saving time, one wall clock time can occur twice
  1062. when shifting from summer to winter time; fold describes whether the
  1063. datetime-like corresponds to the first (0) or the second time (1)
  1064. the wall clock hits the ambiguous time.
  1065. .. versionadded:: 1.1.0
  1066. Notes
  1067. -----
  1068. There are essentially three calling conventions for the constructor. The
  1069. primary form accepts four parameters. They can be passed by position or
  1070. keyword.
  1071. The other two forms mimic the parameters from ``datetime.datetime``. They
  1072. can be passed by either position or keyword, but not both mixed together.
  1073. Examples
  1074. --------
  1075. Using the primary calling convention:
  1076. This converts a datetime-like string
  1077. >>> pd.Timestamp('2017-01-01T12')
  1078. Timestamp('2017-01-01 12:00:00')
  1079. This converts a float representing a Unix epoch in units of seconds
  1080. >>> pd.Timestamp(1513393355.5, unit='s')
  1081. Timestamp('2017-12-16 03:02:35.500000')
  1082. This converts an int representing a Unix-epoch in units of seconds
  1083. and for a particular timezone
  1084. >>> pd.Timestamp(1513393355, unit='s', tz='US/Pacific')
  1085. Timestamp('2017-12-15 19:02:35-0800', tz='US/Pacific')
  1086. Using the other two forms that mimic the API for ``datetime.datetime``:
  1087. >>> pd.Timestamp(2017, 1, 1, 12)
  1088. Timestamp('2017-01-01 12:00:00')
  1089. >>> pd.Timestamp(year=2017, month=1, day=1, hour=12)
  1090. Timestamp('2017-01-01 12:00:00')
  1091. """
  1092. @classmethod
  1093. def fromordinal(cls, ordinal, tz=None):
  1094. """
  1095. Construct a timestamp from a a proleptic Gregorian ordinal.
  1096. Parameters
  1097. ----------
  1098. ordinal : int
  1099. Date corresponding to a proleptic Gregorian ordinal.
  1100. tz : str, pytz.timezone, dateutil.tz.tzfile or None
  1101. Time zone for the Timestamp.
  1102. Notes
  1103. -----
  1104. By definition there cannot be any tz info on the ordinal itself.
  1105. Examples
  1106. --------
  1107. >>> pd.Timestamp.fromordinal(737425)
  1108. Timestamp('2020-01-01 00:00:00')
  1109. """
  1110. return cls(datetime.fromordinal(ordinal), tz=tz)
  1111. @classmethod
  1112. def now(cls, tz=None):
  1113. """
  1114. Return new Timestamp object representing current time local to tz.
  1115. Parameters
  1116. ----------
  1117. tz : str or timezone object, default None
  1118. Timezone to localize to.
  1119. Examples
  1120. --------
  1121. >>> pd.Timestamp.now() # doctest: +SKIP
  1122. Timestamp('2020-11-16 22:06:16.378782')
  1123. Analogous for ``pd.NaT``:
  1124. >>> pd.NaT.now()
  1125. NaT
  1126. """
  1127. if isinstance(tz, str):
  1128. tz = maybe_get_tz(tz)
  1129. return cls(datetime.now(tz))
  1130. @classmethod
  1131. def today(cls, tz=None):
  1132. """
  1133. Return the current time in the local timezone.
  1134. This differs from datetime.today() in that it can be localized to a
  1135. passed timezone.
  1136. Parameters
  1137. ----------
  1138. tz : str or timezone object, default None
  1139. Timezone to localize to.
  1140. Examples
  1141. --------
  1142. >>> pd.Timestamp.today() # doctest: +SKIP
  1143. Timestamp('2020-11-16 22:37:39.969883')
  1144. Analogous for ``pd.NaT``:
  1145. >>> pd.NaT.today()
  1146. NaT
  1147. """
  1148. return cls.now(tz)
  1149. @classmethod
  1150. def utcnow(cls):
  1151. """
  1152. Timestamp.utcnow()
  1153. Return a new Timestamp representing UTC day and time.
  1154. Examples
  1155. --------
  1156. >>> pd.Timestamp.utcnow() # doctest: +SKIP
  1157. Timestamp('2020-11-16 22:50:18.092888+0000', tz='UTC')
  1158. """
  1159. return cls.now(UTC)
  1160. @classmethod
  1161. def utcfromtimestamp(cls, ts):
  1162. """
  1163. Timestamp.utcfromtimestamp(ts)
  1164. Construct a timezone-aware UTC datetime from a POSIX timestamp.
  1165. Notes
  1166. -----
  1167. Timestamp.utcfromtimestamp behavior differs from datetime.utcfromtimestamp
  1168. in returning a timezone-aware object.
  1169. Examples
  1170. --------
  1171. >>> pd.Timestamp.utcfromtimestamp(1584199972)
  1172. Timestamp('2020-03-14 15:32:52+0000', tz='UTC')
  1173. """
  1174. # GH#22451
  1175. return cls.fromtimestamp(ts, tz="UTC")
  1176. @classmethod
  1177. def fromtimestamp(cls, ts, tz=None):
  1178. """
  1179. Timestamp.fromtimestamp(ts)
  1180. Transform timestamp[, tz] to tz's local time from POSIX timestamp.
  1181. Examples
  1182. --------
  1183. >>> pd.Timestamp.fromtimestamp(1584199972) # doctest: +SKIP
  1184. Timestamp('2020-03-14 15:32:52')
  1185. Note that the output may change depending on your local time.
  1186. """
  1187. tz = maybe_get_tz(tz)
  1188. return cls(datetime.fromtimestamp(ts, tz))
  1189. def strftime(self, format):
  1190. """
  1191. Return a formatted string of the Timestamp.
  1192. Parameters
  1193. ----------
  1194. format : str
  1195. Format string to convert Timestamp to string.
  1196. See strftime documentation for more information on the format string:
  1197. https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior.
  1198. Examples
  1199. --------
  1200. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  1201. >>> ts.strftime('%Y-%m-%d %X')
  1202. '2020-03-14 15:32:52'
  1203. """
  1204. try:
  1205. _dt = datetime(self.year, self.month, self.day,
  1206. self.hour, self.minute, self.second,
  1207. self.microsecond, self.tzinfo, fold=self.fold)
  1208. except ValueError as err:
  1209. raise NotImplementedError(
  1210. "strftime not yet supported on Timestamps which "
  1211. "are outside the range of Python's standard library. "
  1212. "For now, please call the components you need (such as `.year` "
  1213. "and `.month`) and construct your string from there."
  1214. ) from err
  1215. return _dt.strftime(format)
  1216. # Issue 25016.
  1217. @classmethod
  1218. def strptime(cls, date_string, format):
  1219. """
  1220. Timestamp.strptime(string, format)
  1221. Function is not implemented. Use pd.to_datetime().
  1222. """
  1223. raise NotImplementedError(
  1224. "Timestamp.strptime() is not implemented. "
  1225. "Use to_datetime() to parse date strings."
  1226. )
  1227. @classmethod
  1228. def combine(cls, date, time):
  1229. """
  1230. Timestamp.combine(date, time)
  1231. Combine date, time into datetime with same date and time fields.
  1232. Examples
  1233. --------
  1234. >>> from datetime import date, time
  1235. >>> pd.Timestamp.combine(date(2020, 3, 14), time(15, 30, 15))
  1236. Timestamp('2020-03-14 15:30:15')
  1237. """
  1238. return cls(datetime.combine(date, time))
  1239. def __new__(
  1240. cls,
  1241. object ts_input=_no_input,
  1242. year=None,
  1243. month=None,
  1244. day=None,
  1245. hour=None,
  1246. minute=None,
  1247. second=None,
  1248. microsecond=None,
  1249. tzinfo_type tzinfo=None,
  1250. *,
  1251. nanosecond=None,
  1252. tz=None,
  1253. unit=None,
  1254. fold=None,
  1255. ):
  1256. # The parameter list folds together legacy parameter names (the first
  1257. # four) and positional and keyword parameter names from pydatetime.
  1258. #
  1259. # There are three calling forms:
  1260. #
  1261. # - In the legacy form, the first parameter, ts_input, is required
  1262. # and may be datetime-like, str, int, or float. The second
  1263. # parameter, offset, is optional and may be str or DateOffset.
  1264. #
  1265. # - ints in the first, second, and third arguments indicate
  1266. # pydatetime positional arguments. Only the first 8 arguments
  1267. # (standing in for year, month, day, hour, minute, second,
  1268. # microsecond, tzinfo) may be non-None. As a shortcut, we just
  1269. # check that the second argument is an int.
  1270. #
  1271. # - Nones for the first four (legacy) arguments indicate pydatetime
  1272. # keyword arguments. year, month, and day are required. As a
  1273. # shortcut, we just check that the first argument was not passed.
  1274. #
  1275. # Mixing pydatetime positional and keyword arguments is forbidden!
  1276. cdef:
  1277. _TSObject ts
  1278. tzinfo_type tzobj
  1279. _date_attributes = [year, month, day, hour, minute, second,
  1280. microsecond, nanosecond]
  1281. if tzinfo is not None:
  1282. # GH#17690 tzinfo must be a datetime.tzinfo object, ensured
  1283. # by the cython annotation.
  1284. if tz is not None:
  1285. raise ValueError("Can provide at most one of tz, tzinfo")
  1286. # User passed tzinfo instead of tz; avoid silently ignoring
  1287. tz, tzinfo = tzinfo, None
  1288. # Allow fold only for unambiguous input
  1289. if fold is not None:
  1290. if fold not in [0, 1]:
  1291. raise ValueError(
  1292. "Valid values for the fold argument are None, 0, or 1."
  1293. )
  1294. if (ts_input is not _no_input and not (
  1295. PyDateTime_Check(ts_input) and
  1296. getattr(ts_input, "tzinfo", None) is None)):
  1297. raise ValueError(
  1298. "Cannot pass fold with possibly unambiguous input: int, "
  1299. "float, numpy.datetime64, str, or timezone-aware "
  1300. "datetime-like. Pass naive datetime-like or build "
  1301. "Timestamp from components."
  1302. )
  1303. if tz is not None and PyTZInfo_Check(tz) and treat_tz_as_pytz(tz):
  1304. raise ValueError(
  1305. "pytz timezones do not support fold. Please use dateutil "
  1306. "timezones."
  1307. )
  1308. if hasattr(ts_input, "fold"):
  1309. ts_input = ts_input.replace(fold=fold)
  1310. # GH 30543 if pd.Timestamp already passed, return it
  1311. # check that only ts_input is passed
  1312. # checking verbosely, because cython doesn't optimize
  1313. # list comprehensions (as of cython 0.29.x)
  1314. if (isinstance(ts_input, _Timestamp) and
  1315. tz is None and unit is None and year is None and
  1316. month is None and day is None and hour is None and
  1317. minute is None and second is None and
  1318. microsecond is None and nanosecond is None and
  1319. tzinfo is None):
  1320. return ts_input
  1321. elif isinstance(ts_input, str):
  1322. # User passed a date string to parse.
  1323. # Check that the user didn't also pass a date attribute kwarg.
  1324. if any(arg is not None for arg in _date_attributes):
  1325. raise ValueError(
  1326. "Cannot pass a date attribute keyword "
  1327. "argument when passing a date string; 'tz' is keyword-only"
  1328. )
  1329. elif ts_input is _no_input:
  1330. # GH 31200
  1331. # When year, month or day is not given, we call the datetime
  1332. # constructor to make sure we get the same error message
  1333. # since Timestamp inherits datetime
  1334. datetime_kwargs = {
  1335. "hour": hour or 0,
  1336. "minute": minute or 0,
  1337. "second": second or 0,
  1338. "microsecond": microsecond or 0,
  1339. "fold": fold or 0
  1340. }
  1341. if year is not None:
  1342. datetime_kwargs["year"] = year
  1343. if month is not None:
  1344. datetime_kwargs["month"] = month
  1345. if day is not None:
  1346. datetime_kwargs["day"] = day
  1347. ts_input = datetime(**datetime_kwargs)
  1348. elif is_integer_object(year):
  1349. # User passed positional arguments:
  1350. # Timestamp(year, month, day[, hour[, minute[, second[,
  1351. # microsecond[, tzinfo]]]]])
  1352. ts_input = datetime(ts_input, year, month, day or 0,
  1353. hour or 0, minute or 0, second or 0, fold=fold or 0)
  1354. unit = None
  1355. if getattr(ts_input, "tzinfo", None) is not None and tz is not None:
  1356. raise ValueError("Cannot pass a datetime or Timestamp with tzinfo with "
  1357. "the tz parameter. Use tz_convert instead.")
  1358. tzobj = maybe_get_tz(tz)
  1359. if tzobj is not None and is_datetime64_object(ts_input):
  1360. # GH#24559, GH#42288 As of 2.0 we treat datetime64 as
  1361. # wall-time (consistent with DatetimeIndex)
  1362. return cls(ts_input).tz_localize(tzobj)
  1363. if nanosecond is None:
  1364. nanosecond = 0
  1365. elif not (999 >= nanosecond >= 0):
  1366. raise ValueError("nanosecond must be in 0..999")
  1367. ts = convert_to_tsobject(ts_input, tzobj, unit, 0, 0, nanosecond)
  1368. if ts.value == NPY_NAT:
  1369. return NaT
  1370. return create_timestamp_from_ts(ts.value, ts.dts, ts.tzinfo, ts.fold, ts.creso)
  1371. def _round(self, freq, mode, ambiguous="raise", nonexistent="raise"):
  1372. cdef:
  1373. int64_t nanos
  1374. freq = to_offset(freq)
  1375. freq.nanos # raises on non-fixed freq
  1376. nanos = delta_to_nanoseconds(freq, self._creso)
  1377. if nanos == 0:
  1378. if freq.nanos == 0:
  1379. raise ValueError("Division by zero in rounding")
  1380. # e.g. self.unit == "s" and sub-second freq
  1381. return self
  1382. # TODO: problem if nanos==0
  1383. if self.tz is not None:
  1384. value = self.tz_localize(None)._value
  1385. else:
  1386. value = self._value
  1387. value = np.array([value], dtype=np.int64)
  1388. # Will only ever contain 1 element for timestamp
  1389. r = round_nsint64(value, mode, nanos)[0]
  1390. result = Timestamp._from_value_and_reso(r, self._creso, None)
  1391. if self.tz is not None:
  1392. result = result.tz_localize(
  1393. self.tz, ambiguous=ambiguous, nonexistent=nonexistent
  1394. )
  1395. return result
  1396. def round(self, freq, ambiguous="raise", nonexistent="raise"):
  1397. """
  1398. Round the Timestamp to the specified resolution.
  1399. Parameters
  1400. ----------
  1401. freq : str
  1402. Frequency string indicating the rounding resolution.
  1403. ambiguous : bool or {'raise', 'NaT'}, default 'raise'
  1404. The behavior is as follows:
  1405. * bool contains flags to determine if time is dst or not (note
  1406. that this flag is only applicable for ambiguous fall dst dates).
  1407. * 'NaT' will return NaT for an ambiguous time.
  1408. * 'raise' will raise an AmbiguousTimeError for an ambiguous time.
  1409. nonexistent : {'raise', 'shift_forward', 'shift_backward, 'NaT', \
  1410. timedelta}, default 'raise'
  1411. A nonexistent time does not exist in a particular timezone
  1412. where clocks moved forward due to DST.
  1413. * 'shift_forward' will shift the nonexistent time forward to the
  1414. closest existing time.
  1415. * 'shift_backward' will shift the nonexistent time backward to the
  1416. closest existing time.
  1417. * 'NaT' will return NaT where there are nonexistent times.
  1418. * timedelta objects will shift nonexistent times by the timedelta.
  1419. * 'raise' will raise an NonExistentTimeError if there are
  1420. nonexistent times.
  1421. Returns
  1422. -------
  1423. a new Timestamp rounded to the given resolution of `freq`
  1424. Raises
  1425. ------
  1426. ValueError if the freq cannot be converted
  1427. Notes
  1428. -----
  1429. If the Timestamp has a timezone, rounding will take place relative to the
  1430. local ("wall") time and re-localized to the same timezone. When rounding
  1431. near daylight savings time, use ``nonexistent`` and ``ambiguous`` to
  1432. control the re-localization behavior.
  1433. Examples
  1434. --------
  1435. Create a timestamp object:
  1436. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  1437. A timestamp can be rounded using multiple frequency units:
  1438. >>> ts.round(freq='H') # hour
  1439. Timestamp('2020-03-14 16:00:00')
  1440. >>> ts.round(freq='T') # minute
  1441. Timestamp('2020-03-14 15:33:00')
  1442. >>> ts.round(freq='S') # seconds
  1443. Timestamp('2020-03-14 15:32:52')
  1444. >>> ts.round(freq='L') # milliseconds
  1445. Timestamp('2020-03-14 15:32:52.193000')
  1446. ``freq`` can also be a multiple of a single unit, like '5T' (i.e. 5 minutes):
  1447. >>> ts.round(freq='5T')
  1448. Timestamp('2020-03-14 15:35:00')
  1449. or a combination of multiple units, like '1H30T' (i.e. 1 hour and 30 minutes):
  1450. >>> ts.round(freq='1H30T')
  1451. Timestamp('2020-03-14 15:00:00')
  1452. Analogous for ``pd.NaT``:
  1453. >>> pd.NaT.round()
  1454. NaT
  1455. When rounding near a daylight savings time transition, use ``ambiguous`` or
  1456. ``nonexistent`` to control how the timestamp should be re-localized.
  1457. >>> ts_tz = pd.Timestamp("2021-10-31 01:30:00").tz_localize("Europe/Amsterdam")
  1458. >>> ts_tz.round("H", ambiguous=False)
  1459. Timestamp('2021-10-31 02:00:00+0100', tz='Europe/Amsterdam')
  1460. >>> ts_tz.round("H", ambiguous=True)
  1461. Timestamp('2021-10-31 02:00:00+0200', tz='Europe/Amsterdam')
  1462. """
  1463. return self._round(
  1464. freq, RoundTo.NEAREST_HALF_EVEN, ambiguous, nonexistent
  1465. )
  1466. def floor(self, freq, ambiguous="raise", nonexistent="raise"):
  1467. """
  1468. Return a new Timestamp floored to this resolution.
  1469. Parameters
  1470. ----------
  1471. freq : str
  1472. Frequency string indicating the flooring resolution.
  1473. ambiguous : bool or {'raise', 'NaT'}, default 'raise'
  1474. The behavior is as follows:
  1475. * bool contains flags to determine if time is dst or not (note
  1476. that this flag is only applicable for ambiguous fall dst dates).
  1477. * 'NaT' will return NaT for an ambiguous time.
  1478. * 'raise' will raise an AmbiguousTimeError for an ambiguous time.
  1479. nonexistent : {'raise', 'shift_forward', 'shift_backward, 'NaT', \
  1480. timedelta}, default 'raise'
  1481. A nonexistent time does not exist in a particular timezone
  1482. where clocks moved forward due to DST.
  1483. * 'shift_forward' will shift the nonexistent time forward to the
  1484. closest existing time.
  1485. * 'shift_backward' will shift the nonexistent time backward to the
  1486. closest existing time.
  1487. * 'NaT' will return NaT where there are nonexistent times.
  1488. * timedelta objects will shift nonexistent times by the timedelta.
  1489. * 'raise' will raise an NonExistentTimeError if there are
  1490. nonexistent times.
  1491. Raises
  1492. ------
  1493. ValueError if the freq cannot be converted.
  1494. Notes
  1495. -----
  1496. If the Timestamp has a timezone, flooring will take place relative to the
  1497. local ("wall") time and re-localized to the same timezone. When flooring
  1498. near daylight savings time, use ``nonexistent`` and ``ambiguous`` to
  1499. control the re-localization behavior.
  1500. Examples
  1501. --------
  1502. Create a timestamp object:
  1503. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  1504. A timestamp can be floored using multiple frequency units:
  1505. >>> ts.floor(freq='H') # hour
  1506. Timestamp('2020-03-14 15:00:00')
  1507. >>> ts.floor(freq='T') # minute
  1508. Timestamp('2020-03-14 15:32:00')
  1509. >>> ts.floor(freq='S') # seconds
  1510. Timestamp('2020-03-14 15:32:52')
  1511. >>> ts.floor(freq='N') # nanoseconds
  1512. Timestamp('2020-03-14 15:32:52.192548651')
  1513. ``freq`` can also be a multiple of a single unit, like '5T' (i.e. 5 minutes):
  1514. >>> ts.floor(freq='5T')
  1515. Timestamp('2020-03-14 15:30:00')
  1516. or a combination of multiple units, like '1H30T' (i.e. 1 hour and 30 minutes):
  1517. >>> ts.floor(freq='1H30T')
  1518. Timestamp('2020-03-14 15:00:00')
  1519. Analogous for ``pd.NaT``:
  1520. >>> pd.NaT.floor()
  1521. NaT
  1522. When rounding near a daylight savings time transition, use ``ambiguous`` or
  1523. ``nonexistent`` to control how the timestamp should be re-localized.
  1524. >>> ts_tz = pd.Timestamp("2021-10-31 03:30:00").tz_localize("Europe/Amsterdam")
  1525. >>> ts_tz.floor("2H", ambiguous=False)
  1526. Timestamp('2021-10-31 02:00:00+0100', tz='Europe/Amsterdam')
  1527. >>> ts_tz.floor("2H", ambiguous=True)
  1528. Timestamp('2021-10-31 02:00:00+0200', tz='Europe/Amsterdam')
  1529. """
  1530. return self._round(freq, RoundTo.MINUS_INFTY, ambiguous, nonexistent)
  1531. def ceil(self, freq, ambiguous="raise", nonexistent="raise"):
  1532. """
  1533. Return a new Timestamp ceiled to this resolution.
  1534. Parameters
  1535. ----------
  1536. freq : str
  1537. Frequency string indicating the ceiling resolution.
  1538. ambiguous : bool or {'raise', 'NaT'}, default 'raise'
  1539. The behavior is as follows:
  1540. * bool contains flags to determine if time is dst or not (note
  1541. that this flag is only applicable for ambiguous fall dst dates).
  1542. * 'NaT' will return NaT for an ambiguous time.
  1543. * 'raise' will raise an AmbiguousTimeError for an ambiguous time.
  1544. nonexistent : {'raise', 'shift_forward', 'shift_backward, 'NaT', \
  1545. timedelta}, default 'raise'
  1546. A nonexistent time does not exist in a particular timezone
  1547. where clocks moved forward due to DST.
  1548. * 'shift_forward' will shift the nonexistent time forward to the
  1549. closest existing time.
  1550. * 'shift_backward' will shift the nonexistent time backward to the
  1551. closest existing time.
  1552. * 'NaT' will return NaT where there are nonexistent times.
  1553. * timedelta objects will shift nonexistent times by the timedelta.
  1554. * 'raise' will raise an NonExistentTimeError if there are
  1555. nonexistent times.
  1556. Raises
  1557. ------
  1558. ValueError if the freq cannot be converted.
  1559. Notes
  1560. -----
  1561. If the Timestamp has a timezone, ceiling will take place relative to the
  1562. local ("wall") time and re-localized to the same timezone. When ceiling
  1563. near daylight savings time, use ``nonexistent`` and ``ambiguous`` to
  1564. control the re-localization behavior.
  1565. Examples
  1566. --------
  1567. Create a timestamp object:
  1568. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  1569. A timestamp can be ceiled using multiple frequency units:
  1570. >>> ts.ceil(freq='H') # hour
  1571. Timestamp('2020-03-14 16:00:00')
  1572. >>> ts.ceil(freq='T') # minute
  1573. Timestamp('2020-03-14 15:33:00')
  1574. >>> ts.ceil(freq='S') # seconds
  1575. Timestamp('2020-03-14 15:32:53')
  1576. >>> ts.ceil(freq='U') # microseconds
  1577. Timestamp('2020-03-14 15:32:52.192549')
  1578. ``freq`` can also be a multiple of a single unit, like '5T' (i.e. 5 minutes):
  1579. >>> ts.ceil(freq='5T')
  1580. Timestamp('2020-03-14 15:35:00')
  1581. or a combination of multiple units, like '1H30T' (i.e. 1 hour and 30 minutes):
  1582. >>> ts.ceil(freq='1H30T')
  1583. Timestamp('2020-03-14 16:30:00')
  1584. Analogous for ``pd.NaT``:
  1585. >>> pd.NaT.ceil()
  1586. NaT
  1587. When rounding near a daylight savings time transition, use ``ambiguous`` or
  1588. ``nonexistent`` to control how the timestamp should be re-localized.
  1589. >>> ts_tz = pd.Timestamp("2021-10-31 01:30:00").tz_localize("Europe/Amsterdam")
  1590. >>> ts_tz.ceil("H", ambiguous=False)
  1591. Timestamp('2021-10-31 02:00:00+0100', tz='Europe/Amsterdam')
  1592. >>> ts_tz.ceil("H", ambiguous=True)
  1593. Timestamp('2021-10-31 02:00:00+0200', tz='Europe/Amsterdam')
  1594. """
  1595. return self._round(freq, RoundTo.PLUS_INFTY, ambiguous, nonexistent)
  1596. @property
  1597. def tz(self):
  1598. """
  1599. Alias for tzinfo.
  1600. Examples
  1601. --------
  1602. >>> ts = pd.Timestamp(1584226800, unit='s', tz='Europe/Stockholm')
  1603. >>> ts.tz
  1604. <DstTzInfo 'Europe/Stockholm' CET+1:00:00 STD>
  1605. """
  1606. return self.tzinfo
  1607. @tz.setter
  1608. def tz(self, value):
  1609. # GH 3746: Prevent localizing or converting the index by setting tz
  1610. raise AttributeError(
  1611. "Cannot directly set timezone. "
  1612. "Use tz_localize() or tz_convert() as appropriate"
  1613. )
  1614. def tz_localize(self, tz, ambiguous="raise", nonexistent="raise"):
  1615. """
  1616. Localize the Timestamp to a timezone.
  1617. Convert naive Timestamp to local time zone or remove
  1618. timezone from timezone-aware Timestamp.
  1619. Parameters
  1620. ----------
  1621. tz : str, pytz.timezone, dateutil.tz.tzfile or None
  1622. Time zone for time which Timestamp will be converted to.
  1623. None will remove timezone holding local time.
  1624. ambiguous : bool, 'NaT', default 'raise'
  1625. When clocks moved backward due to DST, ambiguous times may arise.
  1626. For example in Central European Time (UTC+01), when going from
  1627. 03:00 DST to 02:00 non-DST, 02:30:00 local time occurs both at
  1628. 00:30:00 UTC and at 01:30:00 UTC. In such a situation, the
  1629. `ambiguous` parameter dictates how ambiguous times should be
  1630. handled.
  1631. The behavior is as follows:
  1632. * bool contains flags to determine if time is dst or not (note
  1633. that this flag is only applicable for ambiguous fall dst dates).
  1634. * 'NaT' will return NaT for an ambiguous time.
  1635. * 'raise' will raise an AmbiguousTimeError for an ambiguous time.
  1636. nonexistent : 'shift_forward', 'shift_backward, 'NaT', timedelta, \
  1637. default 'raise'
  1638. A nonexistent time does not exist in a particular timezone
  1639. where clocks moved forward due to DST.
  1640. The behavior is as follows:
  1641. * 'shift_forward' will shift the nonexistent time forward to the
  1642. closest existing time.
  1643. * 'shift_backward' will shift the nonexistent time backward to the
  1644. closest existing time.
  1645. * 'NaT' will return NaT where there are nonexistent times.
  1646. * timedelta objects will shift nonexistent times by the timedelta.
  1647. * 'raise' will raise an NonExistentTimeError if there are
  1648. nonexistent times.
  1649. Returns
  1650. -------
  1651. localized : Timestamp
  1652. Raises
  1653. ------
  1654. TypeError
  1655. If the Timestamp is tz-aware and tz is not None.
  1656. Examples
  1657. --------
  1658. Create a naive timestamp object:
  1659. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651')
  1660. >>> ts
  1661. Timestamp('2020-03-14 15:32:52.192548651')
  1662. Add 'Europe/Stockholm' as timezone:
  1663. >>> ts.tz_localize(tz='Europe/Stockholm')
  1664. Timestamp('2020-03-14 15:32:52.192548651+0100', tz='Europe/Stockholm')
  1665. Analogous for ``pd.NaT``:
  1666. >>> pd.NaT.tz_localize()
  1667. NaT
  1668. """
  1669. if not isinstance(ambiguous, bool) and ambiguous not in {"NaT", "raise"}:
  1670. raise ValueError(
  1671. "'ambiguous' parameter must be one of: "
  1672. "True, False, 'NaT', 'raise' (default)"
  1673. )
  1674. nonexistent_options = ("raise", "NaT", "shift_forward", "shift_backward")
  1675. if nonexistent not in nonexistent_options and not PyDelta_Check(nonexistent):
  1676. raise ValueError(
  1677. "The nonexistent argument must be one of 'raise', "
  1678. "'NaT', 'shift_forward', 'shift_backward' or a timedelta object"
  1679. )
  1680. if self.tzinfo is None:
  1681. # tz naive, localize
  1682. tz = maybe_get_tz(tz)
  1683. if not isinstance(ambiguous, str):
  1684. ambiguous = [ambiguous]
  1685. value = tz_localize_to_utc_single(self._value, tz,
  1686. ambiguous=ambiguous,
  1687. nonexistent=nonexistent,
  1688. creso=self._creso)
  1689. elif tz is None:
  1690. # reset tz
  1691. value = tz_convert_from_utc_single(self._value, self.tz, creso=self._creso)
  1692. else:
  1693. raise TypeError(
  1694. "Cannot localize tz-aware Timestamp, use tz_convert for conversions"
  1695. )
  1696. out = type(self)._from_value_and_reso(value, self._creso, tz=tz)
  1697. return out
  1698. def tz_convert(self, tz):
  1699. """
  1700. Convert timezone-aware Timestamp to another time zone.
  1701. Parameters
  1702. ----------
  1703. tz : str, pytz.timezone, dateutil.tz.tzfile or None
  1704. Time zone for time which Timestamp will be converted to.
  1705. None will remove timezone holding UTC time.
  1706. Returns
  1707. -------
  1708. converted : Timestamp
  1709. Raises
  1710. ------
  1711. TypeError
  1712. If Timestamp is tz-naive.
  1713. Examples
  1714. --------
  1715. Create a timestamp object with UTC timezone:
  1716. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651', tz='UTC')
  1717. >>> ts
  1718. Timestamp('2020-03-14 15:32:52.192548651+0000', tz='UTC')
  1719. Change to Tokyo timezone:
  1720. >>> ts.tz_convert(tz='Asia/Tokyo')
  1721. Timestamp('2020-03-15 00:32:52.192548651+0900', tz='Asia/Tokyo')
  1722. Can also use ``astimezone``:
  1723. >>> ts.astimezone(tz='Asia/Tokyo')
  1724. Timestamp('2020-03-15 00:32:52.192548651+0900', tz='Asia/Tokyo')
  1725. Analogous for ``pd.NaT``:
  1726. >>> pd.NaT.tz_convert(tz='Asia/Tokyo')
  1727. NaT
  1728. """
  1729. if self.tzinfo is None:
  1730. # tz naive, use tz_localize
  1731. raise TypeError(
  1732. "Cannot convert tz-naive Timestamp, use tz_localize to localize"
  1733. )
  1734. else:
  1735. # Same UTC timestamp, different time zone
  1736. tz = maybe_get_tz(tz)
  1737. out = type(self)._from_value_and_reso(self._value, reso=self._creso, tz=tz)
  1738. return out
  1739. astimezone = tz_convert
  1740. def replace(
  1741. self,
  1742. year=None,
  1743. month=None,
  1744. day=None,
  1745. hour=None,
  1746. minute=None,
  1747. second=None,
  1748. microsecond=None,
  1749. nanosecond=None,
  1750. tzinfo=object,
  1751. fold=None,
  1752. ):
  1753. """
  1754. Implements datetime.replace, handles nanoseconds.
  1755. Parameters
  1756. ----------
  1757. year : int, optional
  1758. month : int, optional
  1759. day : int, optional
  1760. hour : int, optional
  1761. minute : int, optional
  1762. second : int, optional
  1763. microsecond : int, optional
  1764. nanosecond : int, optional
  1765. tzinfo : tz-convertible, optional
  1766. fold : int, optional
  1767. Returns
  1768. -------
  1769. Timestamp with fields replaced
  1770. Examples
  1771. --------
  1772. Create a timestamp object:
  1773. >>> ts = pd.Timestamp('2020-03-14T15:32:52.192548651', tz='UTC')
  1774. >>> ts
  1775. Timestamp('2020-03-14 15:32:52.192548651+0000', tz='UTC')
  1776. Replace year and the hour:
  1777. >>> ts.replace(year=1999, hour=10)
  1778. Timestamp('1999-03-14 10:32:52.192548651+0000', tz='UTC')
  1779. Replace timezone (not a conversion):
  1780. >>> import pytz
  1781. >>> ts.replace(tzinfo=pytz.timezone('US/Pacific'))
  1782. Timestamp('2020-03-14 15:32:52.192548651-0700', tz='US/Pacific')
  1783. Analogous for ``pd.NaT``:
  1784. >>> pd.NaT.replace(tzinfo=pytz.timezone('US/Pacific'))
  1785. NaT
  1786. """
  1787. cdef:
  1788. npy_datetimestruct dts
  1789. int64_t value
  1790. object k, v
  1791. datetime ts_input
  1792. tzinfo_type tzobj
  1793. _TSObject ts
  1794. # set to naive if needed
  1795. tzobj = self.tzinfo
  1796. value = self._value
  1797. # GH 37610. Preserve fold when replacing.
  1798. if fold is None:
  1799. fold = self.fold
  1800. if tzobj is not None:
  1801. value = tz_convert_from_utc_single(value, tzobj, creso=self._creso)
  1802. # setup components
  1803. pandas_datetime_to_datetimestruct(value, self._creso, &dts)
  1804. dts.ps = self.nanosecond * 1000
  1805. # replace
  1806. def validate(k, v):
  1807. """ validate integers """
  1808. if not is_integer_object(v):
  1809. raise ValueError(
  1810. f"value must be an integer, received {type(v)} for {k}"
  1811. )
  1812. return v
  1813. if year is not None:
  1814. dts.year = validate("year", year)
  1815. if month is not None:
  1816. dts.month = validate("month", month)
  1817. if day is not None:
  1818. dts.day = validate("day", day)
  1819. if hour is not None:
  1820. dts.hour = validate("hour", hour)
  1821. if minute is not None:
  1822. dts.min = validate("minute", minute)
  1823. if second is not None:
  1824. dts.sec = validate("second", second)
  1825. if microsecond is not None:
  1826. dts.us = validate("microsecond", microsecond)
  1827. if nanosecond is not None:
  1828. dts.ps = validate("nanosecond", nanosecond) * 1000
  1829. if tzinfo is not object:
  1830. tzobj = tzinfo
  1831. # reconstruct & check bounds
  1832. if tzobj is None:
  1833. # We can avoid going through pydatetime paths, which is robust
  1834. # to datetimes outside of pydatetime range.
  1835. ts = _TSObject()
  1836. check_dts_bounds(&dts, self._creso)
  1837. ts.value = npy_datetimestruct_to_datetime(self._creso, &dts)
  1838. ts.dts = dts
  1839. ts.creso = self._creso
  1840. ts.fold = fold
  1841. return create_timestamp_from_ts(
  1842. ts.value, dts, tzobj, fold, reso=self._creso
  1843. )
  1844. elif tzobj is not None and treat_tz_as_pytz(tzobj):
  1845. # replacing across a DST boundary may induce a new tzinfo object
  1846. # see GH#18319
  1847. ts_input = tzobj.localize(datetime(dts.year, dts.month, dts.day,
  1848. dts.hour, dts.min, dts.sec,
  1849. dts.us),
  1850. is_dst=not bool(fold))
  1851. tzobj = ts_input.tzinfo
  1852. else:
  1853. kwargs = {"year": dts.year, "month": dts.month, "day": dts.day,
  1854. "hour": dts.hour, "minute": dts.min, "second": dts.sec,
  1855. "microsecond": dts.us, "tzinfo": tzobj,
  1856. "fold": fold}
  1857. ts_input = datetime(**kwargs)
  1858. ts = convert_datetime_to_tsobject(
  1859. ts_input, tzobj, nanos=dts.ps // 1000, reso=self._creso
  1860. )
  1861. return create_timestamp_from_ts(
  1862. ts.value, dts, tzobj, fold, reso=self._creso
  1863. )
  1864. def to_julian_date(self) -> np.float64:
  1865. """
  1866. Convert TimeStamp to a Julian Date.
  1867. 0 Julian date is noon January 1, 4713 BC.
  1868. Examples
  1869. --------
  1870. >>> ts = pd.Timestamp('2020-03-14T15:32:52')
  1871. >>> ts.to_julian_date()
  1872. 2458923.147824074
  1873. """
  1874. year = self.year
  1875. month = self.month
  1876. day = self.day
  1877. if month <= 2:
  1878. year -= 1
  1879. month += 12
  1880. return (day +
  1881. np.fix((153 * month - 457) / 5) +
  1882. 365 * year +
  1883. np.floor(year / 4) -
  1884. np.floor(year / 100) +
  1885. np.floor(year / 400) +
  1886. 1721118.5 +
  1887. (self.hour +
  1888. self.minute / 60.0 +
  1889. self.second / 3600.0 +
  1890. self.microsecond / 3600.0 / 1e+6 +
  1891. self.nanosecond / 3600.0 / 1e+9
  1892. ) / 24.0)
  1893. def isoweekday(self):
  1894. """
  1895. Return the day of the week represented by the date.
  1896. Monday == 1 ... Sunday == 7.
  1897. """
  1898. # same as super().isoweekday(), but that breaks because of how
  1899. # we have overriden year, see note in create_timestamp_from_ts
  1900. return self.weekday() + 1
  1901. def weekday(self):
  1902. """
  1903. Return the day of the week represented by the date.
  1904. Monday == 0 ... Sunday == 6.
  1905. """
  1906. # same as super().weekday(), but that breaks because of how
  1907. # we have overriden year, see note in create_timestamp_from_ts
  1908. return ccalendar.dayofweek(self.year, self.month, self.day)
  1909. # Aliases
  1910. Timestamp.weekofyear = Timestamp.week
  1911. Timestamp.daysinmonth = Timestamp.days_in_month
  1912. # ----------------------------------------------------------------------
  1913. # Scalar analogues to functions in vectorized.pyx
  1914. @cython.cdivision(False)
  1915. cdef int64_t normalize_i8_stamp(int64_t local_val, int64_t ppd) nogil:
  1916. """
  1917. Round the localized nanosecond timestamp down to the previous midnight.
  1918. Parameters
  1919. ----------
  1920. local_val : int64_t
  1921. ppd : int64_t
  1922. Periods per day in the Timestamp's resolution.
  1923. Returns
  1924. -------
  1925. int64_t
  1926. """
  1927. return local_val - (local_val % ppd)