|
2 | 2 |
|
3 | 3 | module Faker
|
4 | 4 | class Date < Base
|
| 5 | + DAYS_OF_WEEK = %i[sunday monday tuesday wednesday thursday friday saturday].freeze |
| 6 | + |
5 | 7 | class << self
|
6 | 8 | ##
|
7 | 9 | # Produce a random date between two dates.
|
@@ -136,6 +138,52 @@ def in_date_period(month: nil, year: ::Date.today.year)
|
136 | 138 | between(from: from, to: to).to_date
|
137 | 139 | end
|
138 | 140 |
|
| 141 | + ## |
| 142 | + # Produce a random date at given day(s) of the week between two dates. |
| 143 | + # |
| 144 | + # @param day [Symbol, Array<Symbol>] # The day(s) of the week. See {DAYS_OF_WEEK}. |
| 145 | + # @param from [Date, String] The start of the usable date range. |
| 146 | + # @param to [Date, String] The end of the usable date range. |
| 147 | + # @return [Date] |
| 148 | + # |
| 149 | + # @example if used with or without Rails (Active Support) |
| 150 | + # Faker::Date.on_day_of_week_between(day: :tuesday, from: '2023-01-01', to: '2023-02-01') #=> #<Date: 2032-01-10> |
| 151 | + # |
| 152 | + # @example if used with Rails (Active Support) |
| 153 | + # Faker::Date.on_day_of_week_between(day: [:saturday, :sunday], from: 1.month.ago, to: Date.today) #=> #<Date: 2014-09-24> |
| 154 | + # |
| 155 | + # @faker.version next |
| 156 | + def on_day_of_week_between(day:, from:, to:) |
| 157 | + days = [day].flatten |
| 158 | + raise ArgumentError, 'Day of week cannot be empty' if days.empty? |
| 159 | + |
| 160 | + # Convert given days of the week to numbers used by `Date#wday` method |
| 161 | + numeric_weekdays = days.map do |d| |
| 162 | + DAYS_OF_WEEK.index(d.to_sym.downcase) || raise(ArgumentError, "#{d} is not a valid day of the week") |
| 163 | + end |
| 164 | + |
| 165 | + from = get_date_object(from) |
| 166 | + to = get_date_object(to) |
| 167 | + date = Faker::Base.rand_in_range(from, to) |
| 168 | + |
| 169 | + # If the initial date is not on one of the wanted days of the week... |
| 170 | + unless numeric_weekdays.include? date.wday |
| 171 | + # ...pick a date nearby that is on one of the wanted days of the week instead |
| 172 | + date += sample(numeric_weekdays) - date.wday |
| 173 | + |
| 174 | + # Move date 1 week earlier or later if the adjusted date is now outside the date range |
| 175 | + date += 7 if date < from |
| 176 | + date -= 7 if date > to |
| 177 | + |
| 178 | + if date > to || date < from |
| 179 | + raise ArgumentError, |
| 180 | + "There is no #{DAYS_OF_WEEK[date.wday].capitalize} between #{from} and #{to}. Increase the from/to date range or choose a different day of the week." |
| 181 | + end |
| 182 | + end |
| 183 | + |
| 184 | + date |
| 185 | + end |
| 186 | + |
139 | 187 | private
|
140 | 188 |
|
141 | 189 | def birthday_date(date, age)
|
|
0 commit comments