Source code for

"""Provider of data related to date and time."""

import typing as t
from calendar import monthrange, timegm
from datetime import date, datetime, time, timedelta

from mimesis.compat import pytz
from mimesis.enums import TimezoneRegion
from mimesis.providers.base import BaseDataProvider
from mimesis.types import Date, DateTime, Time

__all__ = ["Datetime"]

[docs]class Datetime(BaseDataProvider): """Class for generating data related to the date and time.""" # See: _CURRENT_YEAR =
[docs] def __init__(self, *args: t.Any, **kwargs: t.Any) -> None: """Initialize attributes.""" super().__init__(*args, **kwargs) self._datafile = "datetime.json" self._load_datafile(self._datafile)
[docs] class Meta: """Class for metadata.""" name: t.Final[str] = "datetime"
[docs] @staticmethod def bulk_create_datetimes( date_start: DateTime, date_end: DateTime, **kwargs: t.Any, ) -> t.List[DateTime]: """Bulk create datetime objects. This method creates list of datetime objects from ``date_start`` to ``date_end``. You can use the following keyword arguments: * ``days`` * ``hours`` * ``minutes`` * ``seconds`` * ``microseconds`` .. warning:: Empty ``**kwargs`` produces **timedelta(0)** which obviously cannot be used as step, so you have to pass valid ``**kwargs`` for :py:class:`datetime.timedelta` which will be used as a step by which ``date_start`` will be incremented until it reaches ``date_end`` to avoid infinite loop which eventually leads to ``OverflowError``. See :py:class:`datetime.timedelta` for more details. :param date_start: Begin of the range. :param date_end: End of the range. :param kwargs: Keyword arguments for :py:class:`datetime.timedelta` :return: List of datetime objects :raises: ValueError: When ``date_start``/``date_end`` not passed, when ``date_start`` larger than ``date_end`` or when the given keywords for `datetime.timedelta` represent a non-positive timedelta. """ dt_objects = [] if not date_start and not date_end: raise ValueError("You must pass date_start and date_end") if date_end < date_start: raise ValueError("date_start can not be larger than date_end") if timedelta(**kwargs) <= timedelta(): raise ValueError("timedelta must be positive") while date_start <= date_end: date_start += timedelta(**kwargs) dt_objects.append(date_start) return dt_objects
[docs] def week_date(self, start: int = 2017, end: int = _CURRENT_YEAR) -> str: """Get week number with year. :param start: From start. :param end: To end. :return: Week number. """ year = self.year(start, end) week = self.random.randint(1, 52) return f"{year}-W{week}"
[docs] def day_of_week(self, abbr: bool = False) -> str: """Get a random day of week. :param abbr: Abbreviated day name. :return: Day of the week. """ key = "abbr" if abbr else "name" days: t.List[str] = self.extract(["day", key]) return self.random.choice(days)
[docs] def month(self, abbr: bool = False) -> str: """Get a random month. :param abbr: Abbreviated month name. :return: Month name. """ key = "abbr" if abbr else "name" months: t.List[str] = self.extract(["month", key]) return self.random.choice(months)
[docs] def year(self, minimum: int = 1990, maximum: int = _CURRENT_YEAR) -> int: """Generate a random year. :param minimum: Minimum value. :param maximum: Maximum value. :return: Year. """ return self.random.randint(minimum, maximum)
[docs] def century(self) -> str: """Get a random century. :return: Century. """ return self.random.choice(ROMAN_NUMS)
[docs] def periodicity(self) -> str: """Get a random periodicity string. :return: Periodicity. """ periodicity: t.List[str] = self.extract(["periodicity"]) return self.random.choice(periodicity)
[docs] def date(self, start: int = 2000, end: int = _CURRENT_YEAR) -> Date: """Generate random date object. :param start: Minimum value of year. :param end: Maximum value of year. :return: Formatted date. """ year = self.random.randint(start, end) month = self.random.randint(1, 12) day = self.random.randint(1, monthrange(year, month)[1]) date_object = date(year, month, day) return date_object
[docs] def formatted_date(self, fmt: str = "", **kwargs: t.Any) -> str: """Generate random date as string. :param fmt: The format of date, if None then use standard accepted in the current locale. :param kwargs: Keyword arguments for :meth:`` :return: Formatted date. """ date_obj =**kwargs) if not fmt: fmt = self.extract(["formats", "date"]) return date_obj.strftime(fmt)
[docs] def time(self) -> Time: """Generate a random time object. :return: ``datetime.time`` object. """ random_time = time( self.random.randint(0, 23), self.random.randint(0, 59), self.random.randint(0, 59), self.random.randint(0, 999999), ) return random_time
[docs] def formatted_time(self, fmt: str = "") -> str: """Generate string formatted time. :param fmt: The format of time, if None then use standard accepted in the current locale. :return: String formatted time. """ time_obj = self.time() if not fmt: fmt = self.extract(["formats", "time"]) return time_obj.strftime(fmt)
[docs] def day_of_month(self) -> int: """Generate a random day of month, from 1 to 31. :return: Random value from 1 to 31. """ return self.random.randint(1, 31)
[docs] def timezone(self, region: t.Optional[TimezoneRegion] = None) -> str: """Get a random timezone. :param region: Timezone region. :return: Timezone. """ region_name = self.validate_enum(region, TimezoneRegion) return self.random.choice( [tz for tz in TIMEZONES if tz.startswith(region_name)] )
[docs] def gmt_offset(self) -> str: """Get a random GMT offset value. :return: GMT Offset. """ return self.random.choice(GMT_OFFSETS)
[docs] def datetime( self, start: int = 2000, end: int = _CURRENT_YEAR, timezone: t.Optional[str] = None, ) -> DateTime: """Generate random datetime. :param start: Minimum value of year. :param end: Maximum value of year. :param timezone: Set custom timezone (pytz required). :return: Datetime """ datetime_obj = datetime.combine(, end), time=self.time(), ) if timezone: if not pytz: raise ImportError("Timezones are supported only with pytz") tz = pytz.timezone(timezone) datetime_obj = tz.localize(datetime_obj) return datetime_obj
[docs] def formatted_datetime(self, fmt: str = "", **kwargs: t.Any) -> str: """Generate datetime string in human readable format. :param fmt: Custom format (default is format for current locale) :param kwargs: Keyword arguments for :meth:`~Datetime.datetime()` :return: Formatted datetime string. """ dt_obj = self.datetime(**kwargs) if not fmt: date_fmt = self.extract(["formats", "date"]) time_fmt = self.extract(["formats", "time"]) fmt = f"{date_fmt} {time_fmt}" return dt_obj.strftime(fmt)
[docs] def timestamp(self, posix: bool = True, **kwargs: t.Any) -> t.Union[str, int]: """Generate random timestamp. :param posix: POSIX time. :param kwargs: Kwargs for :meth:`~Datetime.datetime()`. :return: Timestamp. """ stamp = self.datetime(**kwargs) if posix: return timegm(stamp.utctimetuple()) return stamp.strftime("%Y-%m-%dT%H:%M:%SZ")