require 'active_support/all'
days = 0.day.ago
days += 1 until days.since.wday == 2
next_tuesday = days.since
Above code is not doing right. But below is right. Could you tell me why?
require 'active_support/all'
current_day = 0.day.ago
current_day += 1.day until current_day.wday == 2
next_tuesday = current_day
First, mind that you're using ActiveSupport, so this is not pure Ruby. Assuming that, there is an easier way of doing so bundled in ActiveSupport:
Time.now.next_week(:tuesday)
It's possible doing date math using seconds as the interval, but that's old school and I'm sure you don't want to have us old people scare you with stories.
I'm away from my computer so this is untested, but here is the gist of what you want to do:
today = Date.today
today -= today.wday # normalize the day to the first day of the week, AKA Sunday
today += 9 # add a week + 2 days.
It can be stated on one line like:
Date.today - Date.today.wkday + 9
Or something in between the two.
Related
I want to display a closing time in relative words, e.g. "You have 2 hours left to answer the poll".
What is wrong with the below? When there are e.g. 54 minutes left, it returns "54 hours".
minute_diff = ((datetime_value - DateTime.current) * 24 * 60).to_i
case
when minute_diff < 0 # past time
[nil, "closed"]
when minute_diff.between?(0, 59) # within an hour
[minute_diff, "minutes"]
when datetime_value.today? # today
number_of_hours = (minute_diff / 60)
[number_of_hours, "hours"]
when datetime_value.to_date == DateTime.current.tomorrow.to_date # tomorrow
[1, "day"]
when datetime_value.to_date > DateTime.current.tomorrow.to_date # later than tomorrow
number_of_days = (datetime_value.to_date - DateTime.current.to_date).to_i
[number_of_days, "days"]
end
(Suggestions on a better way to return relative time is much appreciated)
Regarding your second question (giving a better way), you should use what is already there.
if (t = DateTime.current) < datetime_value
"You have #{distance_of_time_in_words(t, datetime_value)} left to answer the poll".
else
"Closed"
end
If you want to handle l18n, my favorite is the "twitter-cldr" gem.
I think that the rails date helpers ARE sufficient for this.
if datetime_value > 0
s = "You have #{time_ago_in_words(datetime_value)} left to answer the poll"
else
s = "Closed"
end
I have tried such code, but it doesn't work:
require 'time_diff'
cur_time = Time.now.strftime('%Y-%m-%d %H:%M')
time_diff_components = Time.diff(#art.datetime_of_update, Time.parse(cur_time))
if #art.PRICEM.to_f >= eprice.to_f || #art.PRICEM.blank? && time_diff_components[:hour] < 3 &&
but timediff is 0, in db time looks like this:
2012-08-28 19:53:12
How calculate difference in hour's between now and db?
Firstly, you should look at these two lines:
cur_time = Time.now.strftime('%Y-%m-%d %H:%M')
time_diff_components = Time.diff(#art.datetime_of_update, Time.parse(cur_time))
Why would you format the time and then only use the value as the input to a parsing operation? Surely it would be simpler - and less fragile - to write:
time_diff_components = Time.diff(#art.datetime_of_update, Time.now)
I don't know why Time.diff isn't working for you (I'm not a Ruby dev), but if the aim is to check whether the article was updated "less than 3 hours ago" then there's a simpler approach: subtract three hours from the current time, and compare the article's update time with that limit:
limit_time = Time.now + 3.hours
if #art.PRICEM.to_f >= eprice.to_f || #art.PRICEM.blank? && #art.datetime_of_update >= limit_time
If you don't have to be precise, you can use Rails' time_ago_in_words helper.
time_ago_in_words(Time.now - 3.hours)
#=> about 3 hours
of course, depending on the time difference, this can return 'minutes', 'days', etc. as well.
I need to check whether my current times is between the specified time interval (tonight 9pm and 9am tomorrow). How can this be done in Ruby on Rails.
Thanks in advance
Obviously this is an old question, already marked with a correct answer, however, I wanted to post an answer that might help people finding the same question via search.
The problem with the answer marked correct is that your current time may be past midnight, and at that point in time, the proposed solution will fail.
Here's an alternative which takes this situation into account.
now = Time.now
if (0..8).cover? now.hour
# Note: you could test for 9:00:00.000
# but we're testing for BEFORE 9am.
# ie. 8:59:59.999
a = now - 1.day
else
a = now
end
start = Time.new a.year, a.month, a.day, 21, 0, 0
b = a + 1.day
stop = Time.new b.year, b.month, b.day, 9, 0, 0
puts (start..stop).cover? now
Again, use include? instead of cover? for ruby 1.8.x
Of course you should upgrade to Ruby 2.0
Create a Range object having the two Time instances that define the range you want, then use the #cover? method (if you are on ruby 1.9.x):
now = Time.now
start = Time.gm(2011,1,1)
stop = Time.gm(2011,12,31)
p Range.new(start,stop).cover? now # => true
Note that here I used the explicit method constructor just to make clear that we are using a Range instance. You could safely use the Kernel constructor (start..stop) instead.
If you are still on Ruby 1.8, use the method Range#include? instead of Range#cover?:
p (start..stop).include? now
require 'date'
today = Date.today
tomorrow = today + 1
nine_pm = Time.local(today.year, today.month, today.day, 21, 0, 0)
nine_am = Time.local(tomorrow.year, tomorrow.month, tomorrow.day, 9, 0, 0)
(nine_pm..nine_am).include? Time.now #=> false
This might read better in several situations and the logic is simpler if you have 18.75 for "18:45"
def afterhours?(time = Time.now)
midnight = time.beginning_of_day
starts = midnight + start_hours.hours + start_minutes.minutes
ends = midnight + end_hours.hours + end_minutes.minutes
ends += 24.hours if ends < starts
(starts...ends).cover?(time)
end
I'm using 3 dots because I don't consider 9:00:00.000am after hours.
Then it's a different topic, but it's worth highlighting that cover? comes from Comparable (like time < now), while include? comes from Enumerable (like array inclusion), so I prefer to use cover? when possible.
Here is how I check if an event is tomorrow in Rails 3.x
(event > Time.now.tomorrow.beginning_of_day) && (event < Time.now.tomorrow.end_of_day)
if time is between one day:
(start_hour..end_hour).include? Time.zone.now.hour
I have to make a simple difference between two dates:
Date.parse("2009-06-20") - Date.today
This gives me the difference of the dates in days.
Anyone know a way to easily convert that to the following format:
The event occurred X years, Y months and Z days ago
Thank you.
Found the answer here:
More precise distance_of_time_in_words
with this gem:
https://github.com/radar/dotiw
You may be looking for distance_of_times_in_words
There is a RubyGem which returns Time difference in a hash like {:year => 0, :month => 0,...}
The link is : https://rubygems.org/gems/time_diff
This is an example for difference in days, hours, seconds. Add the fields that you need.
def calculate_difference
minutes = (Date.parse("2009-06-20") - Date.today).to_i / 60
days = minutes / (24*60)
minutes -= days * 24*60
hours = minutes / 60
minutes -= hours * 60
"#{days}d#{hours}h#{minutes}m"
end
I find these generic date differences useful in many cases:
time_a = Time.zone.parse('2020-05-30')
time_b = Time.zone.parse('2010-01-18')
time_diff = {
years: time_a.year - time_b.year,
months: time_a.month - time_b.month,
days: time_a.day - time_b.day,
}
=> {:years=>10, :months=>4, :days=>12}
I don't know of any standard, correct way to do this. As odd as it may seem the standard Ruby library has a Date class but no DateSpan functionality. Rails has a solution but it feels somewhat of a pain for me to require this whole mammoth for such a trivial task.
I have a settlement, I want to judge if the return_service_date is today, how to do this?
This is my code (rails):
if settlement.return_service_date &&
settlement.return_service_date.to_s(:date) == Time.now.to_s(:date)
Is there a better way to do this?
In Rails, you can do:
settlement.return_service_date.today?
For everyone who isn't using rails, my plain ruby solution with Time looks like the following, if you have Dates instead of Times you can convert them with .to_time()
# current time
time = Time.new()
# some time
some_time = Time.new() + 7550
# set beginning of today
today_start = Time.new(time.year,time.month,time.day)
# set ending of today
today_end = today_start + 86399
# check if some_time is in between today start and end
puts (today_start..today_end).cover?(some_time)
Depending on your current time it prints true (if your day still has at least 7550 seconds left) or false.