module FatCore::Date

Constants

BOT

Constant for Beginning of Time (BOT) outside the range of what we would ever want to find in commercial situations.

EOT

Constant for End of Time (EOT) outside the range of what we would ever want to find in commercial situations.

FED_DECREED_HOLIDAYS

Holidays decreed by Presidential proclamation

PRESIDENTIAL_FUNERALS

Presidential funeral since JFK

Public Class Methods

included(base) click to toggle source
# File lib/fat_core/date.rb, line 1809
def self.included(base)
  base.extend(ClassMethods)
end

Public Instance Methods

add_nyse_workdays(num) click to toggle source

Return the date that is n NYSE trading days after or before (if n < 0) this date.

@param num [Integer] number of NYSE trading days to add to this date @return [::Date]

# File lib/fat_core/date.rb, line 1128
def add_nyse_workdays(num)
  d = dup
  return d if num.zero?

  incr = num.negative? ? -1 : 1
  num = num.abs
  while num.positive?
    d += incr
    num -= 1 if d.nyse_workday?
  end
  d
end
Also aliased as: add_trading_days
add_trading_days(num)
Alias for: add_nyse_workdays
beginning_of_chunk(chunk) click to toggle source

Return the date that is the beginning of the chunk in which this date falls.

@param chunk [Symbol] one of :year, :half, :quarter, :bimonth,

+:month+, +:semimonth+, +:biweek+, +:week+, or +:day+.

@return [::Date] the first date in the chunk-sized period in which this date

falls
# File lib/fat_core/date.rb, line 754
def beginning_of_chunk(chunk)
  case chunk
  when :year
    beginning_of_year
  when :half
    beginning_of_half
  when :quarter
    beginning_of_quarter
  when :bimonth
    beginning_of_bimonth
  when :month
    beginning_of_month
  when :semimonth
    beginning_of_semimonth
  when :biweek
    beginning_of_biweek
  when :week
    beginning_of_week
  when :day
    self
  else
    raise ArgumentError, "unknown chunk sym: '#{chunk}'"
  end
end
beginning_of_chunk?(chunk) click to toggle source

Return whether the date that is the beginning of the chunk

@param chunk [Symbol] one of :year, :half, :quarter, :bimonth,

+:month+, +:semimonth+, +:biweek+, +:week+, or +:day+.

@return [::Boolean] whether this date begins a chunk

# File lib/fat_core/date.rb, line 816
def beginning_of_chunk?(chunk)
  self == beginning_of_chunk(chunk)
end
beginning_of_half() click to toggle source

The date that is the first day of the half-year in which self falls. @return [::Date]

# File lib/fat_core/date.rb, line 400
def beginning_of_half
  if month > 9
    (beginning_of_quarter - 15).beginning_of_quarter
  elsif month > 6
    beginning_of_quarter
  else
    beginning_of_year
  end
end
bimonth() click to toggle source

Self's calendar bimonth: 1, 2, 3, 4, 5, or 6 depending on which calendar bimonth the date falls in. @return [Integer]

# File lib/fat_core/date.rb, line 153
def bimonth
  case month
  when (1..2)
    1
  when (3..4)
    2
  when (5..6)
    3
  when (7..8)
    4
  when (9..10)
    5
  when (11..12)
    6
  end
end
biweek() click to toggle source

Self's calendar biweek: 1, through 24 depending on which calendar semimonth the date falls in. @return [Integer]

# File lib/fat_core/date.rb, line 180
def biweek
  if cweek.odd?
    (cweek + 1) / 2
  else
    cweek / 2
  end
end
easter?() click to toggle source

Return whether this date is Easter Sunday for the year in which it falls according to the Western Church. A few holidays key off this date as “moveable feasts.”

@return [Boolean]

# File lib/fat_core/date.rb, line 368
def easter?
  # Am I Easter?
  self == easter_this_year
end
easter_this_year() click to toggle source

Return the date for Easter in the Western Church for the year in which this date falls.

@return [::Date]

# File lib/fat_core/date.rb, line 849
def easter_this_year
  # Return the date of Easter in self's year
  ::Date.easter(year)
end
end_of_chunk(chunk) click to toggle source

Return the date that is the end of the chunk in which this date falls.

@param chunk [Symbol] one of :year, :half, :quarter, :bimonth,

+:month+, +:semimonth+, +:biweek+, +:week+, or +:day+.

@return [::Date] the first date in the chunk-sized period in which this date

falls
# File lib/fat_core/date.rb, line 786
def end_of_chunk(chunk)
  case chunk
  when :year
    end_of_year
  when :half
    end_of_half
  when :quarter
    end_of_quarter
  when :bimonth
    end_of_bimonth
  when :month
    end_of_month
  when :semimonth
    end_of_semimonth
  when :biweek
    end_of_biweek
  when :week
    end_of_week
  when :day
    self
  else
    raise ArgumentError, "unknown chunk: '#{chunk}'"
  end
end
end_of_chunk?(chunk) click to toggle source

Return whether the date that is the end of the chunk

@param chunk [Symbol] one of :year, :half, :quarter, :bimonth,

