show weeks_ago based off week number? - ruby-on-rails

Im trying to show the number of weeks ago calculated from the week number
" x weeks ago "
this should just increment one week ago, two weeks ago, three weeks ago, 1 month ago, 2 months ago, 1 year ago.. etc
Im using method helper:
def weeks_ago_in_words(from_time, include_seconds = false)
to_time = Time.now
weeks_ago = ((to_time - from_time)/1.week).abs
[nil, "last week", "two weeks ago", "three weeks ago"][weeks_ago] ||
distance_of_time_in_words(from_time, to_time, include_seconds)
end
In view:
= weeks_ago_in_words(Time.local(2013) + week.to_i)
week = a week number like 1,10,28,52 etc
This does not give me correct resuls, is there a better way to calculate the "x weeks ago " based on the weeknumer?

If you are comparing two dates from the same year here is the code using cweek:
require 'date'
Time.now.to_date.cweek - Date.new(2013,1,1).cweek
If you are comparing two different years you'll have to add some conditional logic to determine your year multiplier as cweek returns the same value for Dec. 31, 2012 and Jan. 1, 2013.

Related

What is the week number of a week with a weekday(of day X) in a month of a given day X?

I'm looking for a way to get the week number of a week with a weekday(of day X) in a month of day X.
For example:- What is the week number of the week with weekday Tuesday in it of day 13? Answer - second.
Image of the April month
I know it sounds confusing so here's example 2 - If I provide a date of 24 May 2021 then I would like to know that it is the fourth Monday of the month.
Image of the May month
I would be happy with a general answer but it would be great to know if there's an efficient way to do that using dart. Thank you.
Simple math. Get the day of week. Get the day of month, subtract 1, and integer divide by 7, and add 1. Now you have "Monday" "4th one of the month".
To explain, think about it. Days numbered 1 to 7 are always the first one of those days in the month. Similarly, days numbered 8 to 14 are always the second one of those days in the month. Quick math shows that you want:
(dayOfMonth - 1) ~/ 7 + 1
and for dayOfWeek, 1 Jan 1970 was a thursday, and here's some code:
void main() {
var epoch = DateTime.utc(1970, 1, 1);
var target = DateTime.utc(2021, 5, 24); // your input goes here
var days = (target.difference(epoch)).inDays;
// epoch is thursday, so we count back to following sunday
days -= 3;
var dow = days % 7;
print(dow); // sunday = 0 ... saturday = 6
}
This prints "1" in dartpad. Monday!
Be sure to use utc, or you can get messed up on DST.

Show objects based on selected week

I have an active relation Bar object with an attribute shift_date. shift_date represents each day between March and June. March and June comes from Foo which has attributes start_month and end_month:
f = Foo.find(1)
days = (f.end_month - f.start_month).to_i
weeks = (days * 0.142857).round(2)
f.bars will give me days objects. Where days is the total amount of objetcs.
My trouble is to get Bars objects, objects for week 1, 2 or 3 etc:
f.bars.where('shift_date >= ?', (weeks/7.days)).group_by{ |result| result }
operator does not exist: timestamp without time zone >= numeric
So what am I saying? Give me all objects on week 1 or week 5, if any. How do I go about this, please?
Im on to something but not right:
f.bars.where('shift_date >= ?', Date.today).group_by{ |result| result}
Edit:
Im almost there. I could splat out the days with:
days_array = *(f.start_month..f.end_month)
then
f.bars.where(shift_date: days_array[0]..days_array[7])
That would be the answer! But...not really. For my views, I need to group the splatted days in a 7 days interval as week, so days_array[0] to days_array[7] would be week 1 and days_array[8] to days_array[14] would be week 2 etc. How to show that in the view? This will give me everything I need.

Ruby: subtract two dates to get Updated at

