Humanizing time - ruby-on-rails

I have a number of products that are perishable. Therefore, each product has an attribute called hours_expiration that tells how many hours the product can be used before it goes bad.
For ex, apple expires in 168 hours; nut expires in 4320 hours.
Given, the product's hours-to-expiration and the current time (Time.now or Date.now), how can I humanize the time-to-expiration in some of the following sample ways?
Your item is set to expire in about:
6 months and 14 days
1 month and 13 days
1 month and 1 day
27 days
1 day
23 hours
1 hour
50 minutes
1 minute
Looking for something robust and simple!

The distance_of_time_in_words helper seems to be what you ask for.

Another easy helper is time_ago_in_words: https://apidock.com/rails/ActionView/Helpers/DateHelper/time_ago_in_words
The method name might sound like it can only deal with past dates but actually it handles future dates just fine. You can try it in your rails console:
expiration_date = Time.now + 5.days
puts "Expires in #{helper.time_ago_in_words(expiration_date)}"
"Expires in 5 days"

Look at Distance of time docs: http://apidock.com/rails/ActionView/Helpers/DateHelper/distance_of_time_in_words

Related

Check if date expires in less than 20day in rails

I have a table shift and it has a field expiry_date.
I have a requirement to get a list of all shifts with an expiry date in less than 20 days. How can I achieve this in rails?
I tried something like this but it is returning me all Shifts that have expiry_date 20 days ago but I need which will expire in less than 20 days.
scope :20_days_to_expire, -> { where('expiry_date < ?', 20.days.ago) }
Please help me fix this.
You can filter between today and 20 days later:
scope :20_days_to_expire, -> { where(expiry_date: Time.zone.now.beginning_of_day..(Time.zone.now.beginning_of_day + 20.days)) }

Confusing ActiveSupport::Duration calculation results

I understand this from ActiveSupport::Duration (Rails 4.2.4 + ruby 2.2.1):
main > (1.month + 2.days).parts
[[:months, 1], [:days, 2]]
I don't understand this though:
main > (1.hour + 35.minutes).parts
[[:seconds, 3600], [:seconds, 2100]]
Does ActiveSupport::Duration not handle hours and seconds the way it handles months and days? The docs on ActiveSupport::Duration are quite sparse (I can't seem to find better docs).
My main goal is to store a duration (hours and minutes) in a Rails model. Should I forget about ActiveSupport::Duration and just store seconds and then do my own calculations?
ActiveSupport handles months and days (and years) separately from hours, minutes and seconds.
This is because a duration of one hour (or 23 minutes) is always an exact number of seconds. A month on the other hand is a varying number of days and a day can have either 23, 24, or 25 hours depending on daylight savings changes.
It sounds like you don't need this functionality, in which case storing a number of seconds is probably simpler.

.change function is not working for Dates for even number of months in ruby

Hi I have define this method
def change_date
date = Date.today
start_date = date.change(year: 2015, month: (2 * 3)).at_beginning_of_quarter
p 'aaaaaa'
p start_date
end
give me invalid date error .change is not working or am I doing it in a wrong way please guide me how to solve this. Thanx in advance.
This is because the month you are specifying doesn't have the current day.
I mean the current month (July) has 31 days but the month you're setting (June) has only 30 days. You can change your code like so:
# in Rails:
date = Date.today.beginning_of_month # or Date.today.change(day: 1)
Then chain your 'change' in front of the date variable.
This actually happens, because today is the 31 of July, and not all months have 31 days in it, for example June, the 6th month, has only 30 days in it.

Shoter time_ago_in_words eg. 1d ago

In my design i have a latest posts block, in this block there is very little space to say when the post was posted. Therefore, I did it as "1d" instead of "1 day ago". I would like it to be either "Today", "Yesterday" or "xd"(1d, 2d, 3d, etc)
The main reason for not using hours and minutes(and seconds..) is that my format is like this posted_date="2013-01-04", so no hours, minutes, seconds etc.
Is this posible?
def days_ago(date)
days = ((Time.now - date) / 24 / 60 / 60).round
case days
when 0 then 'Today'
when 1 then 'Yesterday'
else "#{days}d"
end
end

How to calculate how much time is remaning 3 days from created_at

I am trying to show to the user how much time is remaning in his profile. Generally I want to do it 3 days before the data is hidden.
I know i can get the future date with - 3.days.from_now. But thats not exactly what i am looking for.
How do I show, how many days are remaning compared to the created_at from the database? The format that gets rendered the mysql db is 2013-06-06 19:41:02 UTC. Now i want to show the time difference (in days) from this created_at date and time.
Any help is appreciated
((user.created_at + 3.days).to_date - Date.today).round
ActionView has you covered:
> Rails.helper.distance_of_time_in_words_to_now(3.days.from_now)
=> "3 days"
> Rails.helper.distance_of_time_in_words_to_now(8.hours.from_now)
=> "about 8 hours"
> Rails.helper.distance_of_time_in_words_to_now(12.weeks.ago)
=> "3 months"
You should be able to do something like this:
my_item.created_at + 3.days

Resources