Given day in week (let's say Monday), I need to find closest date (in future) to given date (for example 9-4-2016) which is this day in week (for these examples, it should be 11-4-2016).
This is a pure Ruby solution.
require 'date'
d = Date.strptime('9-4-2016', '%d-%m-%Y')
#=> #<Date: 2016-04-09 ((2457488j,0s,0n),+0s,2299161j)>
d + (1 - d.wday) % 7
#=> #<Date: 2016-04-11 ((2457490j,0s,0n),+0s,2299161j)>
1 is Monday's offset. d.wday #=> 6.
I have assumed that if the date falls on a Monday, the "closest" Monday is the same day. If it is to be the following Monday, use:
d + (d.wday == 1) ? 7 : (1 - d.wday) % 7
You can find this date in the nearest week of your date:
date = Date.parse('9-4-2016')
(date..date + 6).find {|d| d.strftime("%A") == "Monday"}
#=> Mon, 11 Apr 2016
Related
Usually I don't have issues parsing strings to Time in Rails, however I cannot understand why it's behaving like this:
irb(main):073:0> DateTime.strptime("20/2020", "%V/%Y")
=> Wed, 01 Jan 2020 00:00:00 +0000
I want the 20th week of 2020, not the 1st Jan...
I think that you need to use the commercial method.
require 'date'
week = 20
start_week = Date.commercial(2020, week)
# => Mon, 11 May 2020
puts "#{start_week}"
# => 2020-05-11
In case you need a Range, you can do:
Date.commercial(2020, week).all_week
# => Mon, 11 May 2020..Sun, 17 May 2020
For more information see the documentation.
require 'date'
If week 1 begins on Sunday:
Date.strptime("20/2020", "%U/%Y")
#=> #<Date: 2020-05-17 ((2458987j,0s,0n),+0s,2299161j)>
and on Monday:
d = Date.strptime("20/2020", "%W/%Y")
#=> #<Date: 2020-05-18 ((2458988j,0s,0n),+0s,2299161j)>
and also from the doc Date#strftime (which contains the formatting directives for Date::strptime), "The days in the year before the first week are in week 0".
There is generally a difference between %Y and %G for the year depending on your assumed definition for a week number.
For ISO 8601 weeks (which are commonly used in e.g. Europe), you have to use the week-based year here (%G) rather than the day-=based year (%Y). This is important around the edges of the years. For example, 2021-01-01 is in week 53 of 2020. On this date
%G is 2020, but
%Y is already 2021
If you want to parse an ISO 8601 week, you can thus use the following code to ensur you use the right week and year:
require 'date'
DateTime.strptime("20/2020", "%V/%G")
# => #<DateTime: 2020-05-11T00:00:00+00:00 ((2458981j,0s,0n),+0s,2299161j)>
Hi I've start_date column which capture time stamp, I'd like to query the data based on days like if date falls on sunday or monday like that.
For example
from_date = Tue Nov 22 23:00:00 UTC 2016
to_date = Sun Nov 27 02:00:00 UTC 2016
Here I need get all the records from tuesday 23:00 pm to sunday 02:00 am.
Updated Answer
MySQL has dayofweek function for this.
You can write your query as:
MyModel.where('dayofweek(start_date) = ?', 1) # 1 is Sunday
To get all models which start_date is on Sunday.
To achieve your goal, you can query start_date on Tuesday AND start_date hour is later than 23:00, start_date on Wed, start_date on Thurs and etc.
So the final query would be like:
MyModel.where('(dayofweek(start_date) = ? AND hour(start_date) > ?)
OR dayofweek(start_date) = ? OR dayofweek(start_date) = ? OR
dayofweek(start_date) = ? OR dayofweek(start_date) = ? OR
(dayofweek(start_date) = ? AND hour(start_date) > ?)'
, 3, 23, 4, 5, 6, 7, 1, 2)
Previous Answer
You can use a range query with where:
Model.where(start_date: from_date..to_date)
Would it be possible to go to a certain month of the year with just a given integer. For example
date = Date.today
=> Wed, 30 Dec 2015
What if I want to go back to a certain month based on that date and I am just given a number let's say 7 which is July in the Date::MONTHNAMES so would it be possible to do something like
date = Date.today
=> Wed, 30 Dec 2015
date.go_to_month_of(7) # which will bring me back to July 30, 2015
Okay I found it. It's:
date = Date.today
date.change(:month => x)
Hope this helps you!
So I have a booking system and a user can book a time slot.
The time slots are listed by day and time:
Wednesday - 10am to 2pm
Wednesday - 3pm to 9pm
Sunday - 3pm - 7pm
Tuesday 12pm - 4pm
What I need to happen is return some future dates based on the chosen time slot. So for example if I was to choose the Sunday slot above, another select field would be populated with dates.
The dates would be presented in a day and month format:
5th June
8th May
30th September
The dates would be Sundays only or what ever day was chosen in the time slot drop down list.
I would also need some way to limit how many dates were returned. So maybe every Sunday up to 6 months in the future.
I've taken a look in the API and can't seem to find anything for this.
Would appreciate your help.
Thanks for your time.
To get a list of upcoming days for a particular for the next 6 months, you can use something like this.
require 'date'
start_date = Date.today
end_date = 6.months.from_now
weekday = 0 # 0 for Sunday, 6 for Saturday
dates = (start_date..end_date).to_a.select { |day| day.wday == weekday }
After that, you can format the days as you like
dates.map { |date| date.strftime("#{date.day.ordinalize} %B %Y") }
=> # 12th October 2014
# 19th October 2014
# 26th October 2014
# ...
A slightly different approach than those solutions building ranges of dates, instead build a range of offsets and then build your dates.
start_date = Date.new(2014,10,15)
day_offsets = (0..180).find_all { |i| i % 7 == 0 }
dates = day_offsets.map { |d| (DateTime.now + d).to_date}
How about a method that takes an array argument of what days are selected and returns dates within a range and then format it to fit your needs.
def valid_date_range(days)
days.map! {|day| day.to_date.wday}
today = Date.today
till_date = Date.today + 1.month
valid_dates = (today..till_date).to_enum.select {|date| days.include?(date.wday)}
valid_dates.map {|date| date.to_formatted_s(:short) }
end
So if you needed Monday and Friday you'd call date_range(["Monday", "Friday"]) and it would return an array:
[" 7 Oct", "13 Oct", "14 Oct", "20 Oct", "21 Oct", "27 Oct", "28 Oct", " 3 Nov", " 4 Nov"]
Or, you may just want to play with till_date to get just the current months days like "Date.today.end_of_month" and get:
["10 Oct", "13 Oct", "17 Oct", "20 Oct", "24 Oct", "27 Oct", "31 Oct"]
I can't seem to wrap my head around what might be an easy question..
Suppose I have the date..
Fri, 14 Sep 2012 18:37:50 +0200
How do I find out what week this date is on for this month? Is it the 1st, the 2nd..? The third?
Thanks!
Why use a library? Ruby has it by default:
Week number:
The week 1 of YYYY starts with a Sunday or Monday (according to %U
or %W). The days in the year before the first week are in week 0.
%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.zone.parse("2012-01-01").strftime("%U")
=> "01"
So, given that we can find what week a given date is in the year, we can do some math to figure out what week of the month it occurs in.
> week_of_year_for_first_of_month = Time.zone.parse("2012-07-01").strftime("%U").to_i
> week_of_target_date = Time.zone.parse("2012-07-14").strftime("%U").to_i
> week_occurs_in = week_of_target_date - week_of_year_for_first_of_month + 1
> week_occurs_in # => 2
Or a method:
def week_of_month_for_date(date)
my_date = Time.zone.parse(date)
week_of_target_date = my_date.strftime("%U").to_i
week_of_beginning_of_month = my_date.beginning_of_month.strftime("%U").to_i
week_of_target_date - week_of_beginning_of_month + 1
end
> week_of_month_for_date("2012-07-14") # => 2
> week_of_month_for_date("2012-07-15") # => 3
sachin87 has a library for determining such a thing.
Note that it depends how you count weeks. Let's say June 1 is on a Saturday. What week do you consider June 2 to be on? It might be the second week, or maybe it's the first if you consider a countable week to contain at least 4 days.
Or perhaps, given that June 2 is a Sunday, what's the week number of that Sunday? It's unambiguously the first Sunday. If this is what you mean, then it's actually simple. Dates 1 through 7 are always the first [weekday name] in the month. Dates 8-14 are always second. And so on. All you have to do is build a hash, and it will work for any month.
The week_of_month gem looks like it might be a bit overkill. That implementation uses a lot of array splitting and Array.include? checks.
Instead, here's a module that you can mixin to Date and Time to get the desired behavior.
require "active_support/core_ext/date"
require "active_support/core_ext/time"
module WeekCalculator
def week_of_year(mondays = false)
# Use %U for weeks starting on Sunday
# Use %W for weeks starting on Monday
strftime(mondays ? "%W" : "%U").to_i + 1
end
def week_of_month(mondays = false)
week_of_year(mondays) - beginning_of_month.week_of_year(mondays) + 1
end
end
class Date
include WeekCalculator
end
class Time
include WeekCalculator
end
Date.new(2014, 1, 1).week_of_year # => 1
Date.new(2014, 1, 1).week_of_month # => 1
Date.new(2014, 7, 1).week_of_year # => 27
Date.new(2014, 7, 1).week_of_month # => 1
Date.new(2014, 7, 27).week_of_year # => 31
Date.new(2014, 7, 27).week_of_month # => 5
Date.new(2014, 7, 27).week_of_year(:monday) # => 30
Date.new(2014, 7, 27).week_of_month(:monday) # => 4
I was challenged with answering "June 30th, 2017 is the nth Friday in June, 2017".
I solved this by building an array of all of the day names (Monday, Tuesday, etc) accrued up until the target date, and counting how many matched.
target_date = Date.new(2017, 6, 30)
(1..target_date.day).select do |day_of_month|
Date.new(target_date.year, target_date.month, day_of_month).strftime('%A') == target_date.strftime('%A')
end.length
Try this, find the week of a_date (considering first week is 1, and first day of week is monday):
week = (((a_date.mday + Date.new(a_date.year, a_date.month, 1).wday - 1) / 7) + 1)