One Python standard library per week | datetime

Keywords: github Python

Technology blog: https://github.com/yongxinz/tech-blog

At the same time, welcome to pay attention to my WeChat public number AlwaysBeta, more wonderful content waiting for you to come.

datetime contains functions and classes for processing dates and times.

Time

The time value is represented by the time class. Time instances have the attributes hour, minute, second, and microsecond, and can also include time zone information.

import datetime

t = datetime.time(1, 2, 3)
print(t)	# 01:02:03
print('hour       :', t.hour)	# hour       : 1
print('minute     :', t.minute)	# minute     : 2
print('second     :', t.second)	# second     : 3
print('microsecond:', t.microsecond)	# microsecond: 0
print('tzinfo     :', t.tzinfo)	# tzinfo     : None

The time instance only keeps the time value, not the date associated with the time.

import datetime

print('Earliest  :', datetime.time.min)	# Earliest  : 00:00:00
print('Latest    :', datetime.time.max)	# Latest    : 23:59:59.999999
print('Resolution:', datetime.time.resolution)	# Resolution: 0:00:00.000001

The properties of min and max reflect the effective range of time in a day.

The resolution of time is limited to the whole microsecond. (it can also be said to be a microsecond, see the above code resolution for details)

import datetime

for m in [1, 0, 0.1, 0.6]:
    try:
        print('{:02.1f} :'.format(m),
              datetime.time(0, 0, 0, microsecond=m))
    except TypeError as err:
        print('ERROR:', err)
  
# output
# 1.0 : 00:00:00.000001
# 0.0 : 00:00:00
# ERROR: integer argument expected, got float
# ERROR: integer argument expected, got float        

A floating-point value of microseconds causes a TypeError.

Date

The date value is represented by the date class. Instances have properties year, month, and day. You can easily create the current date using the today() class method.

import datetime

today = datetime.date.today()
print(today)	# 2018-03-18
print('ctime  :', today.ctime())	# ctime  : Sun Mar 18 00:00:00 2018
tt = today.timetuple()
print('tuple  : tm_year  =', tt.tm_year)	# tuple  : tm_year  = 2018
print('         tm_mon   =', tt.tm_mon)		# tm_mon   = 3
print('         tm_mday  =', tt.tm_mday)	# tm_mday  = 18
print('         tm_hour  =', tt.tm_hour)	# tm_hour  = 0
print('         tm_min   =', tt.tm_min)		# tm_min   = 0
print('         tm_sec   =', tt.tm_sec)		# tm_sec   = 0
print('         tm_wday  =', tt.tm_wday)	# tm_wday  = 6
print('         tm_yday  =', tt.tm_yday)	# tm_yday  = 77
print('         tm_isdst =', tt.tm_isdst)	# tm_isdst = -1
print('ordinal:', today.toordinal())	# ordinal: 736771
print('Year   :', today.year)	# Year   : 2018
print('Mon    :', today.month)	# Mon    : 3
print('Day    :', today.day)	# Day    : 18

There are also class methods for creating instances from POSIX timestamps or integers representing date values in the Gregorian calendar, where January 1, 1 year is 1, and each subsequent date increments the value by 1.

import datetime
import time

o = 733114
print(o)	# o               : 733114
print(datetime.date.fromordinal(o))	# fromordinal(o)  : 2008-03-13

t = time.time()
print(t)	# t               : 1521404434.262209
print(datetime.date.fromtimestamp(t))	# fromtimestamp(t): 2018-03-18

This example illustrates the different value types used by fromordinal() and fromtimestamp().

As with time, you can use the min and max attributes to determine the range of supported date values.

import datetime

print('Earliest  :', datetime.date.min)	# Earliest  : 0001-01-01
print('Latest    :', datetime.date.max)	# Latest    : 9999-12-31
print('Resolution:', datetime.date.resolution)	# Resolution: 1 day, 0:00:00

The accuracy of the date is all day.

Another way to create a new date instance is to use replace().

import datetime

d1 = datetime.date(2008, 3, 29)
print('d1:', d1.ctime())	# d1: Sat Mar 29 00:00:00 2008

d2 = d1.replace(year=2009)
print('d2:', d2.ctime())	# d2: Sun Mar 29 00:00:00 2009

This example changes the year, date, and month.

timedeltas

Two datetime objects can be used for basic calculation, or datetime and timedelta can be combined to calculate future and past dates. Subtracting a date produces a timedelta, or you can add or subtract timedelta from a date to produce another date. The internal values of timedelta are stored in days, seconds and microseconds.

import datetime

