I have a database created in a Rails application and now I want use this same database in a Phoenix application (using Ecto). The major problem at this time is with datetime values.
The Rails application show me things like this:
Tue, 06 Feb 2018 00:13:36 -02 -02:00
And the Ecto query on the same table show:
[{{2018, 2, 6}, {2, 13, 36, 22082}}]
Note the timezone lost.
The DB is schemaless on phoenix application and this is necessary.
So, I want keep the timezone information and convert the data to a more useful format for calculations.
Is there a way to do this?
Ecto ~ 3.0
Phoenix ~ 1.2.1
Rails ~ 5
Rails does not store time zone data in the database. All datetime values are stored in UTC. When you query a datetime field on an ActiveRecord object, it converts the output to the time zone set in your application.rb file using config.time_zone =.
Related
I read similar questions but did not find a solution.
My Rails 5 App is in
'America/Sao_Paulo'
time zone but saves all times in UTC to the database.
When saving a datetime
'2017-01-01 19:00:00'
to my database it will convert it to UTC and save the UTS time to the database.
Now I need to convert a string to datetime using:
DateTime.strptime(date + ' ' + time, '%d/%m/%Y %H:%M:%S')
And this will take the date and time values as they are and save them to the database without converting to UTC. How can I let my app know that my the datetime is not in UTC yet?
ActiveRecord (by default) will save any datetime to UTC. So, in my opinion you don't need to worry if the time in the database isn't yet in UTC, because ActiveRecord will convert it to UTC.
So, when saving to database, ActiveRecord will always convert it to UTC (whether it is in UTC or not).
And when fetching from database, it follows your configuration in config/application.rb
You can find in the file config.time_zone = 'YOUR_TIMEZONE'.
Reference:
http://api.rubyonrails.org/classes/ActiveRecord/Timestamp.html
Hope it helps, cheers!
My rails application has a Photo model which has a DATETIME column called taken_at.
I'm trying to understand why I get a different timestamp (num of secs since epoch) using the following methods:
Photo.find(3095).taken_at.to_i # => 1307292495
Photo.select("id, UNIX_TIMESTAMP(taken_at) as timestamp").where(:id => 3095).first['timestamp'] # => 1307317695
Photo.find(3095).taken_at.strftime('%s') # => "1307267295"
I'm using MySQL as the database and I'm using rails 4.1.7
thanks!
So the reason that using UNIX_TIMESTAMP(taken_at) in MYSQL gives a different result is because MySQL assumes that taken_at is a date stored in the server's time zone and converts it to an internal value in UTC before making the timestamp calculation. But taken_at isn't a date stored in the server's time zone, it is a date stored in UTC because ActiveRecord stores all datetimes as UTC in the database and then converts them back to the local time zone when you read the record back from the database.
references:
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_utc-timestamp
I have records with a created column whose datetime is stored in UTC.
For instance, this is the datetime stored in one record: 2014-02-01 00:33:25
But if I retrieve that record and confer it to CST, it'd look like this:
Article.find(1).created.in_time_zone('Central Time (US & Canada)') => Fri, 31 Jan 2014 18:33:25 CST -06:00
Which is a different day/month as far as that timezone goes.
The problem I'm having is finding records based on a date. So say I wanted to pull all records for January 31, 2014 (CST). I want to include my example record.
How do I do that in a Rails app? I'm running Rails 4.0.1 and Ruby 2.0.0 with Postgres 9.3.1.0.
Use AT TIME ZONE to change timezone
Article.where("date(created AT TIME ZONE 'UTC' AT TIME ZONE 'CST') = '01/31/2014'")
Got some help outside of SO and got what I was looking for.
Say I wanted to find all records in a date range, this is what it'd be:
Article.where(created: Date.parse("January 1, 2014").in_time_zone('Central Time (US & Canada)').beginning_of_day.utc..Date.parse("January 31, 2014").in_time_zone('Central Time (US & Canada)').end_of_day.utc)
I'm accessing the Evernote API via the evernote gem for ruby on rails, and I'm storing the objects (notebooks, tags, notes, etc.) in a Postgresql database.
Evernote returns timestamps that look like this:
1344141917000
1344141967000
1344138641000
The evernote api documentation says this is the number of milliseconds that have passed since the base time of January 1, 1970, 00:00:00 GMT
I've conducted the following exercise in the rails console in an attempt to reconstruct the date.
evernote_timestamp_base = Time.gm(1970,01,01,00,00,00)
=> 1970-01-01 00:00:00 UTC
evernote_timestamp_base + 1344138641000
=> 44564-01-22 04:43:20 UTC
Definitely not right. But chopping those last three zeros off yields the right date:
evernote_timestamp_base + 1344138641
=> 2012-08-05 03:50:41 UTC
Am I missing something here? What's the deal with those last three zeros? Will I have to parse and chop the evernote timstamp values and then add them to the 1970 base, or is there an easier way?
Also, what's the best Postgresql data type for storing these values?
Thanks in advance for your help.
To do this in Ruby, use Time.at. You'll need to divide by 1000 since Evernote timestamps are in millseconds and Ruby/Unix timestamps are in seconds.
createdNote = noteStore.createNote(authToken, note)
createTime = Time.at(createdNote.created / 1000);
puts "Note was created at #{createTime}"
In postgresql you could use a timestamp [with|without] time zone as the type for the column.
The unix timestamp is defined as the number of seconds since January 1, 1970, 00:00:00 GMT which is what Ruby and many other systems use and or support. PostgreSQL can do the conversion for you to. Just pass the value in seconds to the to_timestamp function.
SELECT to_timestamp(1344138641000/1000.0)
To convert it back use
SELECT EXTRACT(EPOCH FROM col)
I am migrating a Perl-based web application to Rails. The old application stores dates in a MySql database in local (Pacific) time. For example, there is a created field that might have the value 06/06/2008 14:00:00 representing 2:00 PM June 6, 2008 (PDT) whereas 02/02/2002 06:30:00 represents 6:00 AM February 2, 2002 (PST).
I have written a rake task to take all the old data and import it into the new database. The date in the new database still looks like 06/06/2008 14:00:00 but, of course, my Rails application interprets this as UTC.
The migrating task looks like this:
# Migrating old events in Perl application to new events in Rails
oldevents = OldEvent.all
oldevents.each do |oldevent|
newevent = Event.convert_old_event_to_newevent(oldevent)
newevent.save!
end
The interesting code is in the static method Event.convert_old_event_to_newevent:
def Event.convert_old_event_to_newevent(oldevent)
...
# If the "created" field in the old db contains '06/06/2008 14:00:00' (meaning
# 2:00 PM PDT (since June is during daylight savings time) then the
# "created_at" field in the new database will contain the same string which
# Rails interprets as 2:00 PM GMT.
newevent.created_at = oldevent.created
...
return newevent
end
So, in the migration process, before storing the dates in the new database I need to read the date/times from the old database, convert them to UTC, and then store that in the new database.
How can that be done?
>> Time.local(*'06/06/2008 14:00:00'.split(/[:\/ ]/).values_at(2,0,1,3..5)).utc
=> Fri Jun 06 21:00:00 UTC 2008
This obviously returns a Ruby core library Time object that can be formatted any way you like.
If your time zone is not already Pacific, run your rake import task like:
$ TZ=PST rake initdb:import # whatever
Now, Rails defines a type called DateTime which you may need, and it wants real integer parameters, so:
DateTime.civil_from_format :local, *'06/06/2008 14:00:00'.split(/[:\/ ]/).map(&:to_i).values_at(2,0,1,3..5)