Trouble with time attribute in Ruby on Rails - mysql

I am having this trouble in converting the exiting time string into a new Time object.
When I type this in console
t = Time.parse("8am")
2010-12-06 08:00:00 +0530
it gives back 08:00 as result as seen above.
But when I store this value using
business.start_time = t
business.save(:validate => false)
it stores 02:30 in MySql db.
This happens only when I store via console. When the same data comes from forms, it stores correctly as 08:00 in MySQL table. Is there any problem here. The time zone is set different from the default utc. Please help. what should i do.
I have to parse through all the records in a table and take one string attribute and convert it into its equivalent Time class value and store it in another attribute in the same table. I am writing a rake task for it. But while storing, I get 02:30 instead 08:00 (for example).

Be very careful with dates and MySQL. Datetime fields are stored as if they were strings in the db--so whatever Rails is sending in (check your log for the SQL) is what will be stored. I assume you're set to UTC in your environment.rb, so your Time object is being output in UTC as a string.
MySQL is poor (in my opinion) with respect to handling times in different zones and converting between zones.
I recommend you don't rush through your date handling. Always handle dates in your application and DB in UTC, and do any conversion to a specific timezone on a parsing (by specifying the timezone) or by formatting it in the view.

The time seems to be stored in UTC. Try setting the timezone correctly when starting your console session.

Related

How to use Angular date pipe to convert a date coming from server formatted as local time but actually in UTC?

I am getting data back from server like 2020-02-17 15:36:47 (with no time zone descriptor). This is a date that is generated BY the server and is actually in UTC time (the server's "local" time). However, it is stored as DateTime in MySQL without time zone information.
When I get this back from the server, I need to convert it to local time, but when I try to apply date pipe like dateVariable | date: 'short' : 'UTC' it actually adds time rather than takes it away (my local time is EST) - so I get 2/17/20, 8:36 PM where it should actually be 2/17/20, 10:36 AM.
I guess ths issue is that the client assumes the time coming from the server is already local time, and my pipe is converting it to UTC. In fact, I want to do the opposite - the server time is stored as UTC (even though it is not indicated as such in MySQL DateTime column), and I want to convert to EST (local) using the date pipe. I've searched about and not sure how to handle this outside of modifying what the server returns.

Time on server with Rails

So ... I inserted an entry into a table with time stamps. The entry got inserted perfectly.
But the time stamp that got inserted was :
'2015-06-22 10:32:47'
I checked the time on the server:
Tue Jun 23 01:35:41 IST 2015
And inside mysql :
select now();
2015-06-23 01:33:57
So I check the time in irb.
time = Time.now
=> 2015-06-23 01:36:41 +0530
time.zone
=> "IST"
The time zone is right .. but I dont know where is it picking up the time from? I cant figure out where is it picking up 10:32 from ? and how do I fix it ?
Appreciate all your help.
Rails by design converts a datetime into UTC before inserting the value into the database.
This is because, in general, it's not possible to easily represent timezones in the database. Moreover, this approach guarantees the date will be consistent and/or easy to query in the following cases:
if the server time zone changes or you change server with a different timezone
if you want to query the date using a different timezone
if you want to format the date with different time zones depending on the user or other configs
You can customize the default timezone for the app, so that Rails will properly compute the correct difference to UTC when the value is stored into the database. However, you cannot change this behavior: times will always be converted into UTC before being stored in the database.
Generally speaking, if you properly use the Rails date transformation helpers, this shouldn't cause any issue.
For instance, if you want to query all the records where the time is past, the following query
Record.where('some_date < ?', Time.current)
will properly convert Time.current from your app timezone into UTC, and query the database accordingly.

Convert MySQL times tamp column from one timezone to another

Need some ideas on how to convert an entire database TIMESTAMP columns from one timezone to another.
The current server is UTC, MySQL is also UTC so everything is good in that area. All time related columns are TIMESTAMPs. The problem is that when the time information was being entered, they were in EST/EDT. For example, enter start time: data is 1/1/2011 08:00:00 AM (EST/EDT). Because timezone wasn't implemented at the start, the database stored this as 08:00:00 UTC. So all the data in the database is stored like this. Once we get data that requires timezone info, this model will break.
The question is: how do you convert all these TIMESTAMP columns into the correct UTC time? The code will be changed to deal with this on the display side on a go-forward basis but what about historic data?
The simplest way seems to do a mysqldump --tz-utc of some sort and then import the data back, then release the code. However, I can't seem to find a good example of how to do this properly or if there are other ways to do this in the most efficient way possible.
Thanks!
Could you use the MySQL AddTime function to update the existing data?
UPDATE MyTable SET MyTimeColumn = ADDTIME (MyTimeColumn, -8:00:00) WHERE <the data is bad>

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

MySQL and international dates

Say I have multiple servers in multiple locations and I want to use MySQL's datetime type for the field date and I always want to have the field date have the UTC timestamp so I would execute a UTC_TIMESTAMP() when I add it to the database. Now say I want to have MySQL output the UNIX TIMESTAMP for it.
When I do this on Server A I get the string "2009-06-17 12:00:00" doing the UNIX_TIMESTAMP(STRING) on it gives me the number 1245240000 back. Which is 2009-06-17 12:00:00 in UTC time. Now I do the same thing on Server B.
I get the same string back since its the UTC string but when executing UNIX_TIMESTAMP(STRING) again I get back the wrong number back 1245232800 which is the UTC +2 time. How do I get around this? Should I do the convertion from string to timestamp on the PHP side?
G'day,
I'll ask the obvious here, did you check the date and time on both machines?
Edit: ... and the MySQL timezone was the same on both machines?
Update: Ok. The problem is in the fact that the timestamp string being passed into UNIX_TIMESTAMP is interpreted to be a value in the current timezone which is then converted back to UTC so, because you're in MEZ, two hours is subtracted to return it back to UTC so 7200 is subtracted from your timestamp when it is converted back to a Unix timestring.
Hence, the variation you see when using UNIX_TIMESTAMP() to convert is back to a Unix Epoch timestring.
BTW Shouldn't you be using a TIMESTAMP type for storing off your UTC_TIMESTAMPs instead of DATETIME type?
Update: Decoupling presentation time from stored time is definitely the way to go. You can then reuse the same data all around the world and only have to convert to and from local time when you are presenting the data to a user.
If you don't do this then you are going to have to store off the timezone when the timestamp was made and then go into all sorts of complicated permutations of having to work out if
the local timezone was in daylight saving time when it was stored,
what the difference is between the timezone at the time that the data was stored and the timezone where the data is to be presented.
Leaving it all storeed as UTC gets rid of that.
Most users won't be that happy if they have to work out the local time themselves based on the UTC time returned so systems usually convert to current local time for the user.
This is of course if the user wants the data expressed in local time which is usually the case. The only widely used system I can think of, off the top of my head, that stores and presents its data in UTC is system for air traffic control and flight plan management which are always kept in UTC (or ZULU time to be more precise).
HTH
cheers,
Have you tried doing this?
Execute this instructions together.
SET time_zone = 'UTC';
SELECT FROM_UNIXTIME(0), UNIX_TIMESTAMP('2009-06-17 12:00:00');
// 1970-01-01 00:00:00 1245240000
They only affect the client session, not the server configuration.