Django querying against external database with different timezone - mysql

I have a Django API application running on postgres with TIME_ZONE='America/New_York' and USE_TZ = True.
For a daily report, I need to query another database, MySQL, and compare records from the postgres DB to check for some updates. They should contain the same number of results. The MySQL DB's timezone is UTC however. How can I perform SELECT queries against the MySQL DB to have it match the same date range on my postgres DB?
Example:
These two queries should return the same number of results
# Django/Postgres with TIME_ZONE='America/New_York'`
MyObject.objects.filter(created_on__date=date(2016, 9, 17))
# External MySQL Databse in UTC
sql.execute('SELECT * from MY_TABLE where created_on BETWEEN "2016-09-17" AND "2016-09-18"')

What you need is to convert the date in MySQL to match America/New_York time zone.
The function to achieve that would be CONVERT_TZ() and since you need named time zone first you need to set up time zone tables.
If you are uncertain whether named time zones are available issue below query - if it returns zero the table is empty so using named time zones is unavailable and you need to populate them (I've mentioned a link to documentation above).
SELECT COUNT(*) FROM mysql.time_zone_name;
mysql_tzinfo_to_sql is used to populate time zones tables.
If your time zone is not a moving one then you can go with less safe, hardcored approach (not recommended) by explicitly typing the time difference like so:
mysql> SELECT CONVERT_TZ('2016-09-17 10:00:00','+00:00','+06:00');
-> '2016-09-17 16:00:00' -- Result

Related

How to export data from Cloud SQL to BigQuery on a daily basis?

I have created a connection to Cloud SQL and used EXTERNAL_QUERY() to export the data to Bigquery. My problem is that I do not know a computationally efficient way to export a new days data since the Cloud SQL table is not partitioned; however, it does have a date column date_field but it is of the datatype char.
I have tried running the following query with the view of scheduling a similar type so that it inserts the results: SELECT * FROM EXTERNAL_QUERY("connection", "SELECT period FROM table where date_field = cast(current_date() as char);") but it takes very long to run, whereas: SELECT * FROM EXTERNAL_QUERY("connection", "SELECT period FROM table where date_field = '2020-03-20';") is almost instant.
Firstly, it’s highly recommended to convert the ‘date_field’ column to the datatype DATE. This would improve simplicity and performance in the future.
When comparing two strings, MySQL will make use of indexes to speed up the queries. This is executed successfully when defining the string as ‘2020-03-20’ for example. When casting the current date to a string, it’s possible that the characters set used in the comparison aren’t the same, so indexes can’t be used.
You may want to check the characters set once current_datetime has been casted compared to the values in the ‘date_field’ column. You could then use this command instead of cast:
CONVERT(current_date() USING enter_char_sets_here)
Here is the documentation for the different casting functions.

Convert timezone for all MySQL queries for a specific user

I work on an existing project that stores dates to a MySQL DB. The dates are stored as UTC since all users so far were in GTM+0 and no conversion was needed.
I now need to modify the code so that users from other time zones can use the system. The users choose their timezone when they register to the system, so I have a table holding the timezone for each user.
I know I can use CONVERT_TZ() when I extract and store the dates, but to do so means to go through all the queries and add this function.
When I do:
SET ##session.time_zone:='+7:00';
select now();
The result changes with the timezone variable.
When I do:
SET ##session.time_zone:='+7:00';
select myDate from myTable;
The result stays the same, returning what is stored in the DB.
Is there any way I can change the connection string or is there a session variable I can use that will affect the queries without having to add CONVERT_TZ to every single query?
Edit: this is not a duplicate of Should I use field 'datetime' or 'timestamp'? since using timestamp means I need to change all the date field in the DB, while I try to change something more global so I will not have to do massive changes the Db fields or the code.

Is there any timezone attached with datetime in MySQL?

Is there any timezone attached (like metadata) with every datetime field values in MySQL? Or every dates are independent of timezone?
Is there any timezone attached (like metadata) with every datetime field values in MySQL?
No, there is no timezone stored in DB with every date (like metadata). MySQL, by default, takes the timezone of the server for all stored dates.
To find out what it is try to run this in the shell
mysql> SELECT ##global.time_zone, ##session.time_zone;
Now as you can see there are always these 2 timezones for the serve
Global(for all mysql connections)
Session - local to the connection
Go through this Stackoverflow question to read more about this.
Also this question to read how to change/set it

convert_tz returns null even after loading time zone tables

I have a MySQL database (hosted on Ubuntu) that has a table with a time zone. This date is in the UTC time zone. I have an application that is using this data but needs to convert the time from UTC to PST to display the data in a useful format.
This can probably be changed on the application level, but I don't have the time to do that currently, so what I want to do is use convert_tz to get the correct time zone until I have time to change the application to convert the time zone.
However, whenever I do something like
SELECT id,
category,
convert_tz(create_datetime, 'UTC', 'PST') as create_datetime
FROM table
I get a result like
1, category, NULL
I know that I need to load the time zone tables, so I did, running this command:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
After that I restarted the mysql service. However, convert_tz still returns NULL. Can someone give me a hand?
Thanks!
Make sure that your create_datetime colum is of type TIMESTAMP.
Please refer to the official MySQL Reference Manual:
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_convert-tz
Example:
SELECT CONVERT_TZ('2004-01-01 12:00:00', 'GMT', 'MET');
When I had this problem it was because I used the wrong time zone name. I incorrectly inferred from the time zone used in the example in the MySQL documentation, MET, that 3-letter US time zones such as PST would work. That's not the case: US time zones are named 'PST8PDT' and the like. So whereas
select convert_tz('2016-10-16 06:23:00', 'UTC', 'PST');
returns NULL,
select convert_tz('2016-10-16 06:23:00', 'UTC', 'PST8PDT');
returns the converted time.
You can see the time zone names in your MySQL instance with
select Name from mysql.time_zone_name;

Mysql: Set time_zone for select queries, UTC for everything else

Is it possible to configure MySQL (at runtime) to use UTC for all write queries, but another timezone for all SELECT queries?
I'm storing all dates in UTC (additionally, the app will always pass UTC datetimes to MySQL) and have MySQL configured to be running in UTC (using SET time_zone = '+0:00'); but is there a way for it to automatically translate all SELECT into another timezone?
I realise I can do this in code, but if I can make MySQL do the job for me that'd be much easier.
To be clear: I'd also like to just run a command once, not use any of the date/time formatting functions for each query.
User CONVERT_TZ() in mysql function
SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');
Ref : http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_convert-tz