MySQL DEFAULT CURRENT_TIMESTAMP doesn't work with timezones? - mysql

I'm having a bizarre issue with my local MySQL server. I have a table with a created_at timestamp column set to CURRENT_TIMESTAMP by default. Everything I've read indicates that this should store the time in UTC, then convert it back to local time for display. However, it's not working right. I'm not sure if it's screwing up on the display or what, but when I read the timestamps out, it's giving me the GMT times instead of adjusting for my local timezone. This wouldn't be as big of an issue, except that NOW() is giving me local time, so I can't compare them properly. I feel like I'm probably missing something stupid, but what's going on here?
If it matters, I'm running MySQL 5.5.24 under 64-bit Windows 8 (unfortunately).
Edit:
Poking at it some more has revealed that the timestamps are working fine when I add rows manually; it's just the rows coming from my PHP that are screwy. I guess the PHP connection must be overriding the default timezone for some reason.

Have you loaded time zone data?
http://www.geeksengine.com/article/populate-time-zone-data-for-mysql.html

Ah-hah! My PHP server and my MySQL server were using different timezones. Needed to go add date.timezone = America/New_York to my php.ini file.

Related

Setting MySQL time zone at runtime with Perl DBIx

I have a Perl Catalyst app that store some times in a MySQL database. The times are of type TIMESTAMP and initialized with NOW().
When reading back the times they appear to be in the databases default time zone. However when using the mysql shell I can easily set the time zone by SET time_zone = '+03:00'; and get the correct local time for my time zone.
Is there a way to set the time one like this in Catalyst or DBIx at run time?
I want to be able to support different time zones, for different users, so just changing the default time zone for the database is not enough. I am also aware that I can format the time in Perl after I get the data from MySQL, but there is so much automation going on with Catalyst, DBIx and Template Toolkit so getting the data correctly from the database to start with would be so much more convenient.
My general advise is to set the datetime in your application, not rely on the datetime of the database server. If you don't need to know which timezone a datetime had when it was set you should store it in UTC. If you need to know the timezone later you need to use a database datatype which supports this like 'timestamp with timezone' in Oracle.
See my answer for Formatting timestamp field for output in TemplateToolkit which seems to be what you're asking.

Set MySQL database timezone to GMT

