negative time difference in mysql - mysql

SELECT * , unix_timestamp( NOW( ) ) - unix_timestamp( created ) AS timedif FROM is_meeting_comments WHERE meeting_id_fk=9
This query is used to find out the time difference between when the record was created (CURRENT TIMESTAMP) and when the select query is executed.
This query is return negatives values on remote PC's. While this problem is not apparent when I first tested on my local server. Is this because of different time zones set? But how would this matter, the time should be the same regardless of any PC because its being calculated from the server end.
Why are negative values occurring?

It's likely that it is negative because of timezone differences. The unix_timestamp function assumes the argument is in a local time zone so it will convert it to UTC as part of its conversion process. If "created" is stored as a local time (non UTF) on a pc in a different timezone (or one with a different timezone configured) then the conversion could be off when read back in on a system in a different timezone.
MYSQL can be configured to allow per-connection timezones (so the timezone is the user's timezone, not the database server's timezone) and this can impact the way dates are stored. Check out this page for more details.

Related

Drawbacks of setting MySQL ##session.time_zone per query instead of CONVERT_TZ?

We are storing MySQL timestamp columns in our database.
We are serving multiple web customers in multiple timezones, we often have to query the data sensitive to their timezone to allow them to use their local times.
Here is an example of an average query in our system:
SELECT * FROM user
WHERE CONVERT_TZ(created_at, ##session.time_zone, 'America/Denver')
BETWEEN '2023-01-01 00:00:00' AND '2023-01-31 23:59:59' <--- These are local denver times provided from the customer so we have to convert from the server timezone.
As you can see, our current solution is to leverage the CONVERT_TZ function to convert from the MySQL server timezone interpretation of the timestamp column into the client's local timezone.
This repetition becomes burdensome on developers and can accidentally be left out of crucial queries. We can often have five or six or more instances of CONVERT_TZ in a single query.
To solve this problem we are thinking about leveraging the fact that timestamps are converted automatically by MySQL to the connection time_zone variable as outlined here: https://dev.mysql.com/doc/refman/8.0/en/datetime.html#:~:text=MySQL%20converts%20TIMESTAMP,Zone%20Support%E2%80%9D.
In theory, setting the MySQL time_zone to our customer's timezone prior to the query would automatically make all of their queries able to their local timezone without additional conversions.
This idea yields the following query:
SET ##session.time_zone = 'America/Denver';
SELECT * FROM user
WHERE created_at <-- No longer have to convert the column, because the MySQL time_zone takes affect.
BETWEEN '2023-01-01 00:00:00' AND '2023-01-31 23:59:59'
SET ##session.time_zone = 'SYSTEM'; <-- Revert back to system.
Are there drawbacks to this approach? Can multiple queries across sessions/connections be impacted by the variables of another? Are there race conditions between multiple queries that might inherit the incorrect variable before completing?
Session variables never "leak" into other sessions. Session variables cannot change while the query is running.
The biggest drawback is that you still have datetime values stored in different timezones. You can change the session timezone so you can search based on a given user's preference, but there are many cases when this makes things hard. Here are a few examples, but there may be many others:
Check which of two users was created first
Sort a set of rows by datetime
Allow one user to query the datetime of another user
Check if multiple users can attend the same meeting
And so on. If you store each user's datetimes according the respective user's preference, then you still need to convert one or the other if you want to compare datetimes.
Another downside of storing datetimes in a user's preferred timezone is what if that user moves to another timezone, and they change their preference? You'd have to update all rows that contain times referenced by that user.
The preferred solution is: store all datetimes in UTC.
(Actually, it doesn't matter which TZ you choose, as long as you are consistent. UTC is just a good neutral choice.)
Then you can compare datetimes, you can sort them, and you don't have to worry about developers forgetting how to convert them properly. Convert the values to UTC on insert, and convert them to the user's current preference when you display query results.

How to query MySQL DATETIIME using UTC?

I have stored DATETIME values in MySQL8 which are all UTC. In my case that is -2h. The Ubuntu 20. Server runs on local time and there is a replica also running on local time.
While doing a cron job I realized that the query never returns results due to the time zone shift:
SELECT *
FROM TABLE
WHERE
r.FOUND >= NOW() - interval 1 minute
How can this query be altered to reflect UTC timezone? I am querying with Python but also within other environments (e.g. Grafana). Also the output should be in the timezone of the user.

How to handle MySQL timezone in script

I am developing a mobile application. From the application calls are made to a web service which runs different queries based on mode (?mode=xx)
In some of those queries I use date functions like DATE(NOW()).
The data stored in the MySQL database is stored in GMT-7 (Mountain Time Canada).
I have yet to register a domain/host for this web service but when I do lets say it is hosted in a different city such as Toronto (which is GMT-5 - 2 hours ahead). Then at 10:05pm Mountain Time Canada a user uses the application to send a web request call which has a query like:
SELECT DATE(NOW())
Because the server is hosted in Toronto, that will return tomorrow's date, even though where the user is it is the day before and the application shows data based on the current day.
Anyone have any ideas on this?
Edit:
SYSTEM
2015-01-29 16:19:48
2015-01-29 23:19:48
is the result of running the query select ##time_zone, now(), utc_timestamp()
The queries deal with date (yyyy-mm-dd) and time (hh:mm:ss) column type.
You ran this time-diagnostic query on your MySQL server.
select ##time_zone, now(), utc_timestamp()
It's clear from your local time and utc time that your server machine's system time zone setting is 'Canada/Mountain', and the MySQL server software doesn't have its own timezone setting.
If you pick up your tables and move them unchanged to a server in some nearby timezone, you can update your software always to issue the command
set time_zone = 'Canada/Mountain';
right after you connect from your software. This will make your new MySQL connection behave like your current one does time-zone-wise. If you own the MySQL server you can set its default time zone according to the directions on this page. http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html
Now, here's the story about time data types. DATE, TIME, and DATETIME are all timezone-ignorant. Once you've stored a date/time value you'll get it back the same value even if you change your timezone settings.
The TIMESTAMP data type is timezone-sensitive. Those data items are always stored in UTC, also known as Z, time, formerly known as Greenwich Mean Time. They're always converted to UTC upon being stored, and always converted back upon being retrieved.
The builtin functions for getting current date and time (NOW() and friends) are timezone-sensitive. They'll yield values in local time. The exceptions are the three functions starting with UTC_ which yield values in UTC time.
Many MySQL multi-time-zone applications use the following operational discipline:
Ask each user for a user-preference time zone, or figure it out from some other bit of personal data about the user. (Telephones have this information provisioned into them from the network.) Store that as a zoneinfo-friendly time zone descriptor ('America/New_York', 'Canada/Mountain', 'Europe/Vienna', etc) on the user's behalf.
Upon establishing a MySQL session on behalf of the user, set the user's time zone with a set time_zone query like the one shown above. You should do this right after your connect operation.
Store dates and times for users into TIMESTAMP data types. They'll get converted to UTC as they're stored.
Retrieve them as needed. They'll get converted back to local time.
The idea is that your user's timezone is part of her context. This works well, because if user A is in Vancouver and user B in Halifax, and for some reason user B views user A's time data, it will be shown to B in Atlantic time more-or-less automatically.
It's also good because it deals transparently with the global vagaries of daylight-to-standard time changing. A timestamp from last summer will be displayed in last summer's local time.
Many managers of servers for global use set their system server time, or their MySQL default time zone, to UTC. (Yours doesn't.)
Another way to handle all this is the way in which you've started. Pick a time zone and store your timestamps with respect to that time zone. It's best if you pick a timezone that doesn't alternate between daylight and standard time in that case. Then, when storing times into the database, convert explicity. You'd store times from users in Ottawa by doing something like this.
INSERT INTO tbl (appt) VALUES ( 'whatever-time' - INTERVAL 120 MINUTE)
and you'd get the values out the same way. This is error-prone but you can make it work.
Finally, you can do your conversions yourself.
If you want to know how many minutes of offset there are between some arbitary timezone and UTC, try these two queries.
set time_zone = 'Canada/Atlantic';
select timestampdiff(minute, utc_timestamp(), now());
At this time of year that gives back -240, which is -4:00. You need to use minutes rather than hours because of half-hour or quarter-hour timezone offsets in some countries.
Finally, watch out. TIMESTAMP data types don't represent times before 1970. And, on my MariaDB 10.0 instance it appears to go to hell in a bucket right after 2038-01-19T03:14:07 UTC when the time rolls over out of 32 bits.

Will changing a MySQL timezone change values of DateTime fields in a database?

I have a MySQL database that is set to a local time zone. Times are inserted as UTC time although the database uses a different time zone. I would like to change the time zone to UTC on the MySQL server. I have found documentation on how to do this, but am reluctant as I do not know if that would also change the values that are already stored in the Database.
My Question: Will changing the time zone of a MySQL server also change the values that are already stored?
In principle it shouldn't. There are various reasons why it shouldn't change, depending on the type of your values : mostly DATETIME and TIMESTAMP.
DATETIME values are never converted, so they are independent of the time zone.
TIMESTAMP values are converted (direct quote from the manual here --- I assume you have a fairly recent version of MySQL) "from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.) By default, the current time zone for each connection is the server's time. The time zone can be set on a per-connection basis. As long as the time zone setting remains constant, you get back the same value you store. If you store a TIMESTAMP value, and then change the time zone and retrieve the value, the retrieved value is different from the value you stored. This occurs because the same time zone was not used for conversion in both directions." (from http://dev.mysql.com/doc/refman/5.5/en/datetime.html).
So in both cases the data actually stored on the server does not change (which is as it should be), but the values that your queries will show may be different before and after.
It depends on whether you are using TIMESTAMP or DATETIME columns to store your timestamps.
TIMESTAMP times are translated automatically from local time (precisely: from the connection's time zone setting) to UTC time when they are stored in tables to MySQL. They're translated from UTC to local time when they are retrieved.
But DATETIME timestamps are stored and retrieved exactly as your application presented them to MySQL. So, if you change your default timezone to UTC and then retrieve your TIMESTAMP values, you'll get them back in UTC. So they will look like they changed. But what has changed is the automatic translation.
Changing the MySQL default timezone does not alter any table contents.
You can experiment with this by issuing the following command when connecting to your MySQL.
SET time_zone = '+0:00';
That will change your connection's time zone setting without changing anything else.
Be careful when reconfiguring a production server that you know what you're doing: You say your "MySQL database ... is set to a local time zone." You need to investigate exactly how that is set up before you change anything. Because here are the settings that can affect things.
(1) the clock setting on the server machine running your MySQL server software.
(2) the timezone setting on that machine.
(3) the default (aka global) timezone setting in your running MySQL server.
In most modern servers the clock is set to the correct UTC time and the timezone setting is set to whatever local timezone your users expect. And, the default timezone setting for your MySQL server is set to that same local timezone. You need to verify that those things are correct.
If your server's time of day flips over automatically and correctly from standard to daylight savings time (yesterday morning in the USA) the first two are probably right.
If you issue this MySQL command: SELECT ##global.time_zone' and get back either your local time zone name orSYSTEMthe third is right. Also issueSELECT NOW()` to double check. If you get the right time of day your system is probably fine. Finally, issue these two commands:
SET time_zone = '+0:00';
SELECT NOW();
If you get the presently correct UTC time from your system, then everything is a known and good state, and you're ready to make the timezone switch.
Make the switch by changing the system_time_zone variable in your MySQL configuration file and restarting your MySQL server. See here for directions:
http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html

How to store datetimes in UTC and local timezone

What is a practical way to store datetimes so that I can let users view/query data as of their own local time while keeping information about the original datetime.
Basically, users want to be able to query (as of their own local time) data collected from systems in various time zones. But occasionally, they want to know that the data was created at, say, 18:00 in the original system. It helps when users from different parts of the world communicate about the same event.
User1: What? We don't have any data for 20:00
User2: Dude, it says 20:00 right there on my screen.
User1: Wait, what timezone are you? What's the UTC-time?
User2: What is UTC? Is that something with computers?
User1: OMFG! *click*
I'm looking for advice on how to store the data.
I'm thinking of storing all datetimes in UTC and adding an additional column containing original timezone name, in a form that lets me use mysql CONVERT_TZ, or the counterpart in Java. The application would then convert dates entered by the user into UTC and I can easily query the database. All dates can also easily be converted to the users local time in the application. Using the original time zone column I also would be able to display the original datetime.
However, this means that for each datetime I have, I need an additional column...
start_time_utc datetime
start_time_tz varchar(64)
end_time_utc datetime
end_time_tz varchar(64)
Am I on the right track here?
Would anyone who have worked with such data share their experiences?
(I will be using MySQL 5.5 CE)
Update 1
Data will be delivered in xml files where each entry has a datetime in some local time zone. So there will only be one inserting process, running in one place.
Once loaded in the database, it will be presented in some web application to users in different time zones. For the majority of the use cases the data of interest did also originate from the same time zone as the user looking at the data. For some of the more complicated use cases, a series of events are interconnected and span multiple time zones. Hence, users want to be able to talk about the events in order to investigate probable causes/consequences in the other's time. Not UTC, not their own local time.
As the users can live in different timezones and even can move from one timezone to other, the best practice is to store the date and time in UTC and convert to user's timezone at the time of displaying.
The manual has a section just for this, about timestamp:
TIMESTAMP values are converted from
the current time zone to UTC for
storage, and converted back from UTC
to the current time zone for
retrieval. (This occurs only for the
TIMESTAMP data type, not for other
types such as DATETIME.) By default,
the current time zone for each
connection is the server's time. The
time zone can be set on a
per-connection basis, as described in
Section 9.6, “MySQL Server Time Zone
Support”. As long as the time zone
setting remains constant, you get back
the same value you store. If you store
a TIMESTAMP value, and then change the
time zone and retrieve the value, the
retrieved value is different from the
value you stored. This occurs because
the same time zone was not used for
conversion in both directions. The
current time zone is available as the
value of the time_zone system
variable.
http://dev.mysql.com/doc/refman/5.5/en/timestamp.html
So you can use: SET time_zone = timezone; on the client to set the time zone. Then all queries would translate the timestamp to the correct time zone. No need to do anything complex in Java, except for setting the time zone (I think might even be a parameter in the JDBC connection string)
You can always get the zulu time as base for all your calculations.