Chapter 10 Date, Time and Timezone
10.1 Library Import
All below are built-in libraries. There is a popular library named pytz not covered in this chapter as it is being deprecated. The replacement of pytz is ZoneInfo.
from datetime import date, datetime, timedelta, time
from zoneinfo import ZoneInfo
10.2 ZoneInfo
ZoneInfo is the recommended built-in library to deal with timezone for datetime object.
10.2.1 Constructor
Initialize with zone name as key: ZoneInfo(key='<zone_name'>)
.
= ZoneInfo('Asia/Kuala_Lumpur')
MY = ZoneInfo('America/New_York')
NY = ZoneInfo('UTC')
UTC
MY
NY UTC
## zoneinfo.ZoneInfo(key='Asia/Kuala_Lumpur')
## zoneinfo.ZoneInfo(key='America/New_York')
## zoneinfo.ZoneInfo(key='UTC')
10.3 Date and Datetime
This is a built-in library by Python. There is no need to install this library.
date
and datetime
are both standard built-in python library.
datetime
library contain four object classes:
- date: (year,month,day)
- time: (hour,minute,second)
- datetime: (year,month,day,hour,minute,second)
- timedelta: duration between two datetime or date object
10.3.1 ISO8601
Refer ISO8601 in Wikipedia to understand the common ISO on date/datetime formatting.
UTC: "2007-04-05T14:30Z" #notice Z
GMT+8: "2007-04-05T12:30+08:00 #notice +08:00
GMT+8: "2007-04-05T12:30+0800 #notice +0800
GMT+8: "2007-04-05T12:30+08 #notice +08```
### Date
2019-02-04 #notice no timezone available
10.3.2 Constructor
Use constructor to create datetime / date object. You can make it timezone aware with tzinfo
parameter, which is an ZoneInfo object.
## Date Only
2000,1,1)
date (type(date (2000,1,1))
## Datetime - TImezone Naive
2000,1,1,23,15,55)
datetime (=2000,month=1,day=1,hour=23,minute=15,second=55)
datetime (yeartype(datetime(2000,1,1,0,0,0))
## datetime.date(2000, 1, 1)
## <class 'datetime.date'>
## datetime.datetime(2000, 1, 1, 23, 15, 55)
## datetime.datetime(2000, 1, 1, 23, 15, 55)
## <class 'datetime.datetime'>
Timezone Integration
Datetime supports timezone through built-in library (refer ZoneInfo chapter). Initialize datetime with tzinfo
parameter to have a timezone aware datetime.
= ZoneInfo('Asia/Kuala_Lumpur')
MY = ZoneInfo('America/New_York')
NY = ZoneInfo('UTC')
UTC
## Timezone Aware
2000,1,1,23,15,55, tzinfo=NY) datetime (
## datetime.datetime(2000, 1, 1, 23, 15, 55, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
10.3.3 Class Methods
Now and Today
- Both
now()
andtoday()
return current system local datetime, which is timezone naive. utcnow()
returns UTC datetime, which is also timezone naive.- Only
now()
supportstz
parameter to convert the time to desired timezone. today() / utcnow()** does not supports **
tz``` parameter.
## local datetime
datetime.now() ## local datetime, same as above
datetime.today() ## UTC datetime
datetime.utcnow() =NY) ## convert to New York timezone
datetime.now(tz=NY) ## Error
datetime.today(tz=NY) ## Error datetime.utcnow(tz
## datetime.datetime(2022, 12, 31, 12, 0, 9, 625769)
## datetime.datetime(2022, 12, 31, 12, 0, 9, 636771)
## datetime.datetime(2022, 12, 31, 4, 0, 9, 645774)
## datetime.datetime(2022, 12, 30, 23, 0, 9, 652001, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
## Error in py_call_impl(callable, dots$args, dots$keywords): TypeError: datetime.today() takes no keyword arguments
## Error in py_call_impl(callable, dots$args, dots$keywords): TypeError: datetime.utcnow() takes no keyword arguments
Combine Data and Time (combine)
Apply datetime.combine()
class method on both date and time objects to get datetime
= datetime.now()
now datetime.combine(now.date(), now.time())
## datetime.datetime(2022, 12, 31, 12, 0, 9, 875439)
Convert from String (strptime)
Use strptime
to convert string into datetime object. Refer this cheatsheet for complete directives.
%I : 12-hour
%H : 24-hour
%M : Minute
%p : AM/PM
%y : 18
%Y : 2018
%b : Mar
%m : month (1 to 12)
%d : day
'2011-02-25', '%Y-%m-%d')
datetime.strptime('9-01-18', '%d-%m-%y')
datetime.strptime('09-Mar-2018','%d-%b-%Y')
datetime.strptime('2/5/2018 4:49 PM', '%m/%d/%Y %I:%M %p') datetime.strptime(
## datetime.datetime(2011, 2, 25, 0, 0)
## datetime.datetime(2018, 1, 9, 0, 0)
## datetime.datetime(2018, 3, 9, 0, 0)
## datetime.datetime(2018, 2, 5, 16, 49)
Convert from ISO (fromisoformat)
fromisoformat()
is the reverse ofisoformat()
.
- It actually not ISO compliance: when Z or +8 is included at the end of the string, Error is triggered.
## checkout the iso format
datetime.now().isoformat() "2019-02-05T10:22:33") ## Good
datetime.fromisoformat("2019-02-05T10:22:33Z") ## Error due to trailing 'Z'
datetime.fromisoformat("2019-02-05T10:22:33+0800") ## Errordue to trailing '+0800' datetime.fromisoformat(
## '2022-12-31T12:00:10.354497'
## datetime.datetime(2019, 2, 5, 10, 22, 33)
## Error in py_call_impl(callable, dots$args, dots$keywords): ValueError: Invalid isoformat string: '2019-02-05T10:22:33Z'
## Error in py_call_impl(callable, dots$args, dots$keywords): ValueError: Invalid isoformat string: '2019-02-05T10:22:33+0800'
10.3.4 Instance Attributes
= datetime.now(tz=MY) ## initialize the instance
now
now.month
now.day
now.hour
now.minute## this would be null if TZ parameter not specified now.tzinfo
## 12
## 31
## 12
## 0
## zoneinfo.ZoneInfo(key='Asia/Kuala_Lumpur')
10.3.5 Instance Methods
Update Data(.replace)
Use replace()
to change any parameters of the date/datetime during initialization.
= datetime(1997,3,1,10,35,21) ## replace for datetime
birthday
birthday=NY, year=1998, month=5)
birthday.replace(tzinfo
= date(1999,8,31) ## replace for date
holiday
holiday=2000) holiday.replace(year
## datetime.datetime(1997, 3, 1, 10, 35, 21)
## datetime.datetime(1998, 5, 1, 10, 35, 21, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
## datetime.date(1999, 8, 31)
## datetime.date(2000, 8, 31)
Timezone Conversion (astimezone)
- Use
astimezone(<zoneinfo_timezone>)
to convert a datetime to the desired timezone - When applying this to a timezone naive datetime, the datetime is assumed to be local timezone for conversion. Observe the example below.
= datetime(1997,3,1,10,35,21) ## timezone naive, assumed to be local timezone for conversion
birthday ## convert to NY time
birthday.astimezone(NY)
= datetime(1997,3,1,10,35,21, tzinfo=UTC) ## timezone aware
birthday ## convert to NY time birthday.astimezone(NY)
## datetime.datetime(1997, 2, 28, 21, 35, 21, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
## datetime.datetime(1997, 3, 1, 5, 35, 21, tzinfo=zoneinfo.ZoneInfo(key='America/New_York'))
Convert to String (strftime, isoformat)
Refer this cheatsheet for complete directives.
str( datetime.now() )
'%d-%b-%Y')
datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%fZ') ## ISO 8601 UTC
datetime.utcnow().strftime( datetime.utcnow().isoformat()
## '2022-12-31 12:00:11.743655'
## '31-Dec-2022'
## '2022-12-31T04:00:11.759281Z'
## '2022-12-31T04:00:11.759281'
10.3.6 Instance Attributes
datetime.now().year
datetime.now().month
datetime.now().day
datetime.now().hour datetime.now().minute
## 2022
## 12
## 31
## 12
## 0
10.3.7 Operators
Difference (-)
Use -
to get the difference between two dates as timedelta
object.
= datetime(2000,1,1,10,25,35)
dt1 = datetime(2000,1,2,14,30,55)
dt2
- dt1
dt2 - dt2 dt1
## datetime.timedelta(days=1, seconds=14720)
## datetime.timedelta(days=-2, seconds=71680)
Addition (+)
Adding timedelta
to a datetime to get an adjusted datetime. Note that there can be negative adjustment to any parameters of timedelta.
= timedelta(days=5, hours=-5, minutes=30, seconds=10)
delta = datetime(2000,1,1,10,25,35)
dt1 ## check the delta object
delta ## original datetime
dt1 + timedelta(days=5, hours=-5, minutes=30, seconds=10) ## adjusted datetime dt1
## datetime.timedelta(days=4, seconds=70210)
## datetime.datetime(2000, 1, 1, 10, 25, 35)
## datetime.datetime(2000, 1, 6, 5, 55, 45)
10.4 Time
10.4.1 Constructor
print( time(2) ) ## specify hour only, minutes and seconds default to 0
print( time(2,15) ) ## seconds default to 0
print( time(hour=2,minute=15,second=30) )
## 02:00:00
## 02:15:00
## 02:15:30
10.5 Timedelta
10.5.1 Constructor
- Constructor does not support years argument.
= timedelta(days=365,minutes=33,seconds=15) delt
10.5.2 Using With Datetime
timedelta
can be applied on on datetime object.- Timedelta Cannot be applied on time object , because it potentially go beyond single day (24H).
= datetime.now()
dt1 = timedelta(days=365,minutes=33,seconds=15)
delt
delt
dt1+ delt now
## datetime.timedelta(days=365, seconds=1995)
## datetime.datetime(2022, 12, 31, 12, 0, 14, 748657)
## datetime.datetime(2023, 12, 31, 12, 33, 27, 30434)