I am looking for a way to subtract two dates. I am not sure if a regular - would work for this. Asuming that works I still need it to show Updated 5s ago and not 0h0m5s ago if the post was updated 5s ago. The same goes for Updated 3min ago, I do not want it to show the seconds nor the hours.
So I need the updated at to be as precise as the least precise time unit that is not equal to 0.
If post was updated less than 1 sec ago show now
If post was updated < 1 min ago, but > 1 sec ago have format #s
If post was updated < 1 hour ago, but > 1 min ago have format #m
If post was updated < 1 day ago, but > 1 hour ago have format #h
If post was updated < 1 month ago, but > 1 day ago have format #d
If post was updated < 1 year ago, but > 1 month ago have format #m
If post was updated > 1 year ago have format #y
Please let me know if I wasn't clear enough.
Thank you.
try this in view
<%= time_ago_in_words(#post.updated_at) %>
check at time_ago_in_words method or distance_of_time_in_words

How can I make a `weeks_ago` helper?

How can I make a helper that will tell me how many weeks ago (rounded down) with rails? It could be based of the time_ago_in_words helper however I'd want it to return: "last week" then afterwards just two weeks ago, three weeks ago, etc...
Try this:
def my_time_ago_in_words(from_time, include_seconds = false)
to_time = Time.now
weeks_ago = ((to_time - from_time)/1.week).abs
[nil, "last week", "two weeks ago", "three weeks ago"][weeks_ago] ||
distance_of_time_in_words(from_time, to_time, include_seconds)
end
This function will behave the same as time_ago_in_words. When the from_time is between 1 - 3 week ago, this will print last week, two weeks ago, three weeks ago otherwise it will print the usual.
That would be a nice patch to distance_of_time_in_words:
http://github.com/rails/rails/blob/4cbb9db0a5ff65b0a626a5b043331abefd89e717/actionpack/lib/action_view/helpers/date_helper.rb#L68-103
Also, you can write custom time descriptions for the other levels (day, month, year).
http://robots.thoughtbot.com/post/392707640/the-more-you-know-custom-time-descriptions

In Rails, display time between two dates in English

In a Rails project I want to find the difference between two dates and then display it in natural language. Something like
>> (date1 - date2).to_natural_language
"3 years, 2 months, 1 week, 6 days"
Basically this for ruby.
Google and the Rails API haven't turned up anything. I've found some things that will give you the difference in one unit (ie, how many weeks between two dates) but not something that will accurately calculate years, months, weeks, days all together.
The Rails' ActionView module includes two methods that may do what you require:
distance_of_time_in_words
distance_of_time_in_words_to_now
The other answers may not give the type of output that you're looking for, because instead of giving a string of years, months, etc., the Rails helpers just show the largest unit. If you're looking for something more broken down, here's another option. Stick this method into a helper:
def time_diff_in_natural_language(from_time, to_time)
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
distance_in_seconds = ((to_time - from_time).abs).round
components = []
%w(year month week day).each do |interval|
# For each interval type, if the amount of time remaining is greater than
# one unit, calculate how many units fit into the remaining time.
if distance_in_seconds >= 1.send(interval)
delta = (distance_in_seconds / 1.send(interval)).floor
distance_in_seconds -= delta.send(interval)
components << pluralize(delta, interval)
# if above line give pain. try below one
# components << interval.pluralize(delta)
end
end
components.join(", ")
end
And then in a view you can say something like:
<%= time_diff_in_natural_language(Time.now, 2.5.years.ago) %>
=> 2 years, 6 months, 2 days
The given method only goes down to days, but can be easily extended to add in smaller units if desired.
I tried Daniel's solution and found some incorrect results for a few test cases, due to the fact that it doesn't correctly handle the variable number of days found in months:
> 30.days < 1.month
=> false
So, for example:> d1 = DateTime.civil(2011,4,4)
> d2 = d1 + 1.year + 5.months
> time_diff_in_natural_language(d1,d2)
=> "1 year, 5 months, 3 days"
The following will give you the correct number of {years,months,days,hours,minutes,seconds}:
def time_diff(from_time, to_time)
%w(year month day hour minute second).map do |interval|
distance_in_seconds = (to_time.to_i - from_time.to_i).round(1)
delta = (distance_in_seconds / 1.send(interval)).floor
delta -= 1 if from_time + delta.send(interval) > to_time
from_time += delta.send(interval)
delta
end
end
> time_diff(d1,d2)
=> [1, 5, 0, 0, 0, 0]
distance_of_time_in_words is the most accurate here. Daniel's answer is actully wrong: 2.5 years ago should produce exactly 2 years, 6 months. The issue is that months contain 28-31 day, and years might be leap.
I wish I knew how to fix this :(
DateHelper#distance_of_time_in_words
def date_diff_in_natural_language(date_from, date_to)
components = []
%w(years months days).each do |interval_name|
interval = 1.send(interval_name)
count_intervals = 0
while date_from + interval <= date_to
date_from += interval
count_intervals += 1
end
components << pluralize(count_intervals, interval_name) if count_intervals > 0
end
components.join(', ')
end

Resources