Module: FatCore::Date

Included in:
Date
Defined in:
lib/fat_core/date.rb

Defined Under Namespace

Modules: ClassMethods

Federal Holidays and Workdays collapse

FED_DECREED_HOLIDAYS =

Holidays decreed by Presidential proclamation

[
  # Obama decree extra day before Christmas See
  # http://www.whitehouse.gov/the-press-office/2012/12/21
  ::Date.parse('2012-12-24')
].freeze
PRESIDENTIAL_FUNERALS =

Presidential funeral since JFK

[
  # JKF Funeral
  ::Date.parse('1963-11-25'),
  # DWE Funeral
  ::Date.parse('1969-03-31'),
  # HST Funeral
  ::Date.parse('1972-12-28'),
  # LBJ Funeral
  ::Date.parse('1973-01-25'),
  # RMN Funeral
  ::Date.parse('1994-04-27'),
  # RWR Funeral
  ::Date.parse('2004-06-11'),
  # GTF Funeral
  ::Date.parse('2007-01-02')
]

Constant Summary collapse

BOT =

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

::Date.parse('1900-01-01')
EOT =

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

::Date.parse('3000-12-31')

Formatting collapse

Queries collapse

Relative ::Dates collapse

Federal Holidays and Workdays collapse

NYSE Holidays and Workdays collapse

Instance Method Details

#add_chunk(chunk, n = 1) ⇒ ::Date

Return the date that is n chunks later than self.

Parameters:

  • chunk (Symbol)

    one of +:year+, +:half+, +:quarter+, +:bimonth+, +:month+, +:semimonth+, +:biweek+, +:week+, or +:day+.

  • n (Integer) (defaults to: 1)

    the number of chunks to add, can be negative

Returns:

  • (::Date)

    the date n chunks from this date



676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
# File 'lib/fat_core/date.rb', line 676

def add_chunk(chunk, n = 1)
  case chunk
  when :year
    next_year(n)
  when :half
    next_month(6)
  when :quarter
    next_month(3)
  when :bimonth
    next_month(2)
  when :month
    next_month(n)
  when :semimonth
    next_semimonth(n)
  when :biweek
    next_biweek(n)
  when :week
    next_week(n)
  when :day
    next_day(n)
  else
    raise ArgumentError, "add_chunk unknown chunk: '#{chunk}'"
  end
end

#add_fed_workdays(n) ⇒ ::Date

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

Parameters:

  • n (Integer)

    number of federal workdays to add to this date

Returns:



864
865
866
867
868
869
870
871
872
873
874
# File 'lib/fat_core/date.rb', line 864

def add_fed_workdays(n)
  d = dup
  return d if n.zero?
  incr = n.negative? ? -1 : 1
  n = n.abs
  while n.positive?
    d += incr
    n -= 1 if d.fed_workday?
  end
  d
end

#add_nyse_workdays(n) ⇒ ::Date Also known as: add_trading_days

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

Parameters:

  • n (Integer)

    number of NYSE trading days to add to this date

Returns:



1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
# File 'lib/fat_core/date.rb', line 1041

def add_nyse_workdays(n)
  d = dup
  return d if n.zero?
  incr = n.negative? ? -1 : 1
  n = n.abs
  while n.positive?
    d += incr
    n -= 1 if d.nyse_workday?
  end
  d
end

#americanString

Format date in MM/DD/YYYY form, as typical for the short American form.

Returns:



102
103
104
# File 'lib/fat_core/date.rb', line 102

def american
  strftime '%-m/%-d/%Y'
end

#beginning_of_bimonth::Date

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.

Returns:



393
394
395
396
397
398
399
# File 'lib/fat_core/date.rb', line 393

def beginning_of_bimonth
  if month.odd?
    beginning_of_month
  else
    (self - 1.month).beginning_of_month
  end
end

#beginning_of_bimonth?Boolean

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

Returns:

  • (Boolean)


209
210
211
# File 'lib/fat_core/date.rb', line 209

def beginning_of_bimonth?
  month.odd? && beginning_of_month == self
end

#beginning_of_biweek::Date

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.

Returns:



453
454
455
456
457
458
459
# File 'lib/fat_core/date.rb', line 453