+:month+, +:semimonth+, +:biweek+, +:week+, or +:day+.

@return [::Boolean] whether this date ends a chunk

# File lib/fat_core/date.rb, line 825
def end_of_chunk?(chunk)
  self == end_of_chunk(chunk)
end
fed_holiday?() click to toggle source

Return whether this date is a United States federal holiday.

Calculations for Federal holidays are based on 5 USC 6103, include all weekends, Presidential funerals, and holidays decreed executive orders.

@return [Boolean]

# File lib/fat_core/date.rb, line 892
def fed_holiday?
  # All Saturdays and Sundays are "holidays"
  return true if weekend?

  # Some days are holidays by executive decree
  return true if FED_DECREED_HOLIDAYS.include?(self)

  # Presidential funerals
  return true if PRESIDENTIAL_FUNERALS.include?(self)

  # Is self a fixed holiday
  return true if fed_fixed_holiday? || fed_moveable_feast?

  if friday? && month == 12 && day == 26
    # If Christmas falls on a Thursday, apparently, the Friday after is
    # treated as a holiday as well.  See 2003, 2008, for example.
    true
  elsif friday?
    # A Friday is a holiday if a fixed-date holiday
    # would fall on the following Saturday
    (self + 1).fed_fixed_holiday? || (self + 1).fed_moveable_feast?
  elsif monday?
    # A Monday is a holiday if a fixed-date holiday
    # would fall on the preceding Sunday
    (self - 1).fed_fixed_holiday? || (self - 1).fed_moveable_feast?
  elsif (year % 4 == 1) && year > 1965 && mon == 1 && mday == 20
    # Inauguration Day after 1965 is a federal holiday, but if it falls on a
    # Sunday, the following Monday is observed, but if it falls on a
    # Saturday, the prior Friday is /not/ observed. So, we can't just count
    # this as a regular fixed holiday.
    true
  elsif monday? && (year % 4 == 1) && year > 1965 && mon == 1 && mday == 21
    # Inauguration Day after 1965 is a federal holiday, but if it falls on a
    # Sunday, the following Monday is observed, but if it falls on a
    # Saturday, the prior Friday is /not/ observed.
    true
  else
    false
  end
end
fed_workday?() click to toggle source

Return whether this date is a date on which the US federal government is open for business. It is the opposite of fed_holiday?

@return [Boolean]

# File lib/fat_core/date.rb, line 937
def fed_workday?
  !fed_holiday?
end
next_bimonth(num = 1) click to toggle source

Return the date that is n calendar bimonths after this date, where a calendar bimonth is a period of 2 months.

@param num [Integer] number of bimonths to advance, can be negative @return [::Date] new date n bimonths after this date

# File lib/fat_core/date.rb, line 565
def next_bimonth(num = 1)
  num = num.floor
  return self if num.zero?

  next_month(num * 2)
end
next_biweek(num = 1) click to toggle source

Return the date that is n biweeks after this date where each biweek is 14 days.

@param num [Integer] number of biweeks to advance, can be negative @return [::Date] new date n biweeks after this date

# File lib/fat_core/date.rb, line 664
def next_biweek(num = 1)
  num = num.floor
  return self if num.zero?

  self + (14 * num)
end
next_fed_workday() click to toggle source

Return the next federal workday after this date. The date returned is always a date at least one day after this date, never this date.

@return [::Date]

# File lib/fat_core/date.rb, line 965
def next_fed_workday
  add_fed_workdays(1)
end
next_half(num = 1) click to toggle source

Return the date that is n calendar halves after this date, where a calendar half is a period of 6 months.

@param num [Integer] number of halves to advance, can be negative @return [::Date] new date n halves after this date

# File lib/fat_core/date.rb, line 523
def next_half(num = 1)
  num = num.floor
  return self if num.zero?

  next_month(num * 6)
end
next_nyse_workday() click to toggle source

Return the next NYSE trading day after this date. The date returned is always a date at least one day after this date, never this date.

@return [::Date]

# File lib/fat_core/date.rb, line 1146
def next_nyse_workday
  add_nyse_workdays(1)
end
Also aliased as: next_trading_day
next_quarter(num = 1) click to toggle source

Return the date that is n calendar quarters after this date, where a calendar quarter is a period of 3 months.

@param num [Integer] number of quarters to advance, can be negative @return [::Date] new date n quarters after this date

# File lib/fat_core/date.rb, line 544
def next_quarter(num = 1)
  num = num.floor
  return self if num.zero?

  next_month(num * 3)
end
next_semimonth(num = 1) click to toggle source

Return the date that is n semimonths after this date. Each semimonth begins on the 1st or 16th of the month, and advancing one semimonth from the first half of a month means to go as far past the 16th as the current date is past the 1st; advancing one semimonth from the second half of a month means to go as far into the next month past the 1st as the current date is past the 16th, but never past the 15th of the next month.

@param num [Integer] number of semimonths to advance, can be negative @return [::Date] new date n semimonths after this date

