:py:mod:`cftime_rs`
===================

.. py:module:: cftime_rs


Subpackages
-----------
.. toctree::
   :titlesonly:
   :maxdepth: 3

   tests/index.rst


Submodules
----------
.. toctree::
   :titlesonly:
   :maxdepth: 1

   cftime_rs/index.rst


Package Contents
----------------

Classes
~~~~~~~

.. autoapisummary::

   cftime_rs.PyCFCalendar
   cftime_rs.PyCFDuration
   cftime_rs.PyCFDatetime



Functions
~~~~~~~~~

.. autoapisummary::

   cftime_rs.num2date
   cftime_rs.num2pydate
   cftime_rs.date2num
   cftime_rs.pydate2num



.. py:class:: PyCFCalendar


   PyCFCalendar represents a calendar object.

   .. py:method:: from_str(s: str) -> PyCFCalendar
      :staticmethod:

      Create a PyCFCalendar from a string representation.

      :param s: The string representation of the calendar.
      :type s: str

      :returns: A PyCFCalendar object.
      :rtype: PyCFCalendar

      :raises ValueError: If the calendar string cannot be parsed.



.. py:class:: PyCFDuration


   PyCFDuration is a wrapper around Rust CFDuration.

   All the methods depend on the Calendar definitions found in
   [udunits package](https://github.com/nco/nco/blob/master/data/udunits.dat).

   This duration can be added to a PyCFDatetime.
   The result of the subtraction between two PyCFDatetime objects gives a PyCFDuration.

   .. py:method:: from_years(years: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of years and specific calendar.

      :param years: Number of years.
      :type years: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_month(month: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of month and specific calendar.

      :param month: Number of month.
      :type month: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_weeks(weeks: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of weeks and specific calendar.

      :param weeks: Number of weeks.
      :type weeks: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_days(days: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of days and specific calendar.

      :param days: Number of days.
      :type days: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_hours(hours: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of hours and specific calendar.

      :param hours: Number of hours.
      :type hours: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_minutes(minutes: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of minutes and specific calendar.

      :param minutes: Number of minutes.
      :type minutes: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_seconds(seconds: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of seconds and specific calendar.

      :param seconds: Number of seconds.
      :type seconds: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_milliseconds(milliseconds: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of milliseconds and specific calendar.

      :param milliseconds: Number of milliseconds.
      :type milliseconds: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_microseconds(microseconds: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of microseconds and specific calendar.

      :param microseconds: Number of microseconds.
      :type microseconds: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: from_nanoseconds(nanoseconds: int, calendar: PyCFCalendar) -> PyCFDuration
      :classmethod:

      Makes a new PyCFDuration with the given number of nanoseconds and specific calendar.

      :param nanoseconds: Number of nanoseconds.
      :type nanoseconds: int
      :param calendar: The calendar for the duration.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDuration object.
      :rtype: PyCFDuration


   .. py:method:: num_years() -> float

      Returns the total number of years in the duration.

      :returns: Number of years.
      :rtype: float


   .. py:method:: num_months() -> float

      Returns the total number of months in the duration.

      :returns: Number of months.
      :rtype: float


   .. py:method:: num_weeks() -> float

      Returns the total number of weeks in the duration.

      :returns: Number of weeks.
      :rtype: float


   .. py:method:: num_days() -> float

      Returns the total number of days in the duration.

      :returns: Number of days.
      :rtype: float


   .. py:method:: num_hours() -> float

      Returns the total number of hours in the duration.

      :returns: Number of hours.
      :rtype: float


   .. py:method:: num_minutes() -> float

      Returns the total number of minutes in the duration.

      :returns: Number of minutes.
      :rtype: float


   .. py:method:: num_seconds() -> float

      Returns the total number of seconds in the duration.

      :returns: Number of seconds.
      :rtype: float


   .. py:method:: num_milliseconds() -> float

      Returns the total number of milliseconds in the duration.

      :returns: Number of milliseconds.
      :rtype: float


   .. py:method:: num_microseconds() -> float

      Returns the total number of microseconds in the duration.

      :returns: Number of microseconds.
      :rtype: float


   .. py:method:: num_nanoseconds() -> float

      Returns the total number of nanoseconds in the duration.

      :returns: Number of nanoseconds.
      :rtype: float



.. py:class:: PyCFDatetime


   PyCFDatetime is a wrapper around Rust CFDatetime.

   It represents a date in a specific calendar.

   All the methods depend on the Calendar definitions found in
   [udunits package](https://github.com/nco/nco/blob/master/data/udunits.dat).

   .. py:method:: new(year: int, month: int, day: int, hour: int, minute: int, second: float, calendar: PyCFCalendar) -> PyCFDatetime
      :classmethod:

      Makes a new PyCFDatetime with given year, month, day, hour, minute, second, and specific calendar.

      :param year: The year.
      :type year: int
      :param month: The month.
      :type month: int
      :param day: The day.
      :type day: int
      :param hour: The hour.
      :type hour: int
      :param minute: The minute.
      :type minute: int
      :param second: The second.
      :type second: float
      :param calendar: The calendar for the datetime.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDatetime object.
      :rtype: PyCFDatetime


   .. py:method:: ymd() -> Tuple[int, int, int]

      Returns the year, month, and day of the date.

      :returns: A tuple of (year, month, day).
      :rtype: Tuple[int, int, int]


   .. py:method:: hms() -> Tuple[int, int, int]

      Returns the hour, minute, and second of the time.

      :returns: A tuple of (hour, minute, second).
      :rtype: Tuple[int, int, int]


   .. py:method:: ymd_hms() -> Tuple[int, int, int, int, int, int]

      Returns the year, month, day, hour, minute, and second of the datetime.

      :returns: A tuple of (year, month, day, hour, minute, second).
      :rtype: Tuple[int, int, int, int, int, int]


   .. py:method:: from_ymd_hms(year: int, month: int, day: int, hour: int, minute: int, second: float, calendar: PyCFCalendar) -> PyCFDatetime
      :classmethod:

      Makes a new PyCFDatetime with given year, month, day, hour, minute, second, and specific calendar.

      :param year: The year.
      :type year: int
      :param month: The month.
      :type month: int
      :param day: The day.
      :type day: int
      :param hour: The hour.
      :type hour: int
      :param minute: The minute.
      :type minute: int
      :param second: The second.
      :type second: float
      :param calendar: The calendar for the datetime.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDatetime object.
      :rtype: PyCFDatetime


   .. py:method:: from_hms(hour: int, minute: int, second: float, calendar: PyCFCalendar) -> PyCFDatetime
      :classmethod:

      Makes a new PyCFDatetime with given hour, minute, second, and specific calendar.
      The year, month, and day are set to 1970-01-01.

      :param hour: The hour.
      :type hour: int
      :param minute: The minute.
      :type minute: int
      :param second: The second.
      :type second: float
      :param calendar: The calendar for the datetime.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDatetime object.
      :rtype: PyCFDatetime


   .. py:method:: from_ymd(year: int, month: int, day: int, calendar: PyCFCalendar) -> PyCFDatetime
      :classmethod:

      Makes a new PyCFDatetime with given year, month, day, and specific calendar.
      The hour, minute, and second are set to 0.

      :param year: The year.
      :type year: int
      :param month: The month.
      :type month: int
      :param day: The day.
      :type day: int
      :param calendar: The calendar for the datetime.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDatetime object.
      :rtype: PyCFDatetime


   .. py:method:: from_timestamp(timestamp: int, nanoseconds: int, calendar: PyCFCalendar) -> PyCFDatetime
      :classmethod:

      Makes a new PyCFDatetime with given timestamp, nanoseconds, and specific calendar.

      :param timestamp: The timestamp.
      :type timestamp: int
      :param nanoseconds: The nanoseconds.
      :type nanoseconds: int
      :param calendar: The calendar for the datetime.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDatetime object.
      :rtype: PyCFDatetime


   .. py:method:: change_calendar(calendar: PyCFCalendar) -> PyCFDatetime

      Change the calendar of the PyCFDatetime.

      This can be considered as safe as this method try to recreate the datetime with the same year, month,
      day, hour, minute, second and nanoseconds.

      :param calendar: The calendar for the datetime.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDatetime object.
      :rtype: PyCFDatetime

      :raises ValueError: If the date is not possible in the target calendar.


   .. py:method:: change_calendar_from_timestamp(calendar: PyCFCalendar) -> PyCFDatetime

      Change the calendar of the CFDatetime using the timestamp

      Be aware that there is highly chance that the two dates do not correspond.
      However their distances from epoch are the same.

      :param calendar: The calendar for the datetime.
      :type calendar: PyCFCalendar

      :returns: A new PyCFDatetime object.
      :rtype: PyCFDatetime

      :raises ValueError: If the date is not possible in the target calendar.


   .. py:method:: to_pydatetime() -> datetime.datetime

      Converts the object to a Python datetime object using year, month, day, hour, minute,
      and second

      :returns: A datetime object representing the same date and time as the object.

      :raises ValueError: If the date cannot be converted to a datetime


   .. py:method:: to_pydatetime_from_timestamp() -> datetime.datetime

      Converts the object to a Python datetime object using the timestamp

      :returns: A datetime object representing the same underlying timestamp

      :raises ValueError: If the date cannot be converted to a datetime



.. py:function:: num2date(arr: Iterable[Union[int, float]], units: str, calendar: str) -> List[PyCFDatetime]

   Convert a list of numbers to PyCFDatetime objects based on the specified calendar.

   :param arr: Iterable[Union[int, float]]
               Array of numbers to convert to PyCFDatetime
   :param units: str
                 Valid CF units
   :param calendar: str
                    CF calendar name. Should be one of "standard", "gregorian",
                    "proleptic_gregorian", "julian", "all_leap", "no_leap", "360_day", "365_day", "366_day".
                    If the calendar is not recognized, "standard" will be used

   :raises ValueError: If the date is not valid in the calendar

   :returns:

             List[PyCFDatetime]
                 List of PyCFDatetime objects


.. py:function:: num2pydate(arr: Iterable[Union[int, float]], units: str, calendar: str, from_timestamp: bool = False) -> List[datetime.datetime]

   Convert a list of numbers to datetime objects based on the specified calendar.

   :param arr: Iterable[Union[int, float]]
               Array of numbers to convert to datetime
   :param units: str
                 Valid CF units
   :param calendar: str
                    CF calendar name. Should be one of "standard", "gregorian",
                    "proleptic_gregorian", "julian", "all_leap", "no_leap", "360_day", "365_day", "366_day".
                    If the calendar is not recognized, "standard" will be used
   :param from_timestamp: bool
                          If True, the date will be converted using timestamp value from epoch and python datetime
                          `.from_timestamp` method will be used. This method guarantee that the date is valid if no
                          overflow occurs. While the distance from epoch is the same, the date are likely to be different.
                          If False, the date will be converted using python datetime constructor method : the year, month, day, hour, minute, second and nanoseconds will be extyracted from PyCFDatetime object and given back to python datetime constructor. There is no guarantee that the date is valid in the calendar. This method is also considerably slower than using the timestamp.
                          Default value is False.

   :raises ValueError: If the date is not valid in the calendar

   :returns:

             List[datetime.datetime]
                 List of datetime.datetime objects


.. py:function:: date2num(datetimes: List[PyCFDatetime], units: str, calendar: str, dtype: str) -> Union[int, float]

   Convert a list of PyCFDatetime objects to a list of numbers based on calendar, units, and dtype.


   :param datetimes: List[PyCFDatetime]
                     List of PyCFDatetime objects
   :param units: str
                 Valid CF units
   :param calendar: str
                    CF calendar name. Should be one of "standard", "gregorian",
   :param dtype: str
                 32 bit integer : "i32"
                 64 bit integer : "i64", "i", "integer", "int"
                 32 bit float   : "f32"
                 64 bit float   :  "f64", "f", "float"

   :raises ValueError: If the date is not valid in the calendar
   :raises ValueError: If the dtype is not recognized

   :returns:

             Union[int, float]
                 List of numbers based on calendar, units, and dtype


.. py:function:: pydate2num(datetimes: List[datetime.datetime], units: str, calendar: str, dtype: str) -> Union[int, float]

   Convert a list of python datetime to a list of numbers based on calendar, units, and dtype.

   Since the backend is implemented in Rust, we need to call python datetimes arguments
   in order to convert them to rust object. This inevitably leads to a lot of overhead and
   lower performance thant using num2date.

   :param datetimes: List[datetime.datetime]
                     List of python datetime.datetime objects
   :param units: str
                 Valid CF units
   :param calendar: str
                    CF calendar name. Should be one of "standard", "gregorian",
   :param dtype: str
                 32 bit integer : "i32"
                 64 bit integer : "i64", "i", "integer", "int"
                 32 bit float   : "f32"
                 64 bit float   :  "f64", "f", "float"

   :raises ValueError: If the date is not valid in the calendar
   :raises ValueError: If the dtype is not recognized

   :returns:

             Union[int, float]
                 List of numbers based on calendar, units, and dtype


