How to get current day name from Date.today? - ruby

How does someone get the name of the day from Date.today?
The below should be equal too "Fri" or "Friday":
Date.today #=> Fri, 20 Nov 2015

Use the following:
Date.today.strftime("%A")

Related

I can't get the 15th weekday in ruby

I cant get the next 15th day but not the working day.
DateTime.now.next_day(+15).strftime('%d %^B %Y')
how can i get the next 15th weekday?
You're just adding 15 days to the current date. What you want is to adjust the date:
date = DateTime.now
if (date.mday > 15)
date = date.next_month
end
date = date.next_day(15 - date.mday)
Where that adjusts to be the 15th of the next month if it's already past the 15th of the current month.
Now this can be extended to be an Enumerator:
def each_mday(mday, from: nil)
from ||= DateTime.now
Enumerator.new do |y|
loop do
if (from.mday > mday)
from = from.next_month
end
from = from.next_day(mday - from.mday)
y << from
from += 1
end
end
end
Which makes it possible to find the first day matching particular criteria, like being a weekday:
each_mday(15, from: Date.parse('2019-06-14')).find { |d| (1..5).include?(d.wday) }
Where that returns July 15th, as June 15th is a weekend.
The from argument is optional but useful for testing cases like this to ensure it's working correctly.
15.times.reduce(Date.civil 2019, 03, 24) do |acc, _|
begin
acc += 1
end while [0, 6].include? acc.wday
acc
end
#⇒ #<Date: 2019-04-12 ((2458586j,0s,0n),+0s,2299161j)>
So you want to add 15 business days from the current date. You can go with iGian or Aleksei vanilla ruby answers or use business_time gem:
15.business_days.from_now
If I understood correctly, you want to get next Monday if you hit Saturday or Sunday. Since wday gives you 0 for Sun and 6 for Sat, you can use it to as a conditional to add days towards Monday.
def date_add_next_week_day(days)
date = (Date.today + days)
date += 1 if date.wday == 6
date += 1 if date.wday == 0
date
end
date_add_next_week_day(15).strftime('%d %^B %Y')
If I get the point you need to find the 15th day after a specified date, skipping weekends.
One possible option is to define the skipping_weekend hash like this, considering Date.html#wday:
skip_weekend = { 6 => 2, 0 => 1}
skip_weekend.default = 0
Then:
next15 = DateTime.now.next_day(15)
next15_working = next15.next_day(skip_weekend[next15.wday]).strftime('%d %B %Y')
Now if next15 falls on a working day, next15_working is the same day (hash defaults to 0), otherwise it skips 2 days if Saturday (6th week day, hash maps to 2) or 1 day if Sunday (0th week day, hash maps to 1)
I assume that, given a starting date, ds (a Date object), and a positive integer n, the problem is determine a later date, dt, such that between ds+1 and dt, inclusive, there n weekdays.
require 'date'
def given_date_plus_week_days(dt, week_days)
wday = dt.wday
weeks, days = (week_days + {0=>4, 6=>4}.fetch(wday, wday-1)).divmod(5)
dt - (wday.zero? ? 6 : (wday - 1)) + 7*weeks + days
end
The variable wday is assigned to the day of week for the start date, dt. The start date is moved back to the previous Monday, unless it falls on a Monday, in which case it is not changed. That is reflected in the expression
wday.zero? ? 6 : (wday - 1)
which is subtracted from dt. The number of week days is correspondingly adjusted to
week_days + { 0=>4, 6=>4 }.fetch(wday, wday-1)
The remaining calculations are straightforward.
def display(start_str, week_days)
start = Date.parse(start_str)
7.times.map { |i| start + i }.each do |ds|
de = given_date_plus_week_days(ds, week_days)
puts "#{ds.strftime("%a, %b %d, %Y")} + #{week_days} -> #{de.strftime("%a, %b %d, %Y")}"
end
end
display("April 8", 15)
Mon, Apr 08, 2019 + 15 -> Mon, Apr 29, 2019
Tue, Apr 09, 2019 + 15 -> Tue, Apr 30, 2019
Wed, Apr 10, 2019 + 15 -> Wed, May 01, 2019
Thu, Apr 11, 2019 + 15 -> Thu, May 02, 2019
Fri, Apr 12, 2019 + 15 -> Fri, May 03, 2019
Sat, Apr 13, 2019 + 15 -> Fri, May 03, 2019
Sun, Apr 14, 2019 + 15 -> Fri, May 03, 2019
display("April 8", 17)
Mon, Apr 08, 2019 + 17 -> Wed, May 01, 2019
Tue, Apr 09, 2019 + 17 -> Thu, May 02, 2019
Wed, Apr 10, 2019 + 17 -> Fri, May 03, 2019
Thu, Apr 11, 2019 + 17 -> Mon, May 06, 2019
Fri, Apr 12, 2019 + 17 -> Tue, May 07, 2019
Sat, Apr 13, 2019 + 17 -> Tue, May 07, 2019
Sun, Apr 14, 2019 + 17 -> Tue, May 07, 2019

