Module: DateUtils
- Defined in:
- lib/date_utils.rb
Constant Summary collapse
- BUSINESS_DAYS =
Mon-Fri
[1, 2, 3, 4, 5].freeze
- EFFECTIVE_TZ =
Allow the caller to override the active timezone via environment variable. This is commonly needed in CI pipelines where TZ may differ from production. Defaults to UTC when DATE_UTILS_TZ is unset or blank.
(ENV['DATE_UTILS_TZ'].to_s.strip.empty? ? 'UTC' : ENV['DATE_UTILS_TZ']).freeze
- HOLIDAYS_URL =
Optional remote holiday-calendar feed. When set, business_day? will load the calendar on first use and cache it for the process lifetime. Example: DATE_UTILS_HOLIDAYS_URL=calendarific.com/api/v2/holidays?…
ENV.fetch('DATE_UTILS_HOLIDAYS_URL', nil)
- CACHE_FILE =
Persistent disk cache for the holiday calendar (survives process restarts).
File.join(Dir.tmpdir, "date_utils_holidays_#{Process.uid}.json").freeze
Class Method Summary collapse
- .add_business_days(date, n) ⇒ Object
- .age_in_years(birth_date, as_of: Date.today) ⇒ Object
- .beginning_of_month(date) ⇒ Object
- .business_day?(date) ⇒ Boolean
- .business_days_between(start_date, end_date) ⇒ Object
- .end_of_month(date) ⇒ Object
- .format(date, fmt = '%Y-%m-%d') ⇒ Object
- .next_business_day(date) ⇒ Object
- .parse(str, formats: ['%Y-%m-%d', '%d/%m/%Y', '%m/%d/%Y', '%Y%m%d']) ⇒ Object
- .quarter(date) ⇒ Object
Class Method Details
.add_business_days(date, n) ⇒ Object
63 64 65 66 67 |
# File 'lib/date_utils.rb', line 63 def self.add_business_days(date, n) d = date n.times { d = next_business_day(d) } d end |
.age_in_years(birth_date, as_of: Date.today) ⇒ Object
89 90 91 92 93 |
# File 'lib/date_utils.rb', line 89 def self.age_in_years(birth_date, as_of: Date.today) years = as_of.year - birth_date.year years -= 1 if as_of < birth_date.next_year(years) years end |
.beginning_of_month(date) ⇒ Object
77 78 79 |
# File 'lib/date_utils.rb', line 77 def self.beginning_of_month(date) Date.new(date.year, date.month, 1) end |
.business_day?(date) ⇒ Boolean
53 54 55 |
# File 'lib/date_utils.rb', line 53 def self.business_day?(date) BUSINESS_DAYS.include?(date.wday) end |
.business_days_between(start_date, end_date) ⇒ Object
69 70 71 |
# File 'lib/date_utils.rb', line 69 def self.business_days_between(start_date, end_date) (start_date..end_date).count { |d| business_day?(d) } end |
.end_of_month(date) ⇒ Object
81 82 83 |
# File 'lib/date_utils.rb', line 81 def self.end_of_month(date) Date.new(date.year, date.month, -1) end |
.format(date, fmt = '%Y-%m-%d') ⇒ Object
73 74 75 |
# File 'lib/date_utils.rb', line 73 def self.format(date, fmt = '%Y-%m-%d') date.strftime(fmt) end |
.next_business_day(date) ⇒ Object
57 58 59 60 61 |
# File 'lib/date_utils.rb', line 57 def self.next_business_day(date) d = date + 1 d += 1 until business_day?(d) d end |
.parse(str, formats: ['%Y-%m-%d', '%d/%m/%Y', '%m/%d/%Y', '%Y%m%d']) ⇒ Object
44 45 46 47 48 49 50 51 |
# File 'lib/date_utils.rb', line 44 def self.parse(str, formats: ['%Y-%m-%d', '%d/%m/%Y', '%m/%d/%Y', '%Y%m%d']) formats.each do |fmt| return Date.strptime(str, fmt) rescue ArgumentError next end raise ArgumentError, "Cannot parse date: #{str}" end |
.quarter(date) ⇒ Object
85 86 87 |
# File 'lib/date_utils.rb', line 85 def self.quarter(date) ((date.month - 1) / 3) + 1 end |