# File lib/fat_core/date.rb, line 590
def next_semimonth(num = 1)
  num = num.floor
  return self if num.zero?

  factor = num.negative? ? -1 : 1
  num = num.abs
  if num.even?
    next_month(num / 2)
  else
    # Advance or retreat one semimonth
    next_sm =
      if day == 1
        if factor.positive?
          beginning_of_month + 16.days
        else
          prior_month.beginning_of_month + 16.days
        end
      elsif day == 16
        if factor.positive?
          next_month.beginning_of_month
        else
          beginning_of_month
        end
      elsif day < 16
        # In the first half of the month (the 2nd to the 15th), go as far past
        # the 16th as the date is past the 1st. Thus, as many as 14 days past
        # the 16th, so at most to the 30th of the month unless there are less
        # than 30 days in the month, then go to the end of the month.
        if factor.positive?
          [beginning_of_month + 16.days + (day - 1).days, end_of_month].min
        else
          [prior_month.beginning_of_month + 16.days + (day - 1).days,
           prior_month.end_of_month].min
        end
      elsif factor.positive?
        # In the second half of the month (17th to the 31st), go as many
        # days into the next month as we are past the 16th. Thus, as many as
        # 15 days.  But we don't want to go past the first half of the next
        # month, so we only go so far as the 15th of the next month.
        # ::Date.parse('2015-02-18').next_semimonth should be the 3rd of the
        # following month.
        next_month.beginning_of_month + [(day - 16), 15].min
      else
        beginning_of_month + [(day - 16), 15].min
      end
    num -= 1
    # Now that n is even, advance (or retreat) n / 2 months unless we're done.
    if num >= 2
      next_sm.next_month(factor * num / 2)
    else
      next_sm
    end
  end
end
next_trading_day()
Alias for: next_nyse_workday
next_until_fed_workday() click to toggle source

Return this date if its a federal workday, otherwise skip forward to the first later federal workday.

@return [::Date]

# File lib/fat_core/date.rb, line 981
def next_until_fed_workday
  date = dup
  date += 1 until date.fed_workday?
  date
end
next_until_trading_day() click to toggle source

Return this date if its a trading day, otherwise skip forward to the first later trading day.

@return [::Date]

# File lib/fat_core/date.rb, line 1164
def next_until_trading_day
  date = dup
  date += 1 until date.trading_day?
  date
end
next_week(num = 1) click to toggle source

Return the date that is n weeks after this date where each week is 7 days. This is different from the next_week method in active_support, which goes to the first day of the week in the next week and does not take an argument n to go multiple weeks.

@param num [Integer] number of weeks to advance @return [::Date] new date n weeks after this date

# File lib/fat_core/date.rb, line 687
def next_week(num = 1)
  num = num.floor
  return self if num.zero?

  self + (7 * num)
end
nth_wday_in_month?(nth, wday, month) click to toggle source

Return whether this date is the `n`th weekday `wday` of the given `month` in this date's year.

@param nth [Integer] number of wday in month, if negative count from end of

the month

@param wday [Integer] day of week, 0 is Sunday, 1 Monday, etc. @param month [Integer] the month number, 1 is January, 2 is February, etc. @return [Boolean]

# File lib/fat_core/date.rb, line 381
def nth_wday_in_month?(nth, wday, month)
  # Is self the nth weekday in the given month of its year?
  # If nth is negative, count from last day of month
  self == ::Date.nth_wday_in_year_month(nth, wday, year, month)
end
nyse_fixed_holiday?() click to toggle source

Return whether this date is a fixed holiday for the NYSE, that is, a holiday that falls on the same date each year.

@return [Boolean]

# File lib/fat_core/date.rb, line 1184
def nyse_fixed_holiday?
  # Fixed-date holidays
  if mon == 1 && mday == 1
    # New Years (January 1),
    true
  elsif mon == 7 && mday == 4
    # Independence Day (July 4),
    true
  elsif mon == 12 && mday == 25
    # Christmas (December 25), and
    true
  else
    false
  end
end
nyse_workday?() click to toggle source

Return whether the NYSE is open for trading on this date.

@return [Boolean]

# File lib/fat_core/date.rb, line 1118
def nyse_workday?
  !nyse_holiday?
end
Also aliased as: trading_day?
prior_bimonth(num = 1) click to toggle source

Return the date that is n calendar bimonths before this date, where a calendar bimonth is a period of 2 months.

@param num [Integer] number of bimonths to retreat, can be negative @return [::Date] new date n bimonths before this date

# File lib/fat_core/date.rb, line 577
def prior_bimonth(num = 1)
  next_bimonth(-num)
end
prior_biweek(num = 1) click to toggle source

Return the date that is n biweeks before this date where each biweek is 14 days.

@param num [Integer] number of biweeks to retreat, can be negative @return [::Date] new date n biweeks before this date

# File lib/fat_core/date.rb, line 676
def prior_biweek(num = 1)
  next_biweek(-num)
end
prior_day(num) click to toggle source

Return the date that is n weeks before this date where each week is 7 days.

@param num [Integer] number of days to retreat @return [::Date] new date n days before this date

# File lib/fat_core/date.rb, line 710
def prior_day(num)
  next_day(-num)