def beginning_of_biweek
  if cweek.odd?
    beginning_of_week(:monday)
  else
    (self - 1.week).beginning_of_week(:monday)
  end
end

#beginning_of_biweek?Boolean

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."

Returns:

  • (Boolean)


266
267
268
# File 'lib/fat_core/date.rb', line 266

def beginning_of_biweek?
  beginning_of_biweek == self
end

#beginning_of_chunk(chunk) ⇒ ::Date

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

Parameters:

  • chunk (Symbol)

    one of +:year+, +:half+, +:quarter+, +:bimonth+, +:month+, +:semimonth+, +:biweek+, +:week+, or +:day+.

Returns:

  • (::Date)

    the first date in the chunk-sized period in which this date falls



708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
# File 'lib/fat_core/date.rb', line 708

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_half::Date

The date that is the first day of the half-year in which self falls.

Returns:



362
363
364
365
366
367
368
369
370
# File 'lib/fat_core/date.rb', line 362

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

#beginning_of_half?Boolean

Return whether the date falls on the first day of a half-year.

Returns:

  • (Boolean)


176
177
178
# File 'lib/fat_core/date.rb', line 176

def beginning_of_half?
  beginning_of_half == self
end

#beginning_of_month?Boolean

Return whether the date falls on the first day of a calendar month.

Returns:

  • (Boolean)


226
227
228
# File 'lib/fat_core/date.rb', line 226

def beginning_of_month?
  beginning_of_month == self
end

#beginning_of_quarter?Boolean

Return whether the date falls on the first day of a calendar quarter.

Returns:

  • (Boolean)


192
193
194
# File 'lib/fat_core/date.rb', line 192

def beginning_of_quarter?
  beginning_of_quarter == self
end

#beginning_of_semimonth::Date

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.

Returns:



423
424
425
426
427
428
429
# File 'lib/fat_core/date.rb', line 423

def beginning_of_semimonth
  if day >= 16
    ::Date.new(year, month, 16)
  else
    beginning_of_month
  end
end

#beginning_of_semimonth?Boolean

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.

Returns:

  • (Boolean)


243
244
245
# File 'lib/fat_core/date.rb', line 243

def beginning_of_semimonth?
  beginning_of_semimonth == self
end

#beginning_of_week?Boolean

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."

Returns:

  • (Boolean)


293
294
295
# File 'lib/fat_core/date.rb', line 293

def beginning_of_week?
  beginning_of_week == self
end

#beginning_of_year?Boolean

Return whether the date falls on the first day of a year.

Returns:

  • (Boolean)


160
161
162
# File 'lib/fat_core/date.rb', line 160

def beginning_of_year?
  beginning_of_year == self
end

#easter?Boolean

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."

Returns:

  • (Boolean)


330
331
332
333
# File 'lib/fat_core/date.rb', line 330

def easter?
  # Am I Easter?
  self == easter_this_year
end

#easter_this_year::Date

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

Returns:



769
770
771
772
# File 'lib/fat_core/date.rb', line 769

def easter_this_year
  # Return the date of Easter in self's year
  ::Date.easter(year)
end

#end_of_bimonth::Date

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.

Returns:



408
409
410
411
412
413
414
# File 'lib/fat_core/date.rb', line 408

def end_of_bimonth
  if month.odd?
    (self + 1.month).end_of_month
  else
    end_of_month
  end
end

#end_of_bimonth?Boolean

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

Returns:

  • (Boolean)


218
219
220
# File 'lib/fat_core/date.rb', line 218

def end_of_bimonth?
  month.even? && end_of_month == self
end

#end_of_biweek::Date

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.

Returns:



468
469
470
471
472
473
474
# File 'lib/fat_core/date.rb', line 468

def end_of_biweek
  if cweek.odd?
    (self + 1.week).end_of_week(:monday)
  else
    end_of_week(:monday)
  end
end

#end_of_biweek?Boolean

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."

Returns:

  • (Boolean)


280
281
282
# File 'lib/fat_core/date.rb', line 280

def end_of_biweek?
  end_of_biweek == self
end

#end_of_chunk(chunk) ⇒ ::Date

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

Parameters:

  • chunk (Symbol)

    one of +:year+, +:half+, +:quarter+, +:bimonth+, +:month+, +:semimonth+, +:biweek+, +:week+, or +:day+.

