__init__.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. from __future__ import annotations
  2. import datetime as _datetime
  3. from typing import Union
  4. from typing import cast
  5. from typing import overload
  6. from pendulum.__version__ import __version__
  7. from pendulum.constants import DAYS_PER_WEEK
  8. from pendulum.constants import HOURS_PER_DAY
  9. from pendulum.constants import MINUTES_PER_HOUR
  10. from pendulum.constants import MONTHS_PER_YEAR
  11. from pendulum.constants import SECONDS_PER_DAY
  12. from pendulum.constants import SECONDS_PER_HOUR
  13. from pendulum.constants import SECONDS_PER_MINUTE
  14. from pendulum.constants import WEEKS_PER_YEAR
  15. from pendulum.constants import YEARS_PER_CENTURY
  16. from pendulum.constants import YEARS_PER_DECADE
  17. from pendulum.date import Date
  18. from pendulum.datetime import DateTime
  19. from pendulum.day import WeekDay
  20. from pendulum.duration import Duration
  21. from pendulum.formatting import Formatter
  22. from pendulum.helpers import format_diff
  23. from pendulum.helpers import get_locale
  24. from pendulum.helpers import locale
  25. from pendulum.helpers import set_locale
  26. from pendulum.helpers import week_ends_at
  27. from pendulum.helpers import week_starts_at
  28. from pendulum.interval import Interval
  29. from pendulum.parser import parse
  30. from pendulum.testing.traveller import Traveller
  31. from pendulum.time import Time
  32. from pendulum.tz import UTC
  33. from pendulum.tz import fixed_timezone
  34. from pendulum.tz import local_timezone
  35. from pendulum.tz import set_local_timezone
  36. from pendulum.tz import test_local_timezone
  37. from pendulum.tz import timezones
  38. from pendulum.tz.timezone import FixedTimezone
  39. from pendulum.tz.timezone import Timezone
  40. MONDAY = WeekDay.MONDAY
  41. TUESDAY = WeekDay.TUESDAY
  42. WEDNESDAY = WeekDay.WEDNESDAY
  43. THURSDAY = WeekDay.THURSDAY
  44. FRIDAY = WeekDay.FRIDAY
  45. SATURDAY = WeekDay.SATURDAY
  46. SUNDAY = WeekDay.SUNDAY
  47. _TEST_NOW: DateTime | None = None
  48. _LOCALE = "en"
  49. _WEEK_STARTS_AT: WeekDay = WeekDay.MONDAY
  50. _WEEK_ENDS_AT: WeekDay = WeekDay.SUNDAY
  51. _formatter = Formatter()
  52. @overload
  53. def timezone(name: int) -> FixedTimezone:
  54. ...
  55. @overload
  56. def timezone(name: str) -> Timezone:
  57. ...
  58. @overload
  59. def timezone(name: str | int) -> Timezone | FixedTimezone:
  60. ...
  61. def timezone(name: str | int) -> Timezone | FixedTimezone:
  62. """
  63. Return a Timezone instance given its name.
  64. """
  65. if isinstance(name, int):
  66. return fixed_timezone(name)
  67. if name.lower() == "utc":
  68. return UTC
  69. return Timezone(name)
  70. def _safe_timezone(
  71. obj: str | float | _datetime.tzinfo | Timezone | FixedTimezone | None,
  72. dt: _datetime.datetime | None = None,
  73. ) -> Timezone | FixedTimezone:
  74. """
  75. Creates a timezone instance
  76. from a string, Timezone, TimezoneInfo or integer offset.
  77. """
  78. if isinstance(obj, (Timezone, FixedTimezone)):
  79. return obj
  80. if obj is None or obj == "local":
  81. return local_timezone()
  82. if isinstance(obj, (int, float)):
  83. obj = int(obj * 60 * 60)
  84. elif isinstance(obj, _datetime.tzinfo):
  85. # zoneinfo
  86. if hasattr(obj, "key"):
  87. obj = obj.key
  88. # pytz
  89. elif hasattr(obj, "localize"):
  90. obj = obj.zone # type: ignore[attr-defined]
  91. elif obj.tzname(None) == "UTC":
  92. return UTC
  93. else:
  94. offset = obj.utcoffset(dt)
  95. if offset is None:
  96. offset = _datetime.timedelta(0)
  97. obj = int(offset.total_seconds())
  98. obj = cast(Union[str, int], obj)
  99. return timezone(obj)
  100. # Public API
  101. def datetime(
  102. year: int,
  103. month: int,
  104. day: int,
  105. hour: int = 0,
  106. minute: int = 0,
  107. second: int = 0,
  108. microsecond: int = 0,
  109. tz: str | float | Timezone | FixedTimezone | _datetime.tzinfo | None = UTC,
  110. fold: int = 1,
  111. raise_on_unknown_times: bool = False,
  112. ) -> DateTime:
  113. """
  114. Creates a new DateTime instance from a specific date and time.
  115. """
  116. return DateTime.create(
  117. year,
  118. month,
  119. day,
  120. hour=hour,
  121. minute=minute,
  122. second=second,
  123. microsecond=microsecond,
  124. tz=tz,
  125. fold=fold,
  126. raise_on_unknown_times=raise_on_unknown_times,
  127. )
  128. def local(
  129. year: int,
  130. month: int,
  131. day: int,
  132. hour: int = 0,
  133. minute: int = 0,
  134. second: int = 0,
  135. microsecond: int = 0,
  136. ) -> DateTime:
  137. """
  138. Return a DateTime in the local timezone.
  139. """
  140. return datetime(
  141. year, month, day, hour, minute, second, microsecond, tz=local_timezone()
  142. )
  143. def naive(
  144. year: int,
  145. month: int,
  146. day: int,
  147. hour: int = 0,
  148. minute: int = 0,
  149. second: int = 0,
  150. microsecond: int = 0,
  151. fold: int = 1,
  152. ) -> DateTime:
  153. """
  154. Return a naive DateTime.
  155. """
  156. return DateTime(year, month, day, hour, minute, second, microsecond, fold=fold)
  157. def date(year: int, month: int, day: int) -> Date:
  158. """
  159. Create a new Date instance.
  160. """
  161. return Date(year, month, day)
  162. def time(hour: int, minute: int = 0, second: int = 0, microsecond: int = 0) -> Time:
  163. """
  164. Create a new Time instance.
  165. """
  166. return Time(hour, minute, second, microsecond)
  167. @overload
  168. def instance(
  169. obj: _datetime.datetime,
  170. tz: str | Timezone | FixedTimezone | _datetime.tzinfo | None = UTC,
  171. ) -> DateTime:
  172. ...
  173. @overload
  174. def instance(
  175. obj: _datetime.date,
  176. tz: str | Timezone | FixedTimezone | _datetime.tzinfo | None = UTC,
  177. ) -> Date:
  178. ...
  179. @overload
  180. def instance(
  181. obj: _datetime.time,
  182. tz: str | Timezone | FixedTimezone | _datetime.tzinfo | None = UTC,
  183. ) -> Time:
  184. ...
  185. def instance(
  186. obj: _datetime.datetime | _datetime.date | _datetime.time,
  187. tz: str | Timezone | FixedTimezone | _datetime.tzinfo | None = UTC,
  188. ) -> DateTime | Date | Time:
  189. """
  190. Create a DateTime/Date/Time instance from a datetime/date/time native one.
  191. """
  192. if isinstance(obj, (DateTime, Date, Time)):
  193. return obj
  194. if isinstance(obj, _datetime.date) and not isinstance(obj, _datetime.datetime):
  195. return date(obj.year, obj.month, obj.day)
  196. if isinstance(obj, _datetime.time):
  197. return Time.instance(obj, tz=tz)
  198. return DateTime.instance(obj, tz=tz)
  199. def now(tz: str | Timezone | None = None) -> DateTime:
  200. """
  201. Get a DateTime instance for the current date and time.
  202. """
  203. return DateTime.now(tz)
  204. def today(tz: str | Timezone = "local") -> DateTime:
  205. """
  206. Create a DateTime instance for today.
  207. """
  208. return now(tz).start_of("day")
  209. def tomorrow(tz: str | Timezone = "local") -> DateTime:
  210. """
  211. Create a DateTime instance for tomorrow.
  212. """
  213. return today(tz).add(days=1)
  214. def yesterday(tz: str | Timezone = "local") -> DateTime:
  215. """
  216. Create a DateTime instance for yesterday.
  217. """
  218. return today(tz).subtract(days=1)
  219. def from_format(
  220. string: str,
  221. fmt: str,
  222. tz: str | Timezone = UTC,
  223. locale: str | None = None,
  224. ) -> DateTime:
  225. """
  226. Creates a DateTime instance from a specific format.
  227. """
  228. parts = _formatter.parse(string, fmt, now(tz=tz), locale=locale)
  229. if parts["tz"] is None:
  230. parts["tz"] = tz
  231. return datetime(**parts)
  232. def from_timestamp(timestamp: int | float, tz: str | Timezone = UTC) -> DateTime:
  233. """
  234. Create a DateTime instance from a timestamp.
  235. """
  236. dt = _datetime.datetime.utcfromtimestamp(timestamp)
  237. dt = datetime(
  238. dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond
  239. )
  240. if tz is not UTC or tz != "UTC":
  241. dt = dt.in_timezone(tz)
  242. return dt
  243. def duration(
  244. days: float = 0,
  245. seconds: float = 0,
  246. microseconds: float = 0,
  247. milliseconds: float = 0,
  248. minutes: float = 0,
  249. hours: float = 0,
  250. weeks: float = 0,
  251. years: float = 0,
  252. months: float = 0,
  253. ) -> Duration:
  254. """
  255. Create a Duration instance.
  256. """
  257. return Duration(
  258. days=days,
  259. seconds=seconds,
  260. microseconds=microseconds,
  261. milliseconds=milliseconds,
  262. minutes=minutes,
  263. hours=hours,
  264. weeks=weeks,
  265. years=years,
  266. months=months,
  267. )
  268. def interval(start: DateTime, end: DateTime, absolute: bool = False) -> Interval:
  269. """
  270. Create an Interval instance.
  271. """
  272. return Interval(start, end, absolute=absolute)
  273. # Testing
  274. _traveller = Traveller(DateTime)
  275. freeze = _traveller.freeze
  276. travel = _traveller.travel
  277. travel_to = _traveller.travel_to
  278. travel_back = _traveller.travel_back
  279. __all__ = [
  280. "__version__",
  281. "DAYS_PER_WEEK",
  282. "HOURS_PER_DAY",
  283. "MINUTES_PER_HOUR",
  284. "MONTHS_PER_YEAR",
  285. "SECONDS_PER_DAY",
  286. "SECONDS_PER_HOUR",
  287. "SECONDS_PER_MINUTE",
  288. "WEEKS_PER_YEAR",
  289. "YEARS_PER_CENTURY",
  290. "YEARS_PER_DECADE",
  291. "Date",
  292. "DateTime",
  293. "Duration",
  294. "Formatter",
  295. "WeekDay",
  296. "date",
  297. "datetime",
  298. "duration",
  299. "format_diff",
  300. "freeze",
  301. "from_format",
  302. "from_timestamp",
  303. "get_locale",
  304. "instance",
  305. "interval",
  306. "local",
  307. "locale",
  308. "naive",
  309. "now",
  310. "set_locale",
  311. "week_ends_at",
  312. "week_starts_at",
  313. "parse",
  314. "Interval",
  315. "Time",
  316. "UTC",
  317. "local_timezone",
  318. "set_local_timezone",
  319. "test_local_timezone",
  320. "time",
  321. "timezone",
  322. "timezones",
  323. "today",
  324. "tomorrow",
  325. "travel",
  326. "travel_back",
  327. "travel_to",
  328. "FixedTimezone",
  329. "Timezone",
  330. "yesterday",
  331. ]