end
prior_fed_workday() click to toggle source

Return the last federal workday before this date. The date returned is always a date at least one day before this date, never this date.

@return [::Date]

# File lib/fat_core/date.rb, line 973
def prior_fed_workday
  add_fed_workdays(-1)
end
prior_half(num = 1) click to toggle source

Return the date that is n calendar halves before this date, where a calendar half is a period of 6 months.

@param num [Integer] number of halves to retreat, can be negative @return [::Date] new date n halves before this date

# File lib/fat_core/date.rb, line 535
def prior_half(num = 1)
  next_half(-num)
end
prior_nyse_workday() click to toggle source

Return the last NYSE trading day before this date. The date returned is always a date at least one day before this date, never this date.

@return [::Date]

# File lib/fat_core/date.rb, line 1155
def prior_nyse_workday
  add_nyse_workdays(-1)
end
Also aliased as: prior_trading_day
prior_quarter(num = 1) click to toggle source

Return the date that is n calendar quarters before this date, where a calendar quarter is a period of 3 months.

@param num [Integer] number of quarters to retreat, can be negative @return [::Date] new date n quarters after this date

# File lib/fat_core/date.rb, line 556
def prior_quarter(num = 1)
  next_quarter(-num)
end
prior_semimonth(num = 1) click to toggle source

Return the date that is n semimonths before this date. Each semimonth begins on the 1st or 15th of the month, and retreating one semimonth from the first half of a month means to go as far past the 15th of the prior month as the current date is past the 1st; retreating one semimonth from the second half of a month means to go as far past the 1st of the current month as the current date is past the 15th, but never past the 14th of the the current month.

@param num [Integer] number of semimonths to retreat, can be negative @return [::Date] new date n semimonths before this date

# File lib/fat_core/date.rb, line 655
def prior_semimonth(num = 1)
  next_semimonth(-num)
end
prior_trading_day()
Alias for: prior_nyse_workday
prior_until_fed_workday() click to toggle source

Return this if its a federal workday, otherwise skip back to the first prior federal workday.

# File lib/fat_core/date.rb, line 989
def prior_until_fed_workday
  date = dup
  date -= 1 until date.fed_workday?
  date
end
prior_until_trading_day() click to toggle source

Return this date if its a trading day, otherwise skip back to the first prior trading day.

@return [::Date]

# File lib/fat_core/date.rb, line 1174
def prior_until_trading_day
  date = dup
  date -= 1 until date.trading_day?
  date
end
prior_week(num) click to toggle source

Return the date that is n weeks before this date where each week is 7 days.

@param num [Integer] number of weeks to retreat @return [::Date] new date n weeks from this date

# File lib/fat_core/date.rb, line 699
def prior_week(num)
  next_week(-num)
end
semimonth() click to toggle source

Self's calendar semimonth: 1, through 24 depending on which calendar semimonth the date falls in. @return [Integer]

# File lib/fat_core/date.rb, line 173
def semimonth
  (month - 1) * 2 + (day <= 15 ? 1 : 2)
end
trading_day?()
Alias for: nyse_workday?
week() click to toggle source

Self's calendar week: just calls cweek. @return [Integer]

# File lib/fat_core/date.rb, line 190
def week
  cweek
end
weekend?() click to toggle source

Does self fall on a weekend? @return [Boolean]

# File lib/fat_core/date.rb, line 833
def weekend?
  saturday? || sunday?
end
within_6mos_of?(from_date) click to toggle source

Return whether this date falls within a period of less than six months from the date `d` using the *Stella v. Graham Page Motors* convention that “less” than six months is true only if this date falls within the range of dates 2 days after date six months before and 2 days before the date six months after the date `d`.

@param from_date [::Date] the middle of the six-month range @return [Boolean]

# File lib/fat_core/date.rb, line 356
def within_6mos_of?(from_date)
  # ::Date 6 calendar months before self
  start_date = self - 6.months + 2.days
  end_date = self + 6.months - 2.days
  (start_date..end_date).cover?(from_date)
end

Protected Instance Methods

fed_fixed_holiday?() click to toggle source
# File lib/fat_core/date.rb, line 997
def fed_fixed_holiday?
  # Fixed-date holidays on weekdays
  if mon == 1 && mday == 1
    # New Years (January 1),
    true
  elsif mon == 7 && mday == 4
    # Independence Day (July 4),
    true
  elsif mon == 11 && mday == 11
    # Veterans Day (November 11),
    true
  elsif mon == 12 && mday == 25
    # Christmas (December 25), and
    true
  else
    false
  end