Returns:

  • (::Date)

    the first date in the chunk-sized period in which this date falls



740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
# File 'lib/fat_core/date.rb', line 740

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_half::Date

The date that is the last day of the half-year in which self falls.

Returns:



376
377
378
379
380
381
382
383
384
# File 'lib/fat_core/date.rb', line 376

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_half?Boolean

Return whether the date falls on the last day of a half-year.

Returns:

  • (Boolean)


184
185
186
# File 'lib/fat_core/date.rb', line 184

def end_of_half?
  end_of_half == self
end

#end_of_month?Boolean

Return whether the date falls on the last day of a calendar month.

Returns:

  • (Boolean)


234
235
236
# File 'lib/fat_core/date.rb', line 234

def end_of_month?
  end_of_month == self
end

#end_of_quarter?Boolean

Return whether the date falls on the last day of a calendar quarter.

Returns:

  • (Boolean)


200
201
202
# File 'lib/fat_core/date.rb', line 200

def end_of_quarter?
  end_of_quarter == self
end

#end_of_semimonth::Date

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.

Returns:



438
439
440
441
442
443
444
# File 'lib/fat_core/date.rb', line 438

def end_of_semimonth
  if day <= 15
    ::Date.new(year, month, 15)
  else
    end_of_month
  end
end

#end_of_semimonth?Boolean

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.

Returns:

  • (Boolean)


252
253
254
# File 'lib/fat_core/date.rb', line 252

def end_of_semimonth?
  end_of_semimonth == self
end

#end_of_week?Boolean

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."

Returns:

  • (Boolean)


306
307
308
# File 'lib/fat_core/date.rb', line 306

def end_of_week?
  end_of_week == self
end

#end_of_year?Boolean

Return whether the date falls on the last day of a year.

Returns:

  • (Boolean)


168
169
170
# File 'lib/fat_core/date.rb', line 168

def end_of_year?
  end_of_year == self
end

#engString

Format as an English string, like 'January 12, 2016'

Returns:



93
94
95
# File 'lib/fat_core/date.rb', line 93

def eng
  strftime('%B %e, %Y')
end

#fed_holiday?Boolean

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.

Returns:

  • (Boolean)


808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
# File 'lib/fat_core/date.rb', line 808

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?Boolean

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

Returns:

  • (Boolean)


853
854
855
# File 'lib/fat_core/date.rb', line 853

def fed_workday?
  !fed_holiday?
end

#half1, 2

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.

Returns:

  • (1, 2)


129
130
131
132
133
134
135
136
# File 'lib/fat_core/date.rb', line 129

def half
  case month
  when (1..6)
    1
  when (7..12)
    2
  end
end

#isoString

Format as an ISO string of the form YYYY-MM-DD.

Returns:



60
61
62
# File 'lib/fat_core/date.rb', line 60

def iso
  strftime('%Y-%m-%d')
end

#next_bimonth(n = 1) ⇒ ::Date

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

Parameters:

  • n (Integer) (defaults to: 1)

    number of bimonths to advance, can be negative

Returns:

  • (::Date)

    new date n bimonths after this date



521
522
523
524
525
# File 'lib/fat_core/date.rb', line 521

def next_bimonth(n = 1)
  n = n.floor
  return self if n.zero?
  next_month(n * 2)
end

#next_biweek(n = 1) ⇒ ::Date

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

Parameters:

  • n (Integer) (defaults to: 1)

    number of biweeks to advance, can be negative

Returns:

  • (::Date)

    new date n biweeks after this date



620
621
622
623
624
# File 'lib/fat_core/date.rb', line 620

def next_biweek(n = 1)
  n = n.floor
  return self if n.zero?
  self + (14 * n)
end

#next_fed_workday::Date

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.

Returns:



880
881
882
# File 'lib/fat_core/date.rb', line 880

def next_fed_workday
  add_fed_workdays(1)
end

#next_half(n = 1) ⇒ ::Date

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

Parameters:

  • n (Integer) (defaults to: 1)

    number of halves to advance, can be negative

Returns:

  • (::Date)

    new date n halves after this date



481
482
483
484
485
# File 'lib/fat_core/date.rb', line 481

