My Django application is changing the timezone when I enter a DateTime value into the MySQL database.
Here's my method which adds the new record to the database:
def add_record(self, mdl, **kwargs):
"""add new data as new record in local db"""
return mdl.objects.create(**kwargs)
This is in the **kwargs:
'timestamp': 2020-09-17T17:50:14.304Z
When the time is entered in the database and I view it via phpMyAdmin it shows the same time as above but with -0400 offset.
The MySQL GLOBAL timezone is showing SYSTEM, which on mine would be 'America/New York'. So, it appears the database is defaulting to this timezone even though I'm passing it a timezone.
Note: I've tried replacing the "Z" with "UTC" or "+00:00" but that doesn't resolve the issue.
Django settings are:
TIME_ZONE = 'UTC'
USE_TZ = True
Note: I tried setting USE_TZ to False but this did not resolve the issue and I was not able to pass any timezone information to the database.
How can I force the database to save the correct timezone?
WORKAROUND:
Was not able to get database to store times in UTC timezone so I ended up using this workaround to modify the time to match the database's default timezone. Here's what I used in case it helps anyone.
Note: Your MySQL timezone tables must be loaded for this to work.
After adding the record, this function fixes the time:
def fix_timezone(self, tm, rid):
sql = "UPDATE data_testdata SET timestamp=CONVERT_TZ('"
sql += tm.replace("T", " ").replace("Z", "")
sql += "', '+00:00', '" + DateTimeFunctions().get_mysql_timezone_offset() + "') "
sql += "WHERE dataPointId=" + str(rid) + ";"
cursor = connection.cursor()
cursor.execute(sql)
transaction.commit()
using this class:
from django.db import connection
from datetime import datetime
from zoneinfo import ZoneInfo
from django.utils.dateformat import time_format
class DateTimeFunctions(object):
"""functions for manipulating dates, times, timezones, etc"""
def __init__(self):
pass
def get_mysql_timezone_offset(self):
"""get the offset (+HH:MM) for the mysql timezone"""
return self.get_timezone_offset_from_name(self.get_mysql_timezone_name())
def get_mysql_timezone_name(self):
"""get the name default timezone for the datbase (session tz, or global tz if no session)"""
cursor = connection.cursor()
cursor.execute("SELECT @@global.time_zone, @@session.time_zone;")
tzglobal, tzsession = cursor.fetchone()
if tzsession == "" or tzsession is None:
tz = tzglobal
else:
tz = tzglobal
if tz == "SYSTEM":
return self.get_mysql_system_timezone_name()
else:
return tz
def get_mysql_system_timezone_name(self):
"""get the name of the mysql system timezone"""
cursor = connection.cursor()
cursor.execute("SELECT @@system_time_zone;")
tzname = cursor.fetchone()
return tzname[0]
def get_timezone_offset_from_name(self, tznm):
tdelta = datetime.now(ZoneInfo(tznm)).utcoffset()
deltaseconds = tdelta.total_seconds()
sign = "-" if deltaseconds < 0 else "+"
deltahrs = str(abs(round(deltaseconds/(60*60))))
if len(deltahrs) == 1:
deltahrs = "0" + deltahrs
deltamin = str(round((deltaseconds % (60*60))))
if len(deltamin) == 1:
deltamin = "0" + deltamin
return sign + deltahrs + ":" + deltamin