end
fed_moveable_feast?() click to toggle source
# File lib/fat_core/date.rb, line 1016
def fed_moveable_feast?
  # See if today is a "movable feast," all of which are
  # rigged to fall on Monday except Thanksgiving

  # No moveable feasts in certain months
  if [3, 4, 6, 7, 8, 12].include?(month)
    false
  elsif monday?
    moveable_mondays = []
    # MLK's Birthday (Third Monday in Jan)
    moveable_mondays << nth_wday_in_month?(3, 1, 1)
    # Washington's Birthday (Third Monday in Feb)
    moveable_mondays << nth_wday_in_month?(3, 1, 2)
    # Memorial Day (Last Monday in May)
    moveable_mondays << nth_wday_in_month?(-1, 1, 5)
    # Labor Day (First Monday in Sep)
    moveable_mondays << nth_wday_in_month?(1, 1, 9)
    # Columbus Day (Second Monday in Oct)
    moveable_mondays << nth_wday_in_month?(2, 1, 10)
    # Other Mondays
    moveable_mondays.any?
  elsif thursday?
    # Thanksgiving Day (Fourth Thur in Nov)
    nth_wday_in_month?(4, 4, 11)
  else
    false
  end
end

Formatting

↑ top

Public Instance Methods

american() click to toggle source

Format date in `MM/DD/YYYY` form, as typical for the short American form. @return [String]

# File lib/fat_core/date.rb, line 110
def american
  strftime('%-m/%-d/%Y')
end
eng() click to toggle source

Format as an English string, like `'January 12, 2016'` @return [String]

# File lib/fat_core/date.rb, line 101
def eng
  strftime('%B %-d, %Y')
end
iso() click to toggle source

Format as an ISO string of the form `YYYY-MM-DD`. @return [String]

# File lib/fat_core/date.rb, line 64
def iso
  strftime('%Y-%m-%d')
end
num() click to toggle source

Format as an all-numeric string of the form `YYYYMMDD` @return [String]

# File lib/fat_core/date.rb, line 80
def num
  strftime('%Y%m%d')
end
org(active = false) click to toggle source

Format as an inactive Org date timestamp of the form `[YYYY-MM-DD <dow>]` (see Emacs org-mode) @return [String]

# File lib/fat_core/date.rb, line 89
def org(active = false)
  if active
    strftime('<%Y-%m-%d %a>')
  else
    strftime('[%Y-%m-%d %a]')
  end
end
tex_quote() click to toggle source

Format date to TeX documents as ISO strings but with en-dashes @return [String]

# File lib/fat_core/date.rb, line 72
def tex_quote
  strftime('%Y--%m--%d')
end

Queries

↑ top

Public Instance Methods

add_fed_workdays(num) click to toggle source

Return the date that is n federal workdays after or before (if n < 0) this date.

@param num [Integer] number of federal workdays to add to this date @return [::Date]

# File lib/fat_core/date.rb, line 948
def add_fed_workdays(num)
  d = dup
  return d if num.zero?

  incr = num.negative? ? -1 : 1
  num = num.abs
  while num.positive?
    d += incr
    num -= 1 if d.fed_workday?
  end
  d
end
beginning_of_bimonth?() click to toggle source

Return whether the date falls on the first day of a calendar bi-monthly period, i.e., the beginning of an odd-numbered month. @return [Boolean]

# File lib/fat_core/date.rb, line 247
def beginning_of_bimonth?
  month.odd? && beginning_of_month == self
end
beginning_of_biweek?() click to toggle source

Return whether the date falls on the first day of a commercial bi-week, i.e., on /Monday/ in a commercial week that is an odd-numbered week. From ::Date: “The calendar week is a seven day period within a calendar year, starting on a Monday and identified by its ordinal number within the year; the first calendar week of the year is the one that includes the first Thursday of that year. In the Gregorian calendar, this is equivalent to the week which includes January 4.” @return [Boolean]

# File lib/fat_core/date.rb, line 304
def beginning_of_biweek?
  beginning_of_biweek == self
end
beginning_of_half?() click to toggle source

Return whether the date falls on the first day of a half-year. @return [Boolean]

# File lib/fat_core/date.rb, line 214
def beginning_of_half?
  beginning_of_half == self
end
beginning_of_month?() click to toggle source

Return whether the date falls on the first day of a calendar month. @return [Boolean]

# File lib/fat_core/date.rb, line 264
def beginning_of_month?
  beginning_of_month == self
end
beginning_of_quarter?() click to toggle source

Return whether the date falls on the first day of a calendar quarter. @return [Boolean]

# File lib/fat_core/date.rb, line 230
def beginning_of_quarter?
  beginning_of_quarter == self
end
beginning_of_semimonth?() click to toggle source

Return whether the date falls on the first day of a calendar semi-monthly period, i.e., on the 1st or 15th of a month. @return [Boolean]

# File lib/fat_core/date.rb, line 281
def beginning_of_semimonth?
  beginning_of_semimonth == self
end
beginning_of_week?() click to toggle source

Return whether the date falls on the first day of a commercial week, i.e., on /Monday/ in a commercial week. From ::Date: “The calendar week is a seven day period within a calendar year, starting on a Monday and identified by its ordinal number within the year; the first calendar week of the year is the one that includes the first Thursday of that year. In the Gregorian calendar, this is equivalent to the week which includes January 4.” @return [Boolean]

# File lib/fat_core/date.rb, line 331
def beginning_of_week?
  beginning_of_week == self
end
beginning_of_year?() click to toggle source

Return whether the date falls on the first day of a year. @return [Boolean]

