Calculating exact duration time from a DateTime column in Postgres using Rails - ruby-on-rails

I am trying to get a more accurate output than "about 2 hours" for duration time.
Currently, we are using time_ago_in_words
This looks like the below function in .erb
Duration: <%= time_ago_in_words(#sitrep.incident.created_at) %>
# I found the gem `dotiw` which lets me use:
distance_of_time_in_words(#sitrep.incident.created_at)
# However, there is an error and I can't get either to work in irb
This is my console output when attempting both. All help is appreciated
[1] pry(main)> include ActionView::Helpers
=> Object
[2] pry(main)> t = Sitrep.last.incident.created_at
# redacted output
=> Wed, 28 Nov 2018 21:47:45 UTC +00:00
[3] pry(main)> t
=> Wed, 28 Nov 2018 21:47:45 UTC +00:00
[4] pry(main)> time_ago_in_words(t)
=> "<span class=\"translation_missing\" title=\"translation missing: en.weeks\">Weeks</span>, <span class=\"translation_missing\" title=\"translation missing: en.days\">Days</span>, <span class=\"translation_missing\" title=\"translation missing: en.hours\">Hours</span>, and <span class=\"translation_missing\" title=\"translation missing: en.minutes\">Minutes</span>"
[5] pry(main)> distance_of_time_in_words(t)
NoMethodError: undefined method `seconds' for Wed, 28 Nov 2018 21:47:45 UTC +00:00:Time
Did you mean? send
Did you mean? send
from /Users/mmowris/.rbenv/versions/2.3.8/lib/ruby/gems/2.3.0/gems/activesupport-4.2.7.1/lib/active_support/time_with_zone.rb:371:in `method_missing'
[6] pry(main)>
The first method, time_ago_in_words works for our rails app. This .erb file sends an email, and the output would look something like:
Duration: about 2 hours
Any ideas on how to proceed? Why does this work in our rails project, but not irb? Why can't I get dotiw to work with the same input? Why can't i get taiw to work with the same input that works in production?
Thanks!

use the helper instead of including the helpers manually
> helper.time_ago_in_words(2.hours.ago, true)
=> "2 hours"
> helper.time_ago_in_words((2.hours.ago + 5.seconds), true)
=> "1 hour, 59 minutes, and 55 seconds"

Related

Why does Date.strptime not throw ArgumentError in rails console

In my local rails console passing 9/31/2011 returns 10/1/2011
[1] pry(main)> Date.strptime("09/31/2011", '%m/%d/%Y')
=> Sat, 01 Oct 2011
In heroku console it throws an ArgumentError:
irb(main):002:0> Date.strptime("09/31/2011", '%m/%d/%Y')
ArgumentError: invalid date
from (irb):2:in `strptime'
Double check that your Gemfile dev dependencies don't include something that could mess with Date's strptime function.
For example, the Timecop gem sets an alias for Date.strptime to this method:
https://www.rubydoc.info/gems/timecop/Date.strptime_with_mock_date
Which just ends up calling Time.strptime(str, fmt).to_date.
This behavior looks very similar to what you reported:
irb(main):001:0> Date.strptime("09/31/2011", '%m/%d/%Y')
ArgumentError: invalid date
from (irb):1:in 'strptime'
irb(main):002:0> Time.strptime("09/31/2011", '%m/%d/%Y').to_date
=> Sat, 01 Oct 2011

Ruby and Rails "Date.today" format

In IRB, if I run following commands:
require 'date'
Date.today
I get the following output:
=> #<Date: 2015-09-26 ((2457292j,0s,0n),+0s,2299161j)>
But in Rails console, if I run Date.today, I get this:
=> Sat, 26 Sep 2015
I looked at Rails' Date class but can't find how Rails' Date.today displays the output differently than Ruby's output.
Can anybody tell, in Rails how Date.today or Date.tomorrow formats the date to display nicely?
The answer to your question is ActiveSupport's core extension to Date class. It overrides the default implementations of inspect and to_s:
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
def readable_inspect
strftime('%a, %d %b %Y')
end
alias_method :default_inspect, :inspect
alias_method :inspect, :readable_inspect
Command line example:
ruby-2.2.0 › irb
>> require 'date'
=> true
>> Date.today
=> #<Date: 2015-09-27 ((2457293j,0s,0n),+0s,2299161j)>
>> require 'active_support/core_ext/date'
=> true
>> Date.today
=> Sun, 27 Sep 2015
Rails' strftime or to_s methods should do what you need.
For example, using to_s:
2.2.1 :004 > Date.today.to_s(:long)
=> "September 26, 2015"
2.2.1 :005 > Date.today.to_s(:short)
=> "26 Sep"
If you run this:
require 'date'
p Date.today.strftime("%a, %e %b %Y")
You'll get this: "Sat, 26 Sep 2015"

Scope Chaining in Mongoid 2.2 with Rails 3.0.9 and Ruby 1.8.7

Hi I have application running on Ruby 1.8.7 (i am presently not in a position to update this to 1.9.2) and Rails 3.0.9 running mongoid 2.2.2.
I have a couple of named scopes which I have defined as follows
scope :for_pickups, where(:state => "accepted")
scope :confirmed_shipments, where(:state => "confirmed", :created_at.lt => Date.today - 1.day).desc(:created_at).limit(10)
scope :undelivered_shipments, Proc.new{ |start_date_utc, end_date_utc|
start_date_utc = (Date.today - 7.days).to_time.utc if !start_date_utc.present?
end_date_utc = Date.today.to_time.utc if !end_date_utc.present?
any_of({:created_at.gte => start_date_utc, :created_at.lte => end_date_utc},
{:pickup_date.gte => start_date_utc, :pickup_date.lte => end_date_utc},
{:desired_arrival_date.gte => start_date_utc, :desired_arrival_date.lte => end_date_utc}).
where(:state.in => ["accepted"], :state.nin => ["delivered"]).without(:carrier_digest, :carrier_label_image_base64, :carrier_label_html_base64)
}
scope :search, Proc.new{|search_params|
regexp = Regexp.new(/.*#{search_params.strip}.*/i, true)
where(:golfer_name => regexp)
}
This seems to work well and return the expected values when I use them on their own but when I use scope chaining it gets messed up.
For instance when I run Model.undelivered_shipments.search("sid") i get an array which has :ids as the first parameter
[:ids, #[{:created_at=>{"$gte"=>Thu Sep 27 18:30:00 UTC 2012, "$lte"=>Thu Oct 04 18:30:00 UTC 2012}}, {:pickup_date=>{"$gte"=>Thu Sep 27 18:30:00 UTC 2012, "$lte"=>Thu Oct 04 18:30:00 UTC 2012}}, {:desired_arrival_date=>{"$gte"=>Thu Sep 27 18:30:00 UTC 2012, "$lte"=>Thu Oct 04 18:30:00 UTC 2012}}], :_id=>"sid", :state=>{"$nin"=>["delivered"], "$in"=>["accepted"]}},
options: {:fields=>{:carrier_digest=>0, :carrier_label_html_base64=>0, :carrier_label_image_base64=>0}},
class: Shipment,
embedded: false>
]
Not sure why it returns this and why mongoid criteria defines :_id => 'sid' However when i run the search before the undelivered_shipments method it generates the criteria correctly.
It works if run it with other scopes like for_pickups.search etc but not with the undelivered shipments. I understand I am missing something but I've been through the docs and I can't find anything that really helps. I would really appreciate any help on this
Thanks in advance.

Difference between Rails 2.3 and Rails 3.2 'weeks' method

I've noticed some different behaviour between Rails 2 and Rails 3 when it comes to ActiveSupport date handling.
When I run the following code in a Rails 2.3 application it runs as I expect and outputs the dates one week at a time.
>> first = Date.today
=> Fri, 23 Mar 2012
>> last = Date.today + 2.months
=> Wed, 23 May 2012
>> first.step(last, 1.week) { |date| puts date }
2012-03-23
2012-03-30
2012-04-06
2012-04-13
2012-04-20
2012-04-27
2012-05-04
2012-05-11
2012-05-18
When I try the same code within a Rails 3 application I get the following.
>> first = Date.today
=> Fri, 23 Mar 2012
>> last = Date.today + 2.months
=> Wed, 23 May 2012
>> first.step(last, 1.week) { |date| puts date }
Mar 23, 2012
TypeError: expected numeric
The problems seems to be with how Rails 3 is now handling the .weeks method, Rails 2 outputs the following
>> 1.week
=> 7 days
Where Rails 3 outputs
>> 1.week
=> 604800
Can anyone explain what is going on here and how I can neatly iterate over a date range one week at a time in Rails 3.
No idea why it doesn't work, but this seems to:
(Date.today..(Date.today + 30)).step(7)

Ruby on Rails 3 Time - Parse Milliseconds

I'm trying to parse a date like: 2011-05-21 04:20:46.011 into a Time object in Rails. So far I have the following:
Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
But it doesn't seem to like the "%3N" at the end. How do I parse this date?
Use parse:
x = Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
# => 2011-05-21 04:20:46 -0700
x.usec
# => 11000
In many case you don't need to pass in the format either:
x = Time.parse("2011-05-21 04:20:46.011")
# => 2011-05-21 04:20:46 -0700
x.usec
# => 11000
Try Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
With Ruby v 2.3.2 and Rails v 5.0.0.1 in rails console
2.3.2 :035 > Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
NoMethodError: undefined method `getlocal' for "%Y-%m-%d %H:%M:%S.%3N":String
from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:264:in `make_time'
from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:366:in `parse'
from (irb):35
Note: In code below in the parse format, NOT prefixed %N with the number of fractional digits like %3N and instead simply specified %N and it works
2.3.2 :037 > Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
=> 2011-05-21 04:20:46 +0530
2.3.2 :038 > tt = Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
=> 2011-05-21 04:20:46 +0530
2.3.2 :039 > tt.usec
=> 11000
The above code didn't worked when using parse
2.3.2 :040 > tt = Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
NoMethodError: undefined method `getlocal' for "%Y-%m-%d %H:%M:%S.%N":String
from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:264:in `make_time'
from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:366:in `parse'
from (irb):40
It looks strange because Time.strptime(date, format, now=self.now) official documentation does mention about %3N, %6N and %9N explicitly and using them in the parse format doesn't work!
Rails does provide a counterpart strptime(str, format, now=now()) as part of ActiveSupport::TimeZone API and it internally does the parsing using Ruby's standard DateTime._strptime as shown in its source-code:
# File activesupport/lib/active_support/values/time_zone.rb, line 382
def strptime(str, format, now=now())
parts_to_time(DateTime._strptime(str, format), now)
end
And I guess DateTime._strptime internally delegates to Ruby's standard Time.strptime
For those who are looking for leveraging Rails's Time.zone.parse counterpart for parsing in a specific format they can use below code:
tt = Time.zone.strptime('1999-12-31 14:00:00.011111', '%Y-%m-%d %H:%M:%S.%N')
=> Fri, 31 Dec 1999 14:00:00 UTC +00:00
2.3.2 :031 > tt.usec
=> 11111
Hope someone from the core-team can clarify about this behaviour observed and if the behaviour is normal then at-least a note should be made about in the documentation.

Resources