def next_half(n = 1)
  n = n.floor
  return self if n.zero?
  next_month(n * 6)
end

#next_nyse_workday::Date Also known as: next_trading_day

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.

Returns:



1058
1059
1060
# File 'lib/fat_core/date.rb', line 1058

def next_nyse_workday
  add_nyse_workdays(1)
end

#next_quarter(n = 1) ⇒ ::Date

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

Parameters:

  • n (Integer) (defaults to: 1)

    number of quarters to advance, can be negative

Returns:

  • (::Date)

    new date n quarters after this date



501
502
503
504
505
# File 'lib/fat_core/date.rb', line 501

def next_quarter(n = 1)
  n = n.floor
  return self if n.zero?
  next_month(n * 3)
end

#next_semimonth(n = 1) ⇒ ::Date

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.

Parameters:

  • n (Integer) (defaults to: 1)

    number of semimonths to advance, can be negative

Returns:

  • (::Date)

    new date n semimonths after this date



545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
# File 'lib/fat_core/date.rb', line 545

def next_semimonth(n = 1)
  n = n.floor
  return self if n.zero?
  factor = n.negative? ? -1 : 1
  n = n.abs
  if n.even?
    next_month(n / 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
      else
        # 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.
        if factor.positive?
          next_month.beginning_of_month + [(day - 16), 15].min
        else
          beginning_of_month + [(day - 16), 15].min
        end
      end
    n -= 1
    # Now that n is even, advance (or retreat) n / 2 months unless we're done.
    if n >= 2
      next_sm.next_month(factor * n / 2)
    else
      next_sm
    end
  end
end

#next_until_fed_workday::Date

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

Returns:



896
897
898
899
900
# File 'lib/fat_core/date.rb', line 896

def next_until_fed_workday
  date = dup
  date += 1 until date.fed_workday?
  date
end

#next_until_trading_day::Date

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

Returns:



1076
1077
1078
1079
1080
# File 'lib/fat_core/date.rb', line 1076

def next_until_trading_day
  date = dup
  date += 1 until date.trading_day?
  date
end

#next_week(n = 1) ⇒ ::Date

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.

Parameters:

  • n (Integer) (defaults to: 1)

    number of weeks to advance

Returns:

  • (::Date)

    new date n weeks after this date



642
643
644
645
646
# File 'lib/fat_core/date.rb', line 642

def next_week(n = 1)
  n = n.floor
  return self if n.zero?
  self + (7 * n)
end

#nth_wday_in_month?(n, wday, month) ⇒ Boolean

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

Parameters:

  • n (Integer)

    number of wday in month, if negative count from end of the month

  • wday (Integer)

    day of week, 0 is Sunday, 1 Monday, etc.

  • month (Integer)

    the month number, 1 is January, 2 is February, etc.

Returns:

  • (Boolean)


343
344
345
346
347
# File 'lib/fat_core/date.rb', line 343

def nth_wday_in_month?(n, wday, month)
  # Is self the nth weekday in the given month of its year?
  # If n is negative, count from last day of month
  self == ::Date.nth_wday_in_year_month(n, wday, year, month)
end

#numString

Format as an all-numeric string of the form YYYYMMDD

Returns:



76
77
78
# File 'lib/fat_core/date.rb', line 76

def num
  strftime('%Y%m%d')
end

#nyse_holiday?Boolean

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.

Returns:

  • (Boolean)


997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
# File 'lib/fat_core/date.rb', line 997

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_workday?Boolean Also known as: trading_day?

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

Returns:

  • (Boolean)


1031
1032
1033
# File 'lib/fat_core/date.rb', line 1031

def nyse_workday?
  !nyse_holiday?
end

#orgString

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

Returns:



85
86
87
# File 'lib/fat_core/date.rb', line 85

def org
  strftime('[%Y-%m-%d %a]')
end

#pred::Date

Predecessor of self, opposite of #succ.

Returns:



354
355
356
# File 'lib/fat_core/date.rb', line 354

def pred
  self - 1.day
end

#prior_bimonth(n = 1) ⇒ ::Date

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

Parameters:

  • n (Integer) (defaults to: 1)

    number of bimonths to retreat, can be negative

Returns:

  • (::Date)

    new date n bimonths before this date



532
533
534
# File 'lib/fat_core/date.rb', line 532

def prior_bimonth(n = 1)
  next_bimonth(-n)
end

#prior_biweek(n = 1) ⇒ ::Date

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

Parameters:

  • n (Integer) (defaults to: 1)

    number of biweeks to retreat, can be negative

Returns:

  • (::Date)

    new date n biweeks before this date



631
632
633
# File 'lib/fat_core/date.rb', line 631

def prior_biweek(n = 1)
  next_biweek(-n)
end

#prior_day(n) ⇒ ::Date

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

Parameters:

  • n (Integer)

    number of days to retreat

Returns:

  • (::Date)

    new date n days before this date



664
665
666
# File 'lib/fat_core/date.rb', line 664

def prior_day(n)
  next_day(-n)
end

#prior_fed_workday::Date

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.

Returns:



888
889
890
# File 'lib/fat_core/date.rb', line 888

def prior_fed_workday
  add_fed_workdays(-1)
end

#prior_half(n = 1) ⇒ ::Date

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

Parameters:

  • n (Integer) (defaults to: 1)

    number of halves to retreat, can be negative

Returns:

  • (::Date)

    new date n halves before this date



492
493
494
# File 'lib/fat_core/date.rb', line 492

def prior_half(n = 1)
  next_half(-n)
end

#prior_nyse_workday::Date Also known as: prior_trading_day

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.

Returns:



1067
1068
1069
# File 'lib/fat_core/date.rb', line 1067

def prior_nyse_workday
  add_nyse_workdays(-1)
end

#prior_quarter(n = 1) ⇒ ::Date

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

Parameters:

  • n (Integer) (defaults to: 1)

    number of quarters to retreat, can be negative

Returns:

  • (::Date)

    new date n quarters after this date



512
513
514
# File 'lib/fat_core/date.rb', line 512

def prior_quarter(n = 1)
  next_quarter(-n)
end

#prior_semimonth(n = 1) ⇒ ::Date

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.

Parameters:

  • n (Integer) (defaults to: 1)

    number of semimonths to retreat, can be negative

Returns:

  • (::Date)

    new date n semimonths before this date



611
612
613
# File 'lib/fat_core/date.rb', line 611

def prior_semimonth(n = 1)
  next_semimonth(-n)
end

#prior_until_fed_workdayObject

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



904
905
906
907
908
# File 'lib/fat_core/date.rb', line 904

def prior_until_fed_workday
  date = dup
  date -= 1 until date.fed_workday?
  date
end

#prior_until_trading_day::Date

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

Returns:



1086
1087
1088
1089
1090
# File 'lib/fat_core/date.rb', line 1086

def prior_until_trading_day
  date = dup
  date -= 1 until date.trading_day?
  date
end

#prior_week(n) ⇒ ::Date

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

Parameters:

  • n (Integer)

    number of weeks to retreat

Returns:

  • (::Date)

    new date n weeks from this date



653
654
655
# File 'lib/fat_core/date.rb', line 653

def prior_week(n)
  next_week(-n)
end

#quarter1, ...

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

Returns:

  • (1, 2, 3, 4)


143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/fat_core/date.rb', line 143

def quarter
  case month
  when (1..3)
    1
  when (4..6)
    2
  when (7..9)
    3
  when (10..12)
    4
  end
end

#tex_quoteString

Format date to TeX documents as ISO strings

Returns:



68
69
70
# File 'lib/fat_core/date.rb', line 68

def tex_quote
  iso
end

#weekday?Boolean

Does self fall on a weekday?

Returns:

  • (Boolean)


119
120
121
# File 'lib/fat_core/date.rb', line 119

def weekday?
  !weekend?
end

#weekend?Boolean

Does self fall on a weekend?

Returns:

  • (Boolean)


111
112
113
# File 'lib/fat_core/date.rb', line 111

def weekend?
  saturday? || sunday?
end

#within_6mos_of?(d) ⇒ Boolean

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.

Parameters:

  • d (::Date)

    the middle of the six-month range

Returns:

  • (Boolean)


318
319
320
321
322
323
# File 'lib/fat_core/date.rb', line 318

def within_6mos_of?(d)
  # ::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?(d)
end