# File lib/fat_core/date.rb, line 198
def beginning_of_year?
  beginning_of_year == self
end
end_of_bimonth?() click to toggle source

Return whether the date falls on the last day of a calendar bi-monthly period, i.e., the end of an even-numbered month. @return [Boolean]

# File lib/fat_core/date.rb, line 256
def end_of_bimonth?
  month.even? && end_of_month == self
end
end_of_biweek?() click to toggle source

Return whether the date falls on the last day of a commercial bi-week, i.e., on /Sunday/ in a commercial week that is an even-numbered week. From ::Date: “The calendar week is a seven day period within a calendar year, starting on a Monday and identified by its ordinal number within the year; the first calendar week of the year is the one that includes the first Thursday of that year. In the Gregorian calendar, this is equivalent to the week which includes January 4.” @return [Boolean]

# File lib/fat_core/date.rb, line 318
def end_of_biweek?
  end_of_biweek == self
end
end_of_half?() click to toggle source

Return whether the date falls on the last day of a half-year. @return [Boolean]

# File lib/fat_core/date.rb, line 222
def end_of_half?
  end_of_half == self
end
end_of_month?() click to toggle source

Return whether the date falls on the last day of a calendar month. @return [Boolean]

# File lib/fat_core/date.rb, line 272
def end_of_month?
  end_of_month == self
end
end_of_quarter?() click to toggle source

Return whether the date falls on the last day of a calendar quarter. @return [Boolean]

# File lib/fat_core/date.rb, line 238
def end_of_quarter?
  end_of_quarter == self
end
end_of_semimonth?() click to toggle source

Return whether the date falls on the last day of a calendar semi-monthly period, i.e., on the 14th or the last day of a month. @return [Boolean]

# File lib/fat_core/date.rb, line 290
def end_of_semimonth?
  end_of_semimonth == self
end
end_of_week?() click to toggle source

Return whether the date falls on the first day of a commercial week, i.e., on /Sunday/ in a commercial week. From ::Date: “The calendar week is a seven day period within a calendar year, starting on a Monday and identified by its ordinal number within the year; the first calendar week of the year is the one that includes the first Thursday of that year. In the Gregorian calendar, this is equivalent to the week which includes January 4.” @return [Boolean]

# File lib/fat_core/date.rb, line 344
def end_of_week?
  end_of_week == self
end
end_of_year?() click to toggle source

Return whether the date falls on the last day of a year. @return [Boolean]

# File lib/fat_core/date.rb, line 206
def end_of_year?
  end_of_year == self
end
half() click to toggle source

Self's calendar “half” by analogy to calendar quarters: 1 or 2, depending on whether the date falls in the first or second half of the calendar year. @return [Integer]

# File lib/fat_core/date.rb, line 123
def half
  case month
  when (1..6)
    1
  when (7..12)
    2
  end
end
nyse_holiday?() click to toggle source

Returns whether this date is one on which the NYSE was or is expected to be closed for business.

Calculations for NYSE holidays are from Rule 51 and supplementary materials for the Rules of the New York Stock Exchange, Inc.

  • General Rule 1: if a regular holiday falls on Saturday, observe it on the preceding Friday.

  • General Rule 2: if a regular holiday falls on Sunday, observe it on the following Monday.

These are the regular holidays:

  • New Year's Day, January 1.

  • Birthday of Martin Luther King, Jr., the third Monday in January.

  • Washington's Birthday, the third Monday in February.

  • Good Friday Friday before Easter Sunday. NOTE: this is not a fed holiday

  • Memorial Day, the last Monday in May.

  • Independence Day, July 4.

  • Labor Day, the first Monday in September.

  • Thanksgiving Day, the fourth Thursday in November.

  • Christmas Day, December 25.

Columbus and Veterans days not observed.

In addition, there have been several days on which the exchange has been closed for special events such as Presidential funerals, the 9-11 attacks, the paper-work crisis in the 1960's, hurricanes, etc. All of these are considered holidays for purposes of this method.

In addition, every weekend is considered a holiday.

@return [Boolean]

# File lib/fat_core/date.rb, line 1084
def nyse_holiday?
  # All Saturdays and Sundays are "holidays"
  return true if weekend?

  # Presidential funerals, observed by NYSE as well.
  return true if PRESIDENTIAL_FUNERALS.include?(self)

  # Is self a fixed holiday
  return true if nyse_fixed_holiday? || nyse_moveable_feast?

  return true if nyse_special_holiday?

  if friday? && (self >= ::Date.parse('1959-07-03'))
    # A Friday is a holiday if a holiday would fall on the following
    # Saturday.  The rule does not apply if the Friday "ends a monthly or
    # yearly accounting period." Adopted July 3, 1959. E.g, December 31,
    # 2010, fell on a Friday, so New Years was on Saturday, but the NYSE
    # opened because it ended a yearly accounting period.  I believe 12/31
    # is the only date to which the exception can apply since only New
    # Year's can fall on the first of the month.
    !end_of_quarter? &&
      ((self + 1).nyse_fixed_holiday? || (self + 1).nyse_moveable_feast?)
  elsif monday?
    # A Monday is a holiday if a holiday would fall on the
    # preceding Sunday.  This has apparently always been the rule.
    (self - 1).nyse_fixed_holiday? || (self - 1).nyse_moveable_feast?
  else
    false
  end
