datetime is Python’s standard library for handling dates and times.
First, let’s see how to get the current date and time:
>>> from datetime import datetime
>>> now = datetime.now() # Get the current datetime
>>> print(now)
2015-05-18 16:28:07.198690
>>> print(type(now))
<class 'datetime.datetime'>
Note that datetime is a module, which also contains a datetime class. Importing via from datetime import datetime gives you direct access to the datetime class.
If you only import import datetime, you must reference the full name datetime.datetime.
datetime.now() returns the current date and time as a datetime object.
To specify a particular date and time, construct a datetime object directly with parameters:
>>> from datetime import datetime
>>> dt = datetime(2015, 4, 19, 12, 20) # Create datetime with specified date/time
>>> print(dt)
2015-04-19 12:20:00
datetime to TimestampIn computing, time is actually represented numerically. The moment of January 1, 1970, 00:00:00 UTC+00:00 is called the epoch time (denoted as 0; timestamps for times before 1970 are negative). The current time is the number of seconds relative to the epoch time, known as a timestamp.
You can think of it this way:
timestamp = 0 = 1970-1-1 00:00:00 UTC+0:00
The corresponding Beijing time (UTC+8:00) is:
timestamp = 0 = 1970-1-1 08:00:00 UTC+8:00
A timestamp is timezone-agnostic: once a timestamp is determined, its UTC time is fixed, and conversion to any timezone is fully deterministic. This is why computers store the current time as a timestamp—globally, all computers have identical timestamps at the same moment (assuming time synchronization).
To convert a datetime object to a timestamp, simply call the timestamp() method:
>>> from datetime import datetime
>>> dt = datetime(2015, 4, 19, 12, 20) # Create datetime with specified date/time
>>> dt.timestamp() # Convert datetime to timestamp
1429417200.0
Note that Python timestamps are floating-point numbers, where the integer part represents seconds.
Some programming languages (e.g., Java, JavaScript) use integers for timestamps (representing milliseconds). In such cases, divide the timestamp by 1000 to get Python’s floating-point representation.
datetimeTo convert a timestamp back to a datetime object, use the fromtimestamp() method provided by datetime:
>>> from datetime import datetime
>>> t = 1429417200.0
>>> print(datetime.fromtimestamp(t))
2015-04-19 12:20:00
Remember: timestamps are floating-point numbers with no timezone information, while datetime objects are timezone-aware. The conversion above maps the timestamp to local time (the timezone set by the operating system).
For example, if the local timezone is UTC+8:00 (Beijing time):
2015-04-19 12:20:00 (local time) = 2015-04-19 12:20:00 UTC+8:00
The corresponding Greenwich Mean Time (UTC+0:00) is 8 hours behind:
2015-04-19 04:20:00 UTC+0:00
You can also convert a timestamp directly to UTC time:
>>> from datetime import datetime
>>> t = 1429417200.0
>>> print(datetime.fromtimestamp(t)) # Local time
2015-04-19 12:20:00
>>> print(datetime.utcfromtimestamp(t)) # UTC time
2015-04-19 04:20:00
datetimeUser input for dates/times is often in string format. To process it, first convert the string to a datetime object using datetime.strptime(), which requires a format string for the date/time:
>>> from datetime import datetime
>>> cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
>>> print(cday)
2015-06-01 18:19:59
The format string '%Y-%m-%d %H:%M:%S' defines the structure of the date/time string. For detailed formatting rules, refer to the Python documentation.
Note: The converted datetime object has no timezone information.
datetime to StringTo format a datetime object as a human-readable string, use the strftime() method (also requires a format string):
>>> from datetime import datetime
>>> now = datetime.now()
>>> print(now.strftime('%a, %b %d %H:%M'))
Mon, May 05 16:28
datetimeTo calculate future/past times (add/subtract time), use the + and - operators with the timedelta class:
>>> from datetime import datetime, timedelta
>>> now = datetime.now()
>>> now
datetime.datetime(2015, 5, 18, 16, 57, 3, 540997)
>>> now + timedelta(hours=10)
datetime.datetime(2015, 5, 19, 2, 57, 3, 540997)
>>> now - timedelta(days=1)
datetime.datetime(2015, 5, 17, 16, 57, 3, 540997)
>>> now + timedelta(days=2, hours=12)
datetime.datetime(2015, 5, 21, 4, 57, 3, 540997)
timedelta makes it easy to calculate times for days/hours before or after a given datetime.
Local time refers to the timezone set by the system (e.g., Beijing time = UTC+8:00), while UTC time is UTC+0:00.
A datetime object has a tzinfo attribute (default: None), meaning it cannot be tied to a specific timezone unless explicitly set:
>>> from datetime import datetime, timedelta, timezone
>>> tz_utc_8 = timezone(timedelta(hours=8)) # Create UTC+8:00 timezone
>>> now = datetime.now()
>>> now
datetime.datetime(2015, 5, 18, 17, 2, 10, 871012)
>>> dt = now.replace(tzinfo=tz_utc_8) # Force timezone to UTC+8:00
>>> dt
datetime.datetime(2015, 5, 18, 17, 2, 10, 871012, tzinfo=datetime.timezone(datetime.timedelta(0, 28800)))
This code works correctly only if the system timezone is UTC+8:00. Do not force a timezone mismatch.
First get the current UTC time with utcnow(), then convert it to any timezone:
# Get UTC time and force timezone to UTC+0:00:
>>> utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
>>> print(utc_dt)
2015-05-18 09:05:12.377316+00:00
# Convert to Beijing time using astimezone():
>>> bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
>>> print(bj_dt)
2015-05-18 17:05:12.377316+08:00
# Convert to Tokyo time:
>>> tokyo_dt = utc_dt.astimezone(timezone(timedelta(hours=9)))
>>> print(tokyo_dt)
2015-05-18 18:05:12.377316+09:00
# Convert bj_dt to Tokyo time:
>>> tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9)))
>>> print(tokyo_dt2)
2015-05-18 18:05:12.377316+09:00
Key rule for timezone conversion:
When working with a datetime object, always confirm its correct timezone and set it explicitly as the baseline. Use the astimezone() method on a timezone-aware datetime to convert to any target timezone.
Note: Conversion does not have to start from UTC+0:00—any timezone-aware datetime can be converted correctly (e.g., bj_dt to tokyo_dt above).
A datetime object requires timezone information to represent a unique moment in time; otherwise, it is treated as local time.
For storage, the best practice is to convert datetime to a timestamp (timezone-agnostic) before saving.
Suppose you receive a user-input date/time string (e.g., 2015-1-21 9:01:30) and a timezone string (e.g., UTC+5:00). Write a function to convert them to a timestamp:
# -*- coding:utf-8 -*-
import re
from datetime import datetime, timezone, timedelta
def to_timestamp(dt_str, tz_str):
pass
# Test cases:
t1 = to_timestamp('2015-6-1 08:10:30', 'UTC+7:00')
assert t1 == 1433121030.0, t1
t2 = to_timestamp('2015-5-31 16:10:30', 'UTC-09:00')
assert t2 == 1433121030.0, t2
print('ok')
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from datetime import datetime, timedelta, timezone
now = datetime.now()
print("now =", now)
print("type(now) =", type(now))
dt = datetime(2015, 4, 19, 12, 20)
print("dt =", dt)
print("datetime -> timestamp:", dt.timestamp())
t = dt.timestamp()
print("timestamp -> datetime:", datetime.fromtimestamp(t))
print("timestamp -> datetime as UTC+0:", datetime.utcfromtimestamp(t))
cday = datetime.strptime("2015-6-1 18:19:59", "%Y-%m-%d %H:%M:%S")
print("strptime:", cday)
print("strftime:", cday.strftime("%a, %b %d %H:%M"))
print("current datetime =", cday)
print("current + 10 hours =", cday + timedelta(hours=10))
print("current - 1 day =", cday - timedelta(days=1))
print("current + 2.5 days =", cday + timedelta(days=2, hours=12))
utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
utc8_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
print("UTC+0:00 now =", utc_dt)
print("UTC+8:00 now =", utc8_dt)