python & django timezone usage

Django Timezone

In production, there are multiple time zones, users are more likely to stay in different time zones, if the website is desgined for users in multiple time zones and only use standard time, there will be a deviation in calculation.

To solve the problems like this, using the UTC stanard time in code and database, and it is a good choice to use local time only when interacting with front end users.

Django disabled time zone support by default, you can set USE_TZ = True to enable time zone support in settings. It is best to install the pytz module (pip install pytz) at the same time.

Usage of pytz package

The datetime object for type of Naive and Aware

Python datetime.datetime object has a attribute called tzinfo, it’s used for storing timezone infos. You can use is_aware() and is_naive() methods to check what kind of datetime object is. django.utils.timezone.is_aware()

Using django native datetime object to store local time when django timezone disabled:

1
2
import datetime
now = datetime.datetime.now()

Using django aware datetime object to store local time when django timezone enabled:

1
2
from django.utils import timezone
now = timezone.now() # datetime.datetime(2019, 6, 17, 8, 36, 22, 292901, tzinfo=<UTC>)

Timezone between Django and Python

  1. Django Timezone
1
2
3
from django.utils import timezone
now = timezone.now() # datetime.datetime(2019, 6, 17, 8, 36, 22, 292901, tzinfo=<UTC>)
new = timezone.localtime(now) # datetime.datetime(2019, 6, 17, 16, 36, 22, 292901, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
  1. Python Timezone
1
2
3
4
import datetime
import pytz
now = datetime.datetime.now() # datetime.datetime(2019, 6, 17, 16, 39, 5, 65823)
new = now.replace(tzinfo=(pytz.timezone('Asia/Shanghai'))) # datetime.datetime(2019, 6, 17, 16, 39, 5, 65823, tzinfo=<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>)

Python time/datetime

time module

time module that provides various of time function

Generally there are two ways to express the time:

  1. Timestamp, offset in seconds relative to 1970.1.1 00:00:00, timestamp is unique
1
2
import time
time.time() # 1560762051.8676867
  1. Array, which is struct_time, the struct_time of the same timestamp will be different depending on the time zone
1
time.localtime()  # time.struct_time(tm_year=2019, tm_mon=6, tm_mday=17, tm_hour=17, tm_min=1, tm_sec=4, tm_wday=0, tm_yday=168, tm_isdst=0)

Using gmtime() and mktime() methods to convert two kind of time

1
2
time.gmtime(time.time())  # time.struct_time(tm_year=2019, tm_mon=6, tm_mday=17, tm_hour=9, tm_min=1, tm_sec=22, tm_wday=0, tm_yday=168, tm_isdst=0)
time.mktime(time.localtime()) # 1560762097.0

Convert the types between struct_time and string

1
2
time1 = time.strftime("%Y-%m-%d",time.localtime())  # '2019-06-17'
time2 = time.strptime(time1,"%Y-%m-%d") # time.struct_time(tm_year=2019, tm_mon=6, tm_mday=17, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=168, tm_isdst=-1)

datetime module

datetime module provide multiple functions to handle date and time

The classes defined in datetime module:

  • datetime.date: An idealized naive date, Attributes: year, month, and day.;
  • datetime.time: An idealized time, Attributes: hour, minute, second, microsecond, and tzinfo;
  • datetime.datetime: Combination of date and time. Attributes: year, month, day, hour, minute, second, microsecond, and tzinfo;
  • datetime.timedelta: A duration expressing the difference between two date, time, or datetime instances to microsecond resolution;
  • datetime.tzinfo: Class for time zone information objects;
  • datetime.timezone: A class that implements the tzinfo abstract base class as a fixed offset from the UTC;
1
2
import datetime
datetime.datetime.now() # datetime.datetime(2019, 6, 17, 17, 14, 20, 575740)

Convert the types between datetime and string

1
2
today1 = datetime.datetime.now().strftime("%Y-%m-%d")  # '2019-06-17'
today2 = datetime.datetime.strptime(today,"%Y-%m-%d") # datetime.datetime(2019, 6, 17, 0, 0)

timedelta Objects:

class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

1
2
3
4
5
duration = datetime.timedelta(days=1)  # datetime.timedelta(1)
now = datetime.datetime.now() # datetime.datetime(2019, 6, 17, 17, 22, 17, 222917)
tomorrow = now + duration # datetime.datetime(2019, 6, 18, 17, 22, 17, 222917)
yesterday = now - duration # datetime.datetime(2019, 6, 16, 17, 22, 17, 222917)
duration2 = tomorrow - yesterday # datetime.timedelta(2)

Conversion between time and datetime

1
datetime.datetime.fromtimestamp(time.time())  # datetime.datetime(2019, 6, 17, 17, 24, 35, 111480)

A reference of all the legal format codes:

Directive Description Example
%a Weekday, short version Wed
%A Weekday, full version Wednesday
%w Weekday as a number 0-6, 0 is Sunday 3
%d Day of month 01-31 31
%b Month name, short version Dec
%B Month name, full version December
%m Month as a number 01-12 12
%y Year, short version, without century 18
%Y Year, full version 2018
%H Hour 00-23 17
%I Hour 00-12 05
%p AM/PM PM
%M Minute 00-59 41
%S Second 00-59 08
%f Microsecond 000000-999999 548513
%z UTC offset +0100
%Z Timezone CST
%j Day number of year 001-366 365
%U Week number of year, Sunday as the first day of week, 00-53 52
%W Week number of year, Monday as the first day of week, 00-53 52
%c Local version of date and time Mon Dec 31 17:41:00 2018
%x Local version of date 12/31/18
%X Local version of time 17:41:00
%% A % character %