print('microseconds:', datetime.timedelta(microseconds=1))	# 0:00:00.000001
print('milliseconds:', datetime.timedelta(milliseconds=1))	# 0:00:00.001000
print('seconds     :', datetime.timedelta(seconds=1))	# 0:00:01
print('minutes     :', datetime.timedelta(minutes=1))	# 0:01:00
print('hours       :', datetime.timedelta(hours=1))	# 1:00:00
print('days        :', datetime.timedelta(days=1))	# 1 day, 0:00:00
print('weeks       :', datetime.timedelta(weeks=1))	# 7 days, 0:00:00

Intermediate level values passed to the constructor are converted to days, seconds, and microseconds.

The full duration of the timedelta can be retrieved in seconds using total "seconds().

import datetime

for delta in [datetime.timedelta(microseconds=1),
              datetime.timedelta(milliseconds=1),
              datetime.timedelta(seconds=1),
              datetime.timedelta(minutes=1),
              datetime.timedelta(hours=1),
              datetime.timedelta(days=1),
              datetime.timedelta(weeks=1),
              ]:
    print('{:15} = {:8} seconds'.format(
        str(delta), delta.total_seconds())
    )

# output    
# 0:00:00.000001  =    1e-06 seconds
# 0:00:00.001000  =    0.001 seconds
# 0:00:01         =      1.0 seconds
# 0:01:00         =     60.0 seconds
# 1:00:00         =   3600.0 seconds
# 1 day, 0:00:00  =  86400.0 seconds
# 7 days, 0:00:00 = 604800.0 seconds    

The return value is a floating-point number to accommodate the next second duration.

Date calculation

Standard arithmetic operators are used for date calculation.

import datetime

today = datetime.date.today()
print('Today    :', today)	# Today    : 2018-03-18

one_day = datetime.timedelta(days=1)
print('One day  :', one_day)	# One day  : 1 day, 0:00:00

yesterday = today - one_day
print('Yesterday:', yesterday)	# Yesterday: 2018-03-17

tomorrow = today + one_day
print('Tomorrow :', tomorrow)	# Tomorrow : 2018-03-19

print('tomorrow - yesterday:', tomorrow - yesterday)	# 2 days, 0:00:00
print('yesterday - tomorrow:', yesterday - tomorrow)	# -2 days, 0:00:00

The example shows that using the timedelta object to calculate a new date, you can subtract the date instance to generate the timedelta (including the negative delta value).

Timedelta objects also support arithmetic operations with integers, floating-point numbers, and other timedelta objects.

import datetime

one_day = datetime.timedelta(days=1)
print('1 day    :', one_day)	# 1 day    : 1 day, 0:00:00
print('5 days   :', one_day * 5)	# 5 days   : 5 days, 0:00:00
print('1.5 days :', one_day * 1.5)	# 1.5 days : 1 day, 12:00:00
print('1/4 day  :', one_day / 4)	# 1/4 day  : 6:00:00

# assume an hour for lunch
work_day = datetime.timedelta(hours=7)
meeting_length = datetime.timedelta(hours=1)
print('meetings per day :', work_day / meeting_length)	# meetings per day : 7.0

In this example, several multiples of a day are calculated, resulting in timedelta holding days or hours. The final example shows how to evaluate values by combining two timedelta objects. In this case, the result is a floating-point number.

Date and time comparison

You can use standard comparison operators to compare date and time values to determine which is earlier or later.

import datetime
import time

print('Times:')	# Times:
t1 = datetime.time(12, 55, 0)
print('  t1:', t1)	# t1: 12:55:00
t2 = datetime.time(13, 5, 0)
print('  t2:', t2)	# t2: 13:05:00
print('  t1 < t2:', t1 < t2)	# t1 < t2: True

print('Dates:')	# Dates:
d1 = datetime.date.today()
print('  d1:', d1)	# d1: 2018-03-18
d2 = datetime.date.today() + datetime.timedelta(days=1)
print('  d2:', d2)	# d2: 2018-03-19
print('  d1 > d2:', d1 > d2)	# d1 > d2: False

All comparison operators are supported.

Combined date and time

Use the datetime class to hold values made up of date and time components. Like date, there are several simple class methods that can create instances of datetime.

import datetime

print('Now    :', datetime.datetime.now())
print('Today  :', datetime.datetime.today())
print('UTC Now:', datetime.datetime.utcnow())
print()

FIELDS = [
    'year', 'month', 'day',
    'hour', 'minute', 'second',
    'microsecond',
]

d = datetime.datetime.now()
for attr in FIELDS:
    print('{:15}: {}'.format(attr, getattr(d, attr)))
    
