Rails age of an article in days? - ruby-on-rails

I need to get the age of the article in days. For example, the article was written on Tue, 01 Apr 2014 18:31:07 EDT -04:00 and now I need the days from that date to now printed as an integer. How can I do so?

Please try something like this:
gem install time_diff
install the gem.
require 'time_diff'
time_diff_components = Time.diff(start_date_time, end_date_time)
time_diff_components[:year], time_diff_components[:month], time_diff_components[:week]
This will give more option.
More detail click

This isn't the cleverest way, but it's probably the simplest: use a "magic number": 86400, which is the number of seconds in a day. (you probably already know there are 3600 seconds in an hour, mentally file this number alongside that)
Differences between Time/DateTime objects will be in seconds (as a float). If you divide this by 86400 you get the difference in days, as a float. You can then call to_i on this to get it as an integer if you want.
eg
((Time.now - #article.created_at)/86400).to_i
It's probably worth saving this as a constant, egs SECONDS_IN_A_DAY or something, to avoid mistyping.

With the Date class you can do
(Date.today - #article.created_at.to_date).to_i
to get the number of days between the two dates.

Related

Time datatype in Rails

I created a database using rails with stime attribute (referring to the starting time). Its type is Time. When I added a record with:
stime = "10:10"
it has been added as:
"stime":"2000-0101T10:10:00.000Z"
I only want the time, not the date. I thought it's the difference between Time and DateTime. Could anyone tell me what the problem is?
As the documentation states, it is not.
Time is an abstraction of dates and times. Time is stored internally
as the number of seconds with fraction since the Epoch, January 1,
1970 00:00 UTC.
There are several things you can do:
Store it as a string and do regex validation.
If you are using Postgres and don't mind depending on it, you can use time type. This would allow you do things like: YourModel.where("stime > '13:00:00'").
Store the time of the day in seconds since midnight. This will require you to add some helper methods for creating and scopes for querying data. You might find ActiveSupport's extension on numeric values helpful.
One way of handling this issue, to exemplify Uzbekjon's third point, is storing the time as seconds since midnight in an integer column:
stime = Time.now
# => 2016-04-13 10:58:13 -0700
seconds = stime.seconds_since_midnight.to_i
# => 39493
You can then retrieve this value and parse it into the time of day when needed:
time = Time.at(seconds).utc
# => 1970-01-01 10:58:13 UTC
result = time.strftime("%I:%M")
# => "10:58"
Hope it helps!

Rails timestamps, See how much time passed since last time

In my app I want to print out the duration of time I spent from I made the model until I updated it.
So if I have the value
:created_at set to 2016-04-13 14:00:49 UTC
and
:updated_at set to 2016-04-13 15:05:49 UTC
I want to print out that it took 1hour and 5minutes. (or just 01.05).
How do I do this?
I'm not sure why this was downvoted, though a little googling would probably have gotten you to the right answer fairly quickly.
What you're looking for is called time_ago_in_words
Here is the doc http://apidock.com/rails/ActionView/Helpers/DateHelper/time_ago_in_words
And usage is:
time_ago_in_words #object.created_at
time_ago_in_words #object.updated_at
If you want to use it the console to play with it, make sure you preface it with helper so it's loaded into console
e.g.
helper.time_ago_in_words #object.created_at
update
For checking between 2 dates, not just one date from right now, then you can use distance_of_time_in_words
distance_of_time_in_words(#object.created_at, #object.updated_at)
That gives words like
12 days ago
If you're ONLY looking for hours, and nothing else then you can use basic subtraction and division
#object.updated_at.to_i - #object.created_at.to_i) / 60 / 60
You can try this
diff =#object.updated_at.to_time.to_i - #object.created_at.to_time.to_i
hour = "#{diff / 3600}:#{(diff % 3600) / 60}"

Why are those two datetimes different?

Why isn't Time.current equal to its parsed equivalent?
current = Time.current
# Wed, 16 Sep 2015 17:10:56 CEST +02:00
parsed = Time.zone.parse('16 Sep 2015 17:10:56')
# Wed, 16 Sep 2015 17:10:56 CEST +02:00
current == parsed
# false <= What ?!
current.to_i == parsed.to_i
# true
Ticket.create(datetime: current)
# ...
Ticket.find_by_datetime(parsed)
# nil <= Why ?!
I'm actually having trouble with this in a Ruby on Rails application where I try to find a record based on a datetime attribute that has been parsed, like shown on the last lines.
I really don't get it. Time zones are the same, times are the same down to seconds. What's happening here?
Moreover, how should I proceed to find a record based on a parsed datetime?
They should not be the same:
current.to_f #=> 1442417032.6567826
parsed.to_f #=> 1442417032.0
When parsing, you miss milliseconds.
Thanks everyone for the help. I hope you don't mind but since pieces of the final answer are scattered across multiple answers I will answer my own question building on what you all said.
So as for why the dates are different, it's because of the milliseconds missing in the parsed datetime. As #dimakura mentioned.
current.to_f #=> 1442417032.6567826
parsed.to_f #=> 1442417032.0
Then the answer about how could we fetch the Ticket record based a the parsed datetime.
First it's important to know this will be relevant only for PostgreSQL (my case) or other databases that actually store milliseconds. Thanks to #sjagr for mentioning this.
So we have to query for a range from parsed to parsed + 1 second, like #Stefan explained:
Ticket.where(datetime: parsed...parsed+1).first
And if we have control on the Ticket creation, we could also remove the millisecond precision before saving the the database. Thanks to #sjagr for providing an easy way to do that.
current = Time.current
Ticket.create(datetime: current.change(usec: 0))
Thanks everyone !
It's because they are not equal, they differ by parts of the second. What you see in the console is the result of inspect method called on those dates, which by default, drop any sub-second parts.

How to convert Evernote API Timestamps to Postgresql Timestamps

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)

Rails 3: Is it possible to access a model's attribute in a query?

Sorry if that question sounds strange, but I'm diving into Rails and I'm still learning the jargon. Basically, I'm trying to create a single-pass query that uses the value of one of the model's attributes in a calculation in the query (assuming that's even possible).
I have a Tournament model that has a start_date attribute that is a DateTime object. I'm trying to create a query that returns all the Tournaments that have a start_date no older than 1 hour + the length of the tournament, or put another way, all tournaments that haven't yet started or have started, but haven't ended longer than an hour ago. My current query, which doesn't work, looks like this...
validTourneys = Tournament.where("start_date > (? - duration_in_mins)", (DateTime.now.utc - 1.hour))
where duration_in_mins is an integer attribute of the Tournament model, but this query doesn't work and it seems to be returning all the Tournaments all the time. I'd like to include duration_in_mins in the (DateTime.now.utc - 1.hour) part of the calculation, but I don't know how to reference it, which is why I included it in the string part of the query, hoping that would work. Am I at least on the right track?
I should mention I'm using SQLite for development and PostgreSQL for production.
Thanks for your wisdom!
The problem is that if you subtract minutes from a DateTime object, you are not subtracting minutes but days.
# This works as expected
dt = DateTime.now # Thu, 28 Apr 2011 09:55:14 +0900
an_hour_ago = dt - 1.hour # Thu, 28 Apr 2011 08:55:14 +0900
# But, this does not...
two_hours_in_minutes = 120
two_hours_ago = dt - two_hours_in_minutes # Wed, 29 Dec 2010 09:55:14 +0900
In the last example 120 days are subtracted instead of minutes. This is probably also happening in your query. You have to convert duration_in_minutes to days and then subtract.
I don't know enough about SQL to answer your question directly (I think this will probably also depend on what database you're using, so you might want to mention that).
Have you considered, though, having start_date and end_date as DateTime columns instead of start_date and duration_in_mins? If this is going to be a common query, that would certainly make it more performant, as well as making your code easier to read and understand.
This query will only work if your database is smart enough to know how to add (what I am assuming) is a DateTime and and integer. And I can't think of a database that will do that correctly the way you have it coded. No database will assume minutes. Some might do ticks, seconds, or days.
This part of the calculation
(? - duration_in_mins)
is going to happen on the database, not in Ruby-land.

Resources