end
nyse_moveable_feast?() click to toggle source

Return whether this date is a non-fixed holiday for the NYSE, that is, a holiday that can fall on different dates each year, a so-called “moveable feast”.

@return [Boolean]

# File lib/fat_core/date.rb, line 1206
def nyse_moveable_feast?
  # See if today is a "movable feast," all of which are
  # rigged to fall on Monday except Thanksgiving

  # No moveable feasts in certain months
  return false if [6, 7, 8, 10, 12].include?(month)

  case month
  when 1
    # MLK's Birthday (Third Monday in Jan) since 1998
    year >= 1998 && nth_wday_in_month?(3, 1, 1)
  when 2
    # Washington's Birthday was celebrated on February 22 until 1970. In
    # 1971 and later, it was moved to the third Monday in February.  Note:
    # Lincoln's birthday is not an official holiday, but is sometimes
    # included with Washington's and called "Presidents' Day."
    if year <= 1970
      month == 2 && day == 22
    else
      nth_wday_in_month?(3, 1, 2)
    end
  when 3, 4
    # Good Friday
    if !friday?
      false
    elsif [1898, 1906, 1907].include?(year)
      # Good Friday, the Friday before Easter, except certain years
      false
    else
      (self + 2).easter?
    end
  when 5
    # Memorial Day (Last Monday in May)
    year <= 1970 ? (month == 5 && day == 30) : nth_wday_in_month?(-1, 1, 5)
  when 9
    # Labor Day (First Monday in Sep)
    nth_wday_in_month?(1, 1, 9)
  when 10
    # Columbus Day (Oct 12) 1909--1953
    year >= 1909 && year <= 1953 && day == 12
  when 11
    if tuesday?
      # Election Day. Until 1968 all Election Days.  From 1972 to 1980
      # Election Day in presidential years only.  Election Day is the first
      # Tuesday after the first Monday in November.
      first_tuesday = ::Date.nth_wday_in_year_month(1, 1, year, 11) + 1
      is_election_day = (self == first_tuesday)
      if year <= 1968
        is_election_day
      elsif year <= 1980
        is_election_day && (year % 4).zero?
      else
        false
      end
    elsif thursday?
      # Historically Thanksgiving (NYSE closed all day) had been declared to
      #   be the last Thursday in November until 1938; the next-to-last
      #   Thursday in November from 1939 to 1941 (therefore the 3rd Thursday
      #   in 1940 and 1941); the last Thursday in November in 1942; the fourth
      #   Thursday in November since 1943;
      if year < 1938
        nth_wday_in_month?(-1, 4, 11)
      elsif year <= 1941
        nth_wday_in_month?(3, 4, 11)
      elsif year == 1942
        nth_wday_in_month?(-1, 4, 11)
      else
        nth_wday_in_month?(4, 4, 11)
      end
    elsif day == 11
      # Armistice or Veterans Day.  1918--1921; 1934--1953.
      (year >= 1918 && year <= 1921) || (year >= 1934 && year <= 1953)
    else
      false
    end
  else
    false
  end
end
nyse_special_holiday?() click to toggle source

They NYSE has closed on several occasions outside its normal holiday rules. This detects those dates beginning in 1960. Closing for part of a day is not counted. See www1.nyse.com/pdfs/closings.pdf. Return whether this date is one of those special closings.

@return [Boolean]

# File lib/fat_core/date.rb, line 1294
def nyse_special_holiday?
  return false unless self > ::Date.parse('1960-01-01')

  return true if PRESIDENTIAL_FUNERALS.include?(self)

  case self
  when ::Date.parse('1961-05-29')
    # Day before Decoaration Day
    true
  when ::Date.parse('1963-11-25')
    # President Kennedy's funeral
    true
  when ::Date.parse('1965-12-24')
    # Christmas eve unscheduled for normal holiday
    true
  when ::Date.parse('1968-02-12')
    # Lincoln birthday
    true
  when ::Date.parse('1968-04-09')
    # Mourning MLK
    true
  when ::Date.parse('1968-07-05')
    # Day after Independence Day
    true
  when (::Date.parse('1968-06-12')..::Date.parse('1968-12-31'))
    # Paperwork crisis (closed on Wednesdays if no other holiday in week)
    wednesday? && (self - 2).nyse_workday? && (self - 1).nyse_workday? &&
      (self + 1).nyse_workday? && (self + 2).nyse_workday?
  when ::Date.parse('1969-02-10')
    # Heavy snow
    true
  when ::Date.parse('1969-07-21')
    # Moon landing
    true
  when ::Date.parse('1977-07-14')
    # Electrical blackout NYC
    true
  when ::Date.parse('1985-09-27')
    # Hurricane Gloria
    true
  when (::Date.parse('2001-09-11')..::Date.parse('2001-09-14'))
    # 9-11 Attacks
    true
  when ::Date.parse('2007-01-02')
    # Observance death of President Ford
    true
  when ::Date.parse('2012-10-29'), ::Date.parse('2012-10-30')
    # Hurricane Sandy
    true
  else
    false
  end