# output
# Now    : 2018-03-18 16:20:34.811583
# Today  : 2018-03-18 16:20:34.811616
# UTC Now: 2018-03-18 20:20:34.811627

# year           : 2018
# month          : 3
# day            : 18
# hour           : 16
# minute         : 20
# second         : 34
# microsecond    : 811817

The date time instance has all the properties of the date and time objects.

Like date, datetime provides a convenient class method for creating new instances. It also includes fromordinal() and fromtimestamp().

import datetime

t = datetime.time(1, 2, 3)
print('t :', t)		# t : 01:02:03

d = datetime.date.today()
print('d :', d)		# d : 2018-03-18

dt = datetime.datetime.combine(d, t)
print('dt:', dt)	# dt: 2018-03-18 01:02:03

combine() creates a date time instance from a date and a time instance.

Formatting and parsing

The default string representation of the datetime object uses the ISO-8601 format (YYYY-MM-DDTHH:MM:SS.mmmmmm). You can use the generate alternative format strftime().

import datetime

format = "%a %b %d %H:%M:%S %Y"

today = datetime.datetime.today()
print('ISO     :', today)	# ISO     : 2018-03-18 16:20:34.941204

s = today.strftime(format)
print('strftime:', s)	# strftime: Sun Mar 18 16:20:34 2018

d = datetime.datetime.strptime(s, format)
print('strptime:', d.strftime(format))	# strptime: Sun Mar 18 16:20:34 2018

Use datetime.strptime() to convert the formatted string to a datetime instance.

Python String formatting Mini language You can use the same format code by placing them in the field specification of the format string.

import datetime

today = datetime.datetime.today()
print('ISO     :', today)	# ISO     : 2018-03-18 16:20:35.006116
print('format(): {:%a %b %d %H:%M:%S %Y}'.format(today))	# format(): Sun Mar 18 16:20:35 2018

Each date time format code must still be prefixed with% and subsequent colons will be treated as literal characters to be included in the output.

The following table shows all the format codes for the US / Eastern time zone at 5:00 p.m. on January 13, 2016.

Symbol Meaning example
%a Abbreviated working day name 'Wed'
%A Full working day name 'Wednesday'
%w Weekday number - 0 (Sunday) to 6 (Saturday) '3'
%d Day of the month (zero fill) '13'
%b Abbreviated month name 'Jan'
%B Full month name 'January'
%m One month of the year '01'
%y A year without a century '16'
%Y And the year of the century '2016'
%H 24-hour hours '17'
%I 12 hour hours '05'
%p Morning afternoon 'PM'
%M Minute '00'
%S second '00'
%f Microsecond '000000'
%z UTC offset of time zone aware objects '-0500'
%Z Time zone name 'EST'
%j One day of the year '013'
%W A week of the year '02'
%c Date and time representations of the current locale 'Wed Jan 13 17:00:00 2016'
%x Date representation of the current locale '01/13/16'
%X Time representation of the current locale '17:00:00'
%% Text% character '%'

time zone

In which datetime, the time zone is represented by subclass tzinfo. Because tzinfo is an abstract base class, an application needs to define a subclass and provide appropriate implementation for some methods to make it useful.

datetime does use a somewhat naive implementation in the timezone class, which uses UTC's fixed offset and does not support different offset values for different dates in a year, such as where daylight saving time is applicable, or when UTC's offset changes over time.

import datetime

min6 = datetime.timezone(datetime.timedelta(hours=-6))
plus6 = datetime.timezone(datetime.timedelta(hours=6))
d = datetime.datetime.now(min6)

print(min6, ':', d)	
print(datetime.timezone.utc, ':',
      d.astimezone(datetime.timezone.utc))
print(plus6, ':', d.astimezone(plus6))

# convert to the current system timezone
d_system = d.astimezone()
print(d_system.tzinfo, '      :', d_system)

# UTC-06:00 : 2018-03-18 14:20:35.123594-06:00
# UTC : 2018-03-18 20:20:35.123594+00:00
# UTC+06:00 : 2018-03-19 02:20:35.123594+06:00
# EDT       : 2018-03-18 16:20:35.123594-04:00

To convert a datetime value from one time zone to another, use astimezone(). In the above example, two independent time zones of 6 hours on both sides of UTC are shown, and the UTC instance from datetime.timezone is also used for reference. The final output line shows the value in the system time zone, which is obtained by calling astimezone() without parameters.

Related documents:

https://pymotw.com/3/datetime/index.html

https://zhuanlan.zhihu.com/p/28209870

16 original articles published, 30 praised, 40000 visitors+
Private letter follow

Posted by Shamrox on Tue, 21 Jan 2020 01:55:08 -0800