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 ZoneInfo10.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'>).
MY = ZoneInfo('Asia/Kuala_Lumpur')
NY = ZoneInfo('America/New_York')
UTC= ZoneInfo('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
date (2000,1,1)
type(date (2000,1,1))
## Datetime - TImezone Naive
datetime (2000,1,1,23,15,55)
datetime (year=2000,month=1,day=1,hour=23,minute=15,second=55)
type(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.
MY = ZoneInfo('Asia/Kuala_Lumpur')
NY = ZoneInfo('America/New_York')
UTC= ZoneInfo('UTC')
## Timezone Aware
datetime (2000,1,1,23,15,55, tzinfo=NY)## 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()supportstzparameter to convert the time to desired timezone. today() / utcnow()** does not supports **tz``` parameter.
datetime.now() ## local datetime
datetime.today() ## local datetime, same as above
datetime.utcnow() ## UTC datetime
datetime.now(tz=NY) ## convert to New York timezone
datetime.today(tz=NY) ## Error
datetime.utcnow(tz=NY) ## Error## 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
now = datetime.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
datetime.strptime('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.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.
datetime.now().isoformat() ## checkout the iso format
datetime.fromisoformat("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'## '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
now = datetime.now(tz=MY) ## initialize the instance
now.month
now.day
now.hour
now.minute
now.tzinfo ## this would be null if TZ parameter not specified## 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.
birthday = datetime(1997,3,1,10,35,21) ## replace for datetime
birthday
birthday.replace(tzinfo=NY, year=1998, month=5)
holiday = date(1999,8,31) ## replace for date
holiday
holiday.replace(year=2000)## 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.
birthday = datetime(1997,3,1,10,35,21) ## timezone naive, assumed to be local timezone for conversion
birthday.astimezone(NY) ## convert to NY time
birthday = datetime(1997,3,1,10,35,21, tzinfo=UTC) ## timezone aware
birthday.astimezone(NY) ## convert to NY time## 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() )
datetime.now().strftime('%d-%b-%Y')
datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ') ## ISO 8601 UTC
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.
dt1 = datetime(2000,1,1,10,25,35)
dt2 = datetime(2000,1,2,14,30,55)
dt2 - dt1
dt1 - dt2## 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.
delta = timedelta(days=5, hours=-5, minutes=30, seconds=10)
dt1 = datetime(2000,1,1,10,25,35)
delta ## check the delta object
dt1 ## original datetime
dt1 + timedelta(days=5, hours=-5, minutes=30, seconds=10) ## adjusted datetime## 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.
delt = timedelta(days=365,minutes=33,seconds=15)10.5.2 Using With Datetime
timedeltacan be applied on on datetime object.- Timedelta Cannot be applied on time object , because it potentially go beyond single day (24H).
dt1 = datetime.now()
delt = timedelta(days=365,minutes=33,seconds=15)
delt
dt1
now + delt## datetime.timedelta(days=365, seconds=1995)
## datetime.datetime(2022, 12, 31, 12, 0, 14, 748657)
## datetime.datetime(2023, 12, 31, 12, 33, 27, 30434)