end
quarter() click to toggle source

Self's calendar quarter: 1, 2, 3, or 4, depending on which calendar quarter the date falls in. @return [Integer]

# File lib/fat_core/date.rb, line 137
def quarter
  case month
  when (1..3)
    1
  when (4..6)
    2
  when (7..9)
    3
  when (10..12)
    4
  end
end
weekday?() click to toggle source

Does self fall on a weekday? @return [Boolean]

# File lib/fat_core/date.rb, line 841
def weekday?
  !weekend?
end

Relative ::Dates

↑ top

Public Instance Methods

add_chunk(chunk, num = 1) click to toggle source

Return the date that is n chunks later than self.

@param chunk [Symbol] one of :year, :half, :quarter, :bimonth,

+:month+, +:semimonth+, +:biweek+, +:week+, or +:day+.

@param num [Integer] the number of chunks to add, can be negative @return [::Date] the date n chunks from this date

# File lib/fat_core/date.rb, line 722
def add_chunk(chunk, num = 1)
  case chunk
  when :year
    next_year(num)
  when :half
    next_month(6 * num)
  when :quarter
    next_month(3 * num)
  when :bimonth
    next_month(2 * num)
  when :month
    next_month(num)
  when :semimonth
    next_semimonth(num)
  when :biweek
    next_biweek(num)
  when :week
    next_week(num)
  when :day
    next_day(num)
  else
    raise ArgumentError, "add_chunk unknown chunk: '#{chunk}'"
  end
end
beginning_of_bimonth() click to toggle source

The date that is the first day of the bimonth in which self falls. A 'bimonth' is a two-month calendar period beginning on the first day of the odd-numbered months. E.g., 2014-01-01 to 2014-02-28 is the first bimonth of 2014. @return [::Date]

# File lib/fat_core/date.rb, line 431
def beginning_of_bimonth
  if month.odd?
    beginning_of_month
  else
    (self - 1.month).beginning_of_month
  end
end
beginning_of_biweek() click to toggle source

Return the date that is the first day of the commercial biweek in which self falls. A biweek is a period of two commercial weeks starting with an odd-numbered week and with each week starting in Monday and ending on Sunday. @return [::Date]

# File lib/fat_core/date.rb, line 491
def beginning_of_biweek
  if cweek.odd?
    beginning_of_week(:monday)
  else
    (self - 1.week).beginning_of_week(:monday)
  end
end
beginning_of_semimonth() click to toggle source

The date that is the first day of the semimonth in which self falls. A semimonth is a calendar period beginning on the 1st or 16th of each month and ending on the 15th or last day of the month respectively. So each year has exactly 24 semimonths. @return [::Date]

# File lib/fat_core/date.rb, line 461
def beginning_of_semimonth
  if day >= 16
    ::Date.new(year, month, 16)
  else
    beginning_of_month
  end
end
end_of_bimonth() click to toggle source

The date that is the last day of the bimonth in which self falls. A 'bimonth' is a two-month calendar period beginning on the first day of the odd-numbered months. E.g., 2014-01-01 to 2014-02-28 is the first bimonth of 2014. @return [::Date]

# File lib/fat_core/date.rb, line 446
def end_of_bimonth
  if month.odd?
    (self + 1.month).end_of_month
  else
    end_of_month
  end
end
end_of_biweek() click to toggle source

Return the date that is the last day of the commercial biweek in which self falls. A biweek is a period of two commercial weeks starting with an odd-numbered week and with each week starting in Monday and ending on Sunday. So this will always return a Sunday in an even-numbered week. In the last week of the year (if it is not part of next year's first week) the end of the biweek will not extend beyond self's week, so that week 1 of the following year will start a new biweek. @return [::Date]

# File lib/fat_core/date.rb, line 508
def end_of_biweek
  if cweek >= 52 && end_of_week(:monday).year > year
    end_of_week(:monday)
  elsif cweek.odd?
    (self + 1.week).end_of_week(:monday)
  else
    end_of_week(:monday)
  end
end
end_of_half() click to toggle source

The date that is the last day of the half-year in which self falls. @return [::Date]

# File lib/fat_core/date.rb, line 414
def end_of_half
  if month < 4
    (end_of_quarter + 15).end_of_quarter
  elsif month < 7
    end_of_quarter
  else
    end_of_year
  end
end
end_of_semimonth() click to toggle source

The date that is the last day of the semimonth in which self falls. A semimonth is a calendar period beginning on the 1st or 16th of each month and ending on the 15th or last day of the month respectively. So each year has exactly 24 semimonths. @return [::Date]

# File lib/fat_core/date.rb, line 476
def end_of_semimonth
  if day <= 15
    ::Date.new(year, month, 15)
  else
    end_of_month
  end
end
pred() click to toggle source

Predecessor of self, opposite of `#succ`. @return [::Date]

# File lib/fat_core/date.rb, line 392
def pred
  self - 1.day
end