I need to change the timezone of a single database is this possible?
I know we can change the timezone within our WHM (we are using a dedicated server from hostgator), however a large number of legacy software running on the server has a lot of +6 hours coding in it (i.e. server timezone is CST, we wanted the time in GMT so previous developers altered date/times manually within the code - bad!).
I am now working on a new software and would like to have it all in GMT, I know I can use date_default_timezone_set('GMT') however that will not solve MySQL inserts where the datetime column is set to CURRENT_TIMESTAMP as it will insert # CST timezone.
No, it's not possible to change the timezone for a single database within a MySQL instance.
We can retrieve the server and client time_zone settings with a query, like this:
SELECT ##global.time_zone, ##session.time_zone;
We can also change the client timezone for a session, or change the timezone for the entire MySQL instance.
But we need to be keenly aware of the implication that this change will have on existing client connections, and the how DATETIME and TIMESTAMP values already stored in the instance will be interpreted.
To have the server time_zone set at MySQL instance startup, we can modify the /etc/my.cnf file (or wherever the mysql instance initialization parameters are read from), under the [mysqld] section:
[mysqld]
default-time-zone='+00:00'
-- or --
It is also possible (less desirable) to add the --default_time_zone='+00:00' option to mysqld_safe
NOTE: Changing the timezone setting on the MySQL server does NOT change the values stored in existing DATETIME or TIMESTAMP columns, BUT since it does effectively change the context in which those stored values are interpreted, it will look like all of the values ARE shifted. (Where 08:00 was taken to mean 8AM CST, with the time_zone of the server changed from CST to GMT, that same '08:00' will now be taken to be 8AM GMT, which would effectively be 2AM CST.
Also keep in mind that TIMESTAMP columns are always stored in UTC, while DATETIME columns do not have a timezone.
http://dev.mysql.com/doc/refman/5.5/en/datetime.html
Each client session can change the timezone setting for their own session:
SET time_zone='-06:00';
But none of this really "solves" the timezone conversion problem, it just moves the conversion problem around.
There's nothing inherently "bad" with the application layer handling timezone conversions; sometimes, that's the best place to handle. It just has to be done correctly and consistently.
(What's odd about the setup you describe is that the app is storing DATETIME values as if the MySQL server time_zone is set to GMT, but the MySQL server time_zone is set to something else.)
If you can't change your current time zone you can change the result.
date 2015-01-05 12:06:16
Select date + Interval 2 Hour 'date' From ExampleTable
date 2015-01-05 14:06:16
You can modify the the default value instead of entering current_timestamp make it insert current_timestamp added to hours offset of your timezone. I just did it this way when didn't found any solution, had to invent my own.

MYSQL wrong time.now

We got a Rails 3 Server based on Ruby 1.9.2 running on a MYSQL DB and Problems with the time.now and time.zone.now setting.
For better explaination we assuse its 13:00 UTC right now.
Ubuntu Systemtime is set to 15:00 UTC +02:00 (Thats CEST (Central European Summertime) and is correct for our Timezone).
The Rails time (time.now) is set to 13:00 +0200
the time.zone.now is set to CEST
MYSQL Global time and Session time are both set to SYSTEM
now we create a new entry in the MYSQL DB (via activerecord) which has a timestamp.
but when we look at the timestemp its -2 hours offset to the current server time (in our example 11:00)
We tried setting the time.zone to a very different one for testing propose, it had absolutly no effect on a new mysql entry.
Also we tried to set the mysql global time and session time to UTC, no effect.
The only thing we can imagene right now what could be the problem is that the time.now is taking effect on the mysql entry and is set wrong. Problem here: we're unable to set the time.now setting. But even if that would be possible somehow (is it?), dunno if that fixes the problem.
Did anyone ever have such a problem or any ideas what could cause it?
There are two things to configure for rails.
The current timezone which you've done (used in Time.zone.now), this sets the timezone for timestamps in the instantiated records you load.
The timezone that those values are converted to when stored to the db. This should be set to the same timezone as your system/mysql.
I think this option is configured via: ActiveRecord::Base.default_timezone = :utc
Since your system time is set to CEST, you'll want to use the same value for that as well.
The reason there are two config options is incase you've got users in multiple timezones (international audience), then Time.zone can be set differently for each logged in user, and the db timezone will convert correctly to the Time.zone timezone.

grails/mysql timezone change

Whats the best way to accomplish changing the timezone of an app? The way I see it the following must occur:
Server TZ is changed by sys admin
mysql must be restarted.
every time based column in the database must have all values updated, using convert_tz or equivalent. So either a mysql script must be written or a grails script that loads every row for each class, updating all the time fields.
Obviously the server should be taken down while this is happening, and backups must be in place incase of an error.
Is there a better/easier way to do this?
Java does not use time zones when using Dates; it stores everything as UTC and only uses time zones when displaying dates. see the following link for a discussion of java date/time.
http://www.odi.ch/prog/design/datetime.php
If you're using the Date, Time, or DateTime column types in MySQL, time zone does not matter.
If you’re using the TIMESTAMP column type, time zones may matter since the TIMESTAMP is stored as a UTC but has conversion done when both retrieving and storing the values. For a discussion of MySQL time zone behavior see
http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html .
If you’re worried about synchronizing objects across multiple servers in different time zones things get more complicated, see the following thread for a discussion of this.
http://www.pubbs.net/201006/grails/2500-grails-user-how-to-get-gorm-to-store-dates-as-timestamp-in-utc-by-default-without-a-custom-hibernate-mapping-or-joda-time-plu.html
I know this is an old question but I think it's also pretty timeless... at least, I have stumbled upon it a fair number of times recently... so I thought I would contribute my solution.
First, I am using Grails 2.5.1 and PostgreSQL 9.4 as the backend.
Second, Date fields in Groovy/Grails are stored as timestamp without time zone in PostgreSQL. So it seems to me the first answer above is not actually fully correct - the date is not stored in UTC. This observation got me thinking... along the lines of "well if the database doesn't know what the timezone is, who does"? And the first answer that came to mind was "maybe it's Spring".
Third, the specifics of my problem is that I have a lot of dates that I bootstrapped into the database via BootStrap.groovy and new ThisClass().save(). And because these were dates, not dates + times, they all look like 2005-11-03 00:00:00 as PostgreSQL timestamps (without timezones).
Fourth, what really made the penny drop was when I edited one of my GSPs to include the timezone in the date format string, which showed up as PST (where my server is); and when I included timeZone="Asia/Kolkata" in the g:formatDate of the field in question, the time advanced by 12h30. So pretty clearly my server was running in PST8PDT and since that wasn't PostgreSQL I came back to Spring as the potential place to change things.
Fifth, after reading a few comments about setting the locale in grails-app/conf/spring/resources.groovy I decided to try setting the locale and timezone there, as per:
// Place your Spring DSL code here
beans = {
// from http://stackoverflow.com/questions/1569446/grails-how-to-change-the-current-locale
localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
defaultLocale = new Locale("en","IN")
java.util.Locale.setDefault(defaultLocale)
println "configure spring/resources.groovy defaultLocale $defaultLocale"
defaultTimeZone = TimeZone.getTimeZone("Asia/Kolkata")
java.util.TimeZone.setDefault(defaultTimeZone)
println "configure spring/resources.groovy defaultTimeZone $defaultTimeZone"
}
}
I also used g:format timezone="Asia/Kolkata" format="dd MMM, yyyy a z" for all my date fields. And that seems to interpret all data in PostgreSQL timestamp fields in the correct timezone and at the anticipated hour (ie the hour that was entered), even though the dates were first entered "in the wrong time zone".
Sixth, g:datePicker - I read a number of posts about making this "time zone sensitive", but I found that its dates are interpreted as in the timezone used by Spring and so in my case, this is exactly what I need. Conversely, if someone wanted to enter dates in their locale and have Spring convert them on the fly to the server's time zone, I guess that would require some extra effort.
Personally I think it would be really cool if g:datePicker accepted timeZone as a parameter and used it in the same way g:formatDate does.
We had problems with time differences between using GORM and using groovy.sql.Sql (for quicker data import).
GORM was using the grails config timezone (UTC) that we set in the Bootstrap, but groovy sql was using the default system timezone (GMT).
The problem was solved by setting the timezone in the $JAVA_OPTS, although you could add the switch to grails opts or to the run-app command.
grails -Duser.timezone=UTC run-app

How to set MySQL to use GMT in Windows and Linux

I'm just trying to get MySQL to store time in GMT...
I've read the documentation here: http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html
It says to set: default-time-zone='timezone' in an option file.
However, I've googled for several different terms and cannot find possible values "timezone" is supposed to be. I also don't know where in my.ini (and in Linux, my.cnf) to put this directive. Below [msyqld] ?
Go to [mysqld] section of your my.ini file and under that section enter this line
default-time-zone = '+00:00'
'+00:00' indicates the offset from GMT which in your case will be 0. Please note the '+' sign in the string.
You don't need to install any timezone tables for your problem. After restarting the server, your server will operate in the UTC timezone and hence NOW() will give you the time in GMT.
By default, MySQL is set to your SYSTEM timezone ie. your server timezone is same as your system timezone. So you could also change your system time zone to solve your problem, though this is not recommendable.
Just to save a few clicks, the list of zone names is shown like this:
select name from mysql.time_zone_name;
Beware of setting a fixed-offset zone such as 'GMT' or '+00:00' since it will not alter to match local time / DST etc. If you want it to follow local time, set the zone to 'Europe/London' instead. If you don't want that I'd go for UTC over GMT anyway.
The MySQL Timezone table is not loaded by default, which might be why you're experiencing difficulties. You need to load the timezone table and then set your timezone using the instructions above.
I use this for GMT+2:
SET GLOBAL time_zone = '+02:00';
Screw this... DATETIME, although much easier on the eye when viewing tables, isn't worth this nightmare.
I'm just going to use TIMESTAMP.
Yes, that's a server option for mysqld, and so should be put in the [mysqld] section.
Also, regarding values, see The Definitive Guide to MySQL 5