Ruby Mongoid: How to convert a date into age?

I have a date in Mongoid user collection field dob.
I want to get those users whose age is between 18-30.
but i don't know how to get age from date in Mongoid.
here is the query:
User.in(gender: gender_group).between(dob: 18..30)
Considering a user is 30 years old if he has not yet celebrated his 31st birthday, following would be your logic:
today = Date.today
=> Mon, 07 May 2018
aged_30 = today - 31.years + 1.day
=> Fri, 08 May 1987
aged_18 = today - 18.years
=> Sun, 07 May 2000
User.in(gender: gender_group).between(dob: aged_30..aged_18)

How do I create a cron expression running in Kibana on weekday?

I would like my watcher to run from Monday to Friday only. So I'm trying to use this schedule:
"trigger": {
"schedule" : { "cron" : "0 0 0/4 * * MON-FRI" }
},
"input": {
...
However, I'm getting
Error
Watcher: [parse_exception] could not parse [cron] schedule
when I'm trying to save the watcher. Removing MON-FRI does helps but I need it.
This expression works:
0 0 0/4 ? * MON-FRI
But I'm not sure I understand why ? is required for either the day_of_week or day_of_month
Thank you!
I believe this is what you are looking for:
"0 0 0/4 ? * MON-FRI"
You can use croneval to check your cron expressions 1:
$ /usr/share/elasticsearch/bin/x-pack/croneval "0 0 0/4 ? * MON-FRI"
Valid!
Now is [Mon, 20 Aug 2018 13:32:26]
Here are the next 10 times this cron expression will trigger:
1. Mon, 20 Aug 2018 09:00:00
2. Mon, 20 Aug 2018 13:00:00
3. Mon, 20 Aug 2018 17:00:00
4. Mon, 20 Aug 2018 21:00:00
5. Tue, 21 Aug 2018 01:00:00
6. Tue, 21 Aug 2018 05:00:00
7. Tue, 21 Aug 2018 09:00:00
8. Tue, 21 Aug 2018 13:00:00
9. Tue, 21 Aug 2018 17:00:00
10. Tue, 21 Aug 2018 21:00:00
For the first expression you'll get following java exception:
java.lang.IllegalArgumentException: support for specifying both a day-of-week AND a day-of-month parameter is not implemented.
You can also use Crontab guru to get human readable descriptions like:
At every minute past every 4th hour from 0 through 23 on every day-of-week from Monday through Friday.
The question mark means 'No Specific value'. From the documentation on Quartz's website:
? (“no specific value”) - useful when you need to specify something in one of the two fields in which the character is allowed, but not the other. For example, if I want my trigger to fire on a particular day of the month (say, the 10th), but don’t care what day of the week that happens to be, I would put “10” in the day-of-month field, and “?” in the day-of-week field. See the examples below for clarification.
http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/crontrigger.html
I suppose since you want your schedule to run every 4 hours, mon-fri, the actual day of the month is irrelevant, so the ? specifies that. * on teh other hand would be 'all values' which would not make sense since you are specifying only mon-fri for day of the week.
Hope that helps!

Ruby: Grouping a date range by year and month

I am creating a range for each month in my example range.
example_range = (Time.zone.today..2.years.from_now)
Output should look like so:
=> [Wed, 03 Aug 2016..Wed, 31 Aug 2016, Thu, 01 Sep 2016..Fri,
30 Sep 2016, Sat, 01 Oct 2016..Mon, 03 Oct 2016, ...]
At the moment I'm doing this, which doesn't work for ranges longer than a year, because the grouping will put January '16 and January '17 in one group.
example_range.group_by(&:month).each { |_, month| month.first..month.last }
I also tried this, but ruby segfaults on this for some reason...
example_range.group_by(&:year).map{ |ary| ary.group_by(&:month)}
Does anyone know a more beautiful (or at least working) way of doing this?
How is this:
example_range.group_by {|date| [date.year, date.month] }.map {|_, month| month.first..month.last }
If you are using Active Support (Rails), this will also work:
example_range.group_by(&:beginning_of_month).map {|_, month| month.first..month.last }
The best solution I think is this:
example_range.group_by {|date| date.month.to_s + "-" + date.year.to_s}
You can adjust the way you need.

Rails 3.2.8 - How do I get the week number from Rails?

I would like to know how to get the current week number from Rails and how do I manipulate it:
Translate the week number into date.
Make an interval based on week number.
Thanks.
Use strftime:
%U - Week number of the year. The week starts with Sunday. (00..53)
%W - Week number of the year. The week starts with Monday. (00..53)
Time.now.strftime("%U").to_i # 43
# Or...
Date.today.strftime("%U").to_i # 43
If you want to add 43 weeks (or days,years,minutes, etc...) to a date, you can use 43.weeks, provided by ActiveSupport:
irb(main):001:0> 43.weeks
=> 301 days
irb(main):002:0> Date.today + 43.weeks
=> Thu, 22 Aug 2013
irb(main):003:0> Date.today + 10.days
=> Sun, 04 Nov 2012
irb(main):004:0> Date.today + 1.years # or 1.year
=> Fri, 25 Oct 2013
irb(main):005:0> Date.today + 5.months
=> Mon, 25 Mar 2013
You are going to want to stay away from strftime("%U") and "%W".
Instead, use Date.cweek.
The problem is, if you ever want to take a week number and convert it to a date, strftime won't give you a value that you can pass back to Date.commercial.
Date.commercial expects a range of values that are 1 based.
Date.strftime("%U|%W") returns a value that is 0 based. You would think you could just +1 it and it would be fine. The problem will hit you at the end of a year when there are 53 weeks. (Like what just happened...)
For example, let's look at the end of Dec 2015 and the results from your two options for getting a week number:
Date.parse("2015-12-31").strftime("%W") = 52
Date.parse("2015-12-31").cweek = 53
Now, let's look at converting that week number to a date...
Date.commercial(2015, 52, 1) = Mon, 21 Dec 2015
Date.commercial(2015, 53, 1) = Mon, 28 Dec 2015
If you blindly just +1 the value you pass to Date.commercial, you'll end up with an invalid date in other situations:
For example, December 2014:
Date.commercial(2014, 53, 1) = ArgumentError: invalid date
If you ever have to convert that week number back to a date, the only surefire way is to use Date.cweek.
date.commercial([cwyear=-4712[, cweek=1[, cwday=1[, start=Date::ITALY]]]]) → date
Creates a date object denoting the given week date.
The week and the day of week should be a negative
or a positive number (as a relative week/day from the end of year/week when negative).
They should not be zero.
For the interval
require 'date'
def week_dates( week_num )
year = Time.now.year
week_start = Date.commercial( year, week_num, 1 )
week_end = Date.commercial( year, week_num, 7 )
week_start.strftime( "%m/%d/%y" ) + ' - ' + week_end.strftime("%m/%d/%y" )
end
puts week_dates(22)
EG: Input (Week Number): 22
Output: 06/12/08 - 06/19/08
credit: Siep Korteling http://www.ruby-forum.com/topic/125140
Date#cweek seems to get the ISO-8601 week number (a Monday-based week) like %V in strftime (mentioned by #Robban in a comment).
For example, the Monday and the Sunday of the week I'm writing this:
[ Date.new(2015, 7, 13), Date.new(2015, 7, 19) ].map { |date|
date.strftime("U: %U - W: %W - V: %V - cweek: #{date.cweek}")
}
# => ["U: 28 - W: 28 - V: 29 - cweek: 29", "U: 29 - W: 28 - V: 29 - cweek: 29"]

Resources