# Python : Core Library : Dates & Times **Standard Library** \[ [calendar](https://docs.python.org/3/library/calendar.html) | [datetime](https://docs.python.org/3/library/datetime.html) | [time](https://docs.python.org/3/library/time.html) | [zoneinfo](https://docs.python.org/3/library/zoneinfo.html) ] **Third-Party** \[ python-dateutil -> [PyPI](https://pypi.org/project/python-dateutil/) | [src](https://github.com/dateutil/dateutil/) | [docs](https://dateutil.readthedocs.io/en/stable/) ] [[Tech/Data/Dates & Times|ISO 8601]] ## Standard Library #### calendar Useful for creating calendar displays. ```python Calendar( firstweekday=0 ) # 0 == Monday calendar.Day # enum calendar.MONDAY ... calendar.Month # enum calendar.JANUARY ... ``` ```bash $ python -m calendar 2000 ``` #### datetime - *aware* — includes tz context - *naive* — doesn't include tz context - all four types are immutable (`date`, `datetime`, `time`, `timedelta`) - for types with a `tzinfo` attribute (`datetime` and `time`), set it to an instance of a subclass of the abstract base class `datetime.tzinfo` — such as `datetime.timezone` and `zoneinfo.ZoneInfo` - for methods with a `timespec` parameter (`datetime` and `time`), it indicates the truncation point - options: `auto`, `hours`, `minutes`, `seconds`, `milliseconds`, `microseconds` ###### Formatting Codes ``` %a weekday, abbrev Sun..Sat %A weekday, full Sunday..Saturday %w weekday, number 0..6 %d day of month 01..31 %b month, abbrev Jan..Dec %B month, full January..December %m month, number 01..12 %y year, short 00..99 %Y year, full 0001..9999 %H hour (24hr clock) 00..23 %I hour (12hr clock) 00..12 %p AM/PM %M minute 00..59 %S second 00.59 %f microsecond 000000..999999 %z offset "" or ±HHMM[SS[.ffffff]] %Z time zone "", UTC, GMT, ... %j day of year 001..366 %U week number (Sun) 00..53 %W week number (Mon) 00..53 %c localized datetime ex: Tue Aug 16 21:30:00 1988 %x localized date ex: 08/16/88, 08/16/1988 %X localized time ex: 21:30:00 %% literal '%' ``` ###### API ```python # supports comparison operators with itself date( year, month (1-12), day (1-31) ) # Class Attributes .today() # current local date .fromtimestamp( timestamp ) # takes a float representing POSIX time (seconds since 1970) .fromisoformat( datestring ) # Instance Attributes .__format__/.strftime( format ) .__str__/.isoformat() # "YYYY-MM-DD" .isoweekday() # 1 (Mon) .. 7 (Sun) .replace( year, month, day ) .weekday() # 0 (Mon) .. 6 (Sun) # subclass of `date` # fold := the first or second time through the hour (because of DST shifts) # supports comparison operators with itself if both operands are aware or both are naive datetime( year, month (1-12), day (1-31), hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0 (0-1) ) # Class Attributes .fromisoformat( datetimestring ) .fromtimestamp( timestamp, tz=None ) # takes a float representing POSIX time (seconds since 1970) .now( tz=None ) # same as today() unless tz passed .strptime( datetimestring, format ) .today() # current local datetime .utcfromtimestamp( timestamp ) # deprecated in favor of fromtimestamp( tz=timezone.utc ) .utcnow() # deprecated in favor of now( tz=timezone.utc ) # Instance Attributes __format__/strftime( format ) __str__() # equiv to isoformat( " " ) astimezone( tz=None ) # if no tz, assumes local time date() isoformat( sep="T", timespec="auto" ) # YYYY-MM-DDTHH:MM:SS if microsecond is 0 # YYYY-MM-DDTHH:MM:SS.ffffff if microsecond is not 0 # +HH:MM if tzinfo isoweekday() # 1 (Mon) .. 7 (Sun) replace( ... ) time() # without tzinfo timestamp() # returns POSIX time as float (seconds since 1970) tztime() # with tzinfo weekday() # 0 (Mon) .. 6 (Sun) # supports comparisons with itself if both operands are naive or both are aware time( hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0 ) # Class Attributes .fromisoformat( timestring ) # Instance Attributes .__format__/.strftime( format ) .__str__() # equiv to isoformat() .isoformat( timespec="auto" ) .replace( ... ) # only stores days, seconds and microseconds - the rest get converted to those three units # supports math operations with itself as well as date and datetime # supports comparison operations with itself timedelta( days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0 ) # Instance Attributes .total_seconds() tzinfo # ABC timezone < tzinfo # Class Attributes .utc UTC -> datetime.timezone.utc # type: datetime.timezone ``` #### time ```python process_time() # seconds of time consumed by process so far sleep( seconds ) time() # current POSIX datetime (float) tzname() # returns tuple: ( non-dst name, dst name ) ``` #### zoneinfo [tz database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) ```python ZoneInfo < datetime.tzinfo ZoneInfo( key ) # key is path relative to TZPATH # ex: "America/Los_Angeles", "America/Chicago", "America/New_York" key/__str__() available_timezones() # returns set TZPATH # Ubuntu: /usr/share/zoneinfo ``` ## python-dateutil ```python from dateutil.relativedelta import relativedelta # Supports math operations with datetimes: # - relative values are added or subtracted from current # - absolute values replace current # Two construction methods: d = relativedelta( dt1, dt2 ) d = relativedelta( years, months, weeks, days, hours, minutes, seconds, microseconds, # relative values year, month, day, hour, minute, second, microsecond, # absolute values ) # Example: d = datetime.now() + relativedelta( days=1, hour=10 ) # tomorrow at 10am ``` Also `dateutil.rrule`, which implements the recurrence rules from [RFC 5545](https://datatracker.ietf.org/doc/html/rfc5545) ([iCalendar](https://icalendar.org/)). ```python import dateutil.rrule as dr import dateutil.parser as dp import dateutil.relativedelta as drel start = dp.parse( "19/02/2010" ) # 3rd Fri in 2010-Feb rr = dr.rrule( dr.MONTHLY, byweekday = drel.FR( 3 ), dtstart=start, count=10 ) # 3rd Fri/ea month print map( str, rr ) -> [ "2010-02-19 00:00:00" ... "2010-11-19 00:00:00" ] print [ d.strftime( "%d/%m/%Y" ) for d in rr[ ::2 ] ] -> [ "19/02/2010", "16/04/2010", "18/06/2010", "20/08/2010", "15/10/2010" ] ```