fat_date 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.rspec +3 -0
 - data/.rubocop.yml +9 -0
 - data/.ruby-version +1 -0
 - data/CHANGELOG.org +5 -0
 - data/LICENSE.txt +21 -0
 - data/README.org +720 -0
 - data/Rakefile +12 -0
 - data/lib/fat_date/date.rb +2051 -0
 - data/lib/fat_date/patches.rb +20 -0
 - data/lib/fat_date/version.rb +5 -0
 - data/lib/fat_date.rb +18 -0
 - data/sig/fat_date.rbs +4 -0
 - metadata +73 -0
 
    
        data/README.org
    ADDED
    
    | 
         @@ -0,0 +1,720 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #+TITLE: FatDate Guide
         
     | 
| 
      
 2 
     | 
    
         
            +
            #+OPTIONS: toc:5
         
     | 
| 
      
 3 
     | 
    
         
            +
            #+PROPERTY: header-args:ruby :colnames no :hlines yes :exports both :wrap example :ruby ruby
         
     | 
| 
      
 4 
     | 
    
         
            +
            #+PROPERTY: header-args:sh :exports code
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            [[https://travis-ci.org/ddoherty03/fat_core.svg?branch=master]]
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            * README Setup Do First for Code Blocks                            :noexport:
         
     | 
| 
      
 9 
     | 
    
         
            +
            Run this block before all others to ensure that we are reading the libraries
         
     | 
| 
      
 10 
     | 
    
         
            +
            from the source directory.
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            #+begin_src ruby :results output :export no
         
     | 
| 
      
 13 
     | 
    
         
            +
              puts "Current directory: #{Dir.pwd}"
         
     | 
| 
      
 14 
     | 
    
         
            +
              puts "Ruby LOADPATH:"
         
     | 
| 
      
 15 
     | 
    
         
            +
              $:.unshift("./lib") unless $:[0] == './lib'
         
     | 
| 
      
 16 
     | 
    
         
            +
              $:[0..10].each { |d| puts d }
         
     | 
| 
      
 17 
     | 
    
         
            +
              puts "..."
         
     | 
| 
      
 18 
     | 
    
         
            +
              require 'fat_date'  # => true
         
     | 
| 
      
 19 
     | 
    
         
            +
            #+end_src
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            #+RESULTS:
         
     | 
| 
      
 22 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 23 
     | 
    
         
            +
            Current directory: /home/ded/src/fat_date
         
     | 
| 
      
 24 
     | 
    
         
            +
            Ruby LOADPATH:
         
     | 
| 
      
 25 
     | 
    
         
            +
            ./lib
         
     | 
| 
      
 26 
     | 
    
         
            +
            /home/ded/.rbenv/rbenv.d/exec/gem-rehash
         
     | 
| 
      
 27 
     | 
    
         
            +
            /home/ded/.rbenv/versions/3.4.1/lib/ruby/site_ruby/3.4.0
         
     | 
| 
      
 28 
     | 
    
         
            +
            /home/ded/.rbenv/versions/3.4.1/lib/ruby/site_ruby/3.4.0/x86_64-linux
         
     | 
| 
      
 29 
     | 
    
         
            +
            /home/ded/.rbenv/versions/3.4.1/lib/ruby/site_ruby
         
     | 
| 
      
 30 
     | 
    
         
            +
            /home/ded/.rbenv/versions/3.4.1/lib/ruby/vendor_ruby/3.4.0
         
     | 
| 
      
 31 
     | 
    
         
            +
            /home/ded/.rbenv/versions/3.4.1/lib/ruby/vendor_ruby/3.4.0/x86_64-linux
         
     | 
| 
      
 32 
     | 
    
         
            +
            /home/ded/.rbenv/versions/3.4.1/lib/ruby/vendor_ruby
         
     | 
| 
      
 33 
     | 
    
         
            +
            /home/ded/.rbenv/versions/3.4.1/lib/ruby/3.4.0
         
     | 
| 
      
 34 
     | 
    
         
            +
            /home/ded/.rbenv/versions/3.4.1/lib/ruby/3.4.0/x86_64-linux
         
     | 
| 
      
 35 
     | 
    
         
            +
            ...
         
     | 
| 
      
 36 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            * FatDate
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            ~fat_date~ is a simple gem to collect core extensions for the Date class to
         
     | 
| 
      
 42 
     | 
    
         
            +
            make it more useful in financial applications.
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            * Installation
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            Add this line to your application's Gemfile:
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            #+begin_SRC ruby
         
     | 
| 
      
 49 
     | 
    
         
            +
              gem 'fat_date', :git => 'https://github.com/ddoherty03/fat_date.git'
         
     | 
| 
      
 50 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
            And then execute:
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            #+begin_src shell
         
     | 
| 
      
 55 
     | 
    
         
            +
              $ bundle
         
     | 
| 
      
 56 
     | 
    
         
            +
            #+end_src
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            Or install it yourself as:
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
            #+begin_src shell
         
     | 
| 
      
 61 
     | 
    
         
            +
              $ gem install fat_core
         
     | 
| 
      
 62 
     | 
    
         
            +
            #+end_src
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            * Usage
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            Many of these have little that is of general interest, but there are a few
         
     | 
| 
      
 67 
     | 
    
         
            +
            goodies.
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            *** Constants
         
     | 
| 
      
 70 
     | 
    
         
            +
            ~FatDate~ adds two date constants to the ~Date~ class, Date::BOT and
         
     | 
| 
      
 71 
     | 
    
         
            +
            Date::EOT.  These represent the earliest and latest dates of practical
         
     | 
| 
      
 72 
     | 
    
         
            +
            commercial interest.  The exact values are rather arbitrary, but they prove
         
     | 
| 
      
 73 
     | 
    
         
            +
            useful in date ranges, for example.  They are defined as:
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
            - ~Date::BOT~ :: January 1, 1900
         
     | 
| 
      
 76 
     | 
    
         
            +
            - ~Date::EOT~ :: December 31, 3000
         
     | 
| 
      
 77 
     | 
    
         
            +
            - ~Date::FEDERAL_DECREED_HOLIDAYS~ :: an Array of dates declared as non-work
         
     | 
| 
      
 78 
     | 
    
         
            +
              days for federal employees by presidential proclamation
         
     | 
| 
      
 79 
     | 
    
         
            +
            - ~Date::PRESIDENTIAL_FUNERALS~ :: an Array of dates of presidential funerals,
         
     | 
| 
      
 80 
     | 
    
         
            +
              which are observed with a closing of most federal agencies
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            *** Ensure
         
     | 
| 
      
 83 
     | 
    
         
            +
            The ~Date.ensure~ class method tries to convert its argument to a ~Date~
         
     | 
| 
      
 84 
     | 
    
         
            +
            object by (1) applying the ~#to_date~ method or (2) applying the ~Date.parse~
         
     | 
| 
      
 85 
     | 
    
         
            +
            method to a String.  This is handy when you want to define a method that takes
         
     | 
| 
      
 86 
     | 
    
         
            +
            a date argument but want the caller to be able to supply anything that can
         
     | 
| 
      
 87 
     | 
    
         
            +
            reasonably be converted to a ~Date~:
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
            #+begin_src ruby :results output
         
     | 
| 
      
 90 
     | 
    
         
            +
              $:.unshift("~/src/fat_core/lib")
         
     | 
| 
      
 91 
     | 
    
         
            +
              require 'fat_core/date'  # => true
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
              def tomorow_tomorrow(arg)
         
     | 
| 
      
 94 
     | 
    
         
            +
                from = Date.ensure(arg)  # => ArgumentError: cannot convert class 'Array' to a Date or DateTime
         
     | 
| 
      
 95 
     | 
    
         
            +
                from + 2.days            # => Mon, 03 Jun 2024, Wed, 16 Oct 2024 05:47:30 -0500, Sun, 03 Mar 2024
         
     | 
| 
      
 96 
     | 
    
         
            +
              end                        # => :tomorow_tomorrow
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
              puts tomorow_tomorrow('June 1').to_s
         
     | 
| 
      
 99 
     | 
    
         
            +
              puts tomorow_tomorrow(Time.now).to_s
         
     | 
| 
      
 100 
     | 
    
         
            +
              # But it's only as good as Date.parse!  If all it sees is 'March', it returns
         
     | 
| 
      
 101 
     | 
    
         
            +
              # March 1 of the current year.
         
     | 
| 
      
 102 
     | 
    
         
            +
              puts tomorow_tomorrow('Ides of March').to_s
         
     | 
| 
      
 103 
     | 
    
         
            +
            #+end_src
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 106 
     | 
    
         
            +
            2025-06-03
         
     | 
| 
      
 107 
     | 
    
         
            +
            2025-10-18T04:54:44-05:00
         
     | 
| 
      
 108 
     | 
    
         
            +
            2025-03-03
         
     | 
| 
      
 109 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
            *** Formatting
         
     | 
| 
      
 112 
     | 
    
         
            +
            ~FatDate~ provides some concise methods for printing string versions of dates
         
     | 
| 
      
 113 
     | 
    
         
            +
            that are often useful:
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
            #+begin_SRC ruby :results output
         
     | 
| 
      
 116 
     | 
    
         
            +
              require_relative './lib/fat_date'
         
     | 
| 
      
 117 
     | 
    
         
            +
              d = Date.parse('1957-09-22')
         
     | 
| 
      
 118 
     | 
    
         
            +
              puts "ISO: #{d.iso}"
         
     | 
| 
      
 119 
     | 
    
         
            +
              puts "All Numbers: #{d.num}"
         
     | 
| 
      
 120 
     | 
    
         
            +
              puts "Emacs Org Mode Inactive: #{d.org}"
         
     | 
| 
      
 121 
     | 
    
         
            +
              puts "Emacs Org Mode Active: #{d.org(active: true)}"
         
     | 
| 
      
 122 
     | 
    
         
            +
              puts "LaTeX: #{d.tex_quote}"
         
     | 
| 
      
 123 
     | 
    
         
            +
              puts "English: #{d.eng}"
         
     | 
| 
      
 124 
     | 
    
         
            +
              puts "American: #{d.american}"
         
     | 
| 
      
 125 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 128 
     | 
    
         
            +
            ISO: 1957-09-22
         
     | 
| 
      
 129 
     | 
    
         
            +
            All Numbers: 19570922
         
     | 
| 
      
 130 
     | 
    
         
            +
            Emacs Org Mode Inactive: [1957-09-22 Sun]
         
     | 
| 
      
 131 
     | 
    
         
            +
            Emacs Org Mode Active: <1957-09-22 Sun>
         
     | 
| 
      
 132 
     | 
    
         
            +
            LaTeX: 1957--09--22
         
     | 
| 
      
 133 
     | 
    
         
            +
            English: September 22, 1957
         
     | 
| 
      
 134 
     | 
    
         
            +
            American: 9/22/1957
         
     | 
| 
      
 135 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            Most of these are self-explanatory, but a couple are not.  The
         
     | 
| 
      
 138 
     | 
    
         
            +
            ~Date.org(active: false)~ method formats a date as an Emacs org-mode
         
     | 
| 
      
 139 
     | 
    
         
            +
            timestamp, by default an inactive timestamp that does not show up in the org
         
     | 
| 
      
 140 
     | 
    
         
            +
            agenda, but can be made active with the optional parameter ~active:~ set to a
         
     | 
| 
      
 141 
     | 
    
         
            +
            truthy value.  See [[https://orgmode.org/manual/Timestamps.html#Timestamps]].
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
            The ~#tex_quote~ method formats the date in iso form but using TeX's
         
     | 
| 
      
 144 
     | 
    
         
            +
            convention of using en-dashes to separate the components.
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
            *** Chunks
         
     | 
| 
      
 147 
     | 
    
         
            +
            Many of the methods provided by ~FatDate~ deal with various calendar periods
         
     | 
| 
      
 148 
     | 
    
         
            +
            that are less common than those provided by the Ruby Standard Library or gems
         
     | 
| 
      
 149 
     | 
    
         
            +
            such as ~active_support~.  This documentation refers to these calendar periods
         
     | 
| 
      
 150 
     | 
    
         
            +
            as "chunks", and they are the following:
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
            - year,
         
     | 
| 
      
 153 
     | 
    
         
            +
            - half,
         
     | 
| 
      
 154 
     | 
    
         
            +
            - quarter,
         
     | 
| 
      
 155 
     | 
    
         
            +
            - bimonth,
         
     | 
| 
      
 156 
     | 
    
         
            +
            - month,
         
     | 
| 
      
 157 
     | 
    
         
            +
            - semimonth,
         
     | 
| 
      
 158 
     | 
    
         
            +
            - biweek,
         
     | 
| 
      
 159 
     | 
    
         
            +
            - week, and
         
     | 
| 
      
 160 
     | 
    
         
            +
            - day
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
            ~FatDate~ provides methods that query whether the date falls on the beginning
         
     | 
| 
      
 163 
     | 
    
         
            +
            or end of each of these chunks:
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
            #+begin_SRC ruby :results value
         
     | 
| 
      
 166 
     | 
    
         
            +
              require_relative './lib/fat_date'
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
              tab = []
         
     | 
| 
      
 169 
     | 
    
         
            +
              tab << ['Subject Date', 'Method', 'Result']
         
     | 
| 
      
 170 
     | 
    
         
            +
              tab << nil
         
     | 
| 
      
 171 
     | 
    
         
            +
              d = Date.parse('2017-06-30')
         
     | 
| 
      
 172 
     | 
    
         
            +
              %i[beginning end].each do |side|
         
     | 
| 
      
 173 
     | 
    
         
            +
                %i(year half quarter bimonth month semimonth biweek week).each do |chunk|
         
     | 
| 
      
 174 
     | 
    
         
            +
                  meth = "#{side}_of_#{chunk}?".to_sym
         
     | 
| 
      
 175 
     | 
    
         
            +
                  tab << [d.iso, meth.to_s, "#{d.send(meth)}"]
         
     | 
| 
      
 176 
     | 
    
         
            +
                end
         
     | 
| 
      
 177 
     | 
    
         
            +
              end
         
     | 
| 
      
 178 
     | 
    
         
            +
              tab
         
     | 
| 
      
 179 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 182 
     | 
    
         
            +
            | Subject Date | Method                  | Result |
         
     | 
| 
      
 183 
     | 
    
         
            +
            |--------------+-------------------------+--------|
         
     | 
| 
      
 184 
     | 
    
         
            +
            | 2017-06-30   | beginning_of_year?      | false  |
         
     | 
| 
      
 185 
     | 
    
         
            +
            | 2017-06-30   | beginning_of_half?      | false  |
         
     | 
| 
      
 186 
     | 
    
         
            +
            | 2017-06-30   | beginning_of_quarter?   | false  |
         
     | 
| 
      
 187 
     | 
    
         
            +
            | 2017-06-30   | beginning_of_bimonth?   | false  |
         
     | 
| 
      
 188 
     | 
    
         
            +
            | 2017-06-30   | beginning_of_month?     | false  |
         
     | 
| 
      
 189 
     | 
    
         
            +
            | 2017-06-30   | beginning_of_semimonth? | false  |
         
     | 
| 
      
 190 
     | 
    
         
            +
            | 2017-06-30   | beginning_of_biweek?    | false  |
         
     | 
| 
      
 191 
     | 
    
         
            +
            | 2017-06-30   | beginning_of_week?      | false  |
         
     | 
| 
      
 192 
     | 
    
         
            +
            | 2017-06-30   | end_of_year?            | false  |
         
     | 
| 
      
 193 
     | 
    
         
            +
            | 2017-06-30   | end_of_half?            | true   |
         
     | 
| 
      
 194 
     | 
    
         
            +
            | 2017-06-30   | end_of_quarter?         | true   |
         
     | 
| 
      
 195 
     | 
    
         
            +
            | 2017-06-30   | end_of_bimonth?         | true   |
         
     | 
| 
      
 196 
     | 
    
         
            +
            | 2017-06-30   | end_of_month?           | true   |
         
     | 
| 
      
 197 
     | 
    
         
            +
            | 2017-06-30   | end_of_semimonth?       | true   |
         
     | 
| 
      
 198 
     | 
    
         
            +
            | 2017-06-30   | end_of_biweek?          | false  |
         
     | 
| 
      
 199 
     | 
    
         
            +
            | 2017-06-30   | end_of_week?            | false  |
         
     | 
| 
      
 200 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
            It also provides corresponding methods that return the date at the beginning
         
     | 
| 
      
 203 
     | 
    
         
            +
            or end of the calendar chunk, starting at the given date:
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
            #+begin_SRC ruby
         
     | 
| 
      
 206 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
              tab = []
         
     | 
| 
      
 209 
     | 
    
         
            +
              tab << ['Subject Date', 'Method', 'Result']
         
     | 
| 
      
 210 
     | 
    
         
            +
              tab << nil
         
     | 
| 
      
 211 
     | 
    
         
            +
              d = Date.parse('2017-04-21')
         
     | 
| 
      
 212 
     | 
    
         
            +
              %i[beginning end].each do |side|
         
     | 
| 
      
 213 
     | 
    
         
            +
                %i(year half quarter bimonth month semimonth biweek week ).each do |chunk|
         
     | 
| 
      
 214 
     | 
    
         
            +
                  meth = "#{side}_of_#{chunk}".to_sym
         
     | 
| 
      
 215 
     | 
    
         
            +
                  tab << [d.iso, "d.#{meth}", "#{d.send(meth)}"]
         
     | 
| 
      
 216 
     | 
    
         
            +
                end
         
     | 
| 
      
 217 
     | 
    
         
            +
              end
         
     | 
| 
      
 218 
     | 
    
         
            +
              tab
         
     | 
| 
      
 219 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 222 
     | 
    
         
            +
            | Subject Date | Method                   | Result     |
         
     | 
| 
      
 223 
     | 
    
         
            +
            |--------------+--------------------------+------------|
         
     | 
| 
      
 224 
     | 
    
         
            +
            | 2017-04-21   | d.beginning_of_year      | 2017-01-01 |
         
     | 
| 
      
 225 
     | 
    
         
            +
            | 2017-04-21   | d.beginning_of_half      | 2017-01-01 |
         
     | 
| 
      
 226 
     | 
    
         
            +
            | 2017-04-21   | d.beginning_of_quarter   | 2017-04-01 |
         
     | 
| 
      
 227 
     | 
    
         
            +
            | 2017-04-21   | d.beginning_of_bimonth   | 2017-03-01 |
         
     | 
| 
      
 228 
     | 
    
         
            +
            | 2017-04-21   | d.beginning_of_month     | 2017-04-01 |
         
     | 
| 
      
 229 
     | 
    
         
            +
            | 2017-04-21   | d.beginning_of_semimonth | 2017-04-16 |
         
     | 
| 
      
 230 
     | 
    
         
            +
            | 2017-04-21   | d.beginning_of_biweek    | 2017-04-10 |
         
     | 
| 
      
 231 
     | 
    
         
            +
            | 2017-04-21   | d.beginning_of_week      | 2017-04-17 |
         
     | 
| 
      
 232 
     | 
    
         
            +
            | 2017-04-21   | d.end_of_year            | 2017-12-31 |
         
     | 
| 
      
 233 
     | 
    
         
            +
            | 2017-04-21   | d.end_of_half            | 2017-06-30 |
         
     | 
| 
      
 234 
     | 
    
         
            +
            | 2017-04-21   | d.end_of_quarter         | 2017-06-30 |
         
     | 
| 
      
 235 
     | 
    
         
            +
            | 2017-04-21   | d.end_of_bimonth         | 2017-04-30 |
         
     | 
| 
      
 236 
     | 
    
         
            +
            | 2017-04-21   | d.end_of_month           | 2017-04-30 |
         
     | 
| 
      
 237 
     | 
    
         
            +
            | 2017-04-21   | d.end_of_semimonth       | 2017-04-30 |
         
     | 
| 
      
 238 
     | 
    
         
            +
            | 2017-04-21   | d.end_of_biweek          | 2017-04-23 |
         
     | 
| 
      
 239 
     | 
    
         
            +
            | 2017-04-21   | d.end_of_week            | 2017-04-23 |
         
     | 
| 
      
 240 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
            You can query which numerical half, quarter, etc. that a given date falls in:
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
      
 244 
     | 
    
         
            +
            #+begin_SRC ruby
         
     | 
| 
      
 245 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
              tab = []
         
     | 
| 
      
 248 
     | 
    
         
            +
              tab << ['Subject Date', 'Method', 'Result']
         
     | 
| 
      
 249 
     | 
    
         
            +
              tab << nil
         
     | 
| 
      
 250 
     | 
    
         
            +
              %i(year half quarter bimonth month semimonth biweek week ).each do |chunk|
         
     | 
| 
      
 251 
     | 
    
         
            +
                d = Date.parse('2017-04-21') + rand(100)
         
     | 
| 
      
 252 
     | 
    
         
            +
                meth = "#{chunk}".to_sym
         
     | 
| 
      
 253 
     | 
    
         
            +
                tab << [d.iso, "d.#{meth}", "in #{chunk} number #{d.send(meth)}"]
         
     | 
| 
      
 254 
     | 
    
         
            +
              end
         
     | 
| 
      
 255 
     | 
    
         
            +
              tab
         
     | 
| 
      
 256 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 259 
     | 
    
         
            +
            | Subject Date | Method      | Result                 |
         
     | 
| 
      
 260 
     | 
    
         
            +
            |--------------+-------------+------------------------|
         
     | 
| 
      
 261 
     | 
    
         
            +
            | 2017-07-26   | d.year      | in year number 2017    |
         
     | 
| 
      
 262 
     | 
    
         
            +
            | 2017-06-01   | d.half      | in half number 1       |
         
     | 
| 
      
 263 
     | 
    
         
            +
            | 2017-07-08   | d.quarter   | in quarter number 3    |
         
     | 
| 
      
 264 
     | 
    
         
            +
            | 2017-04-30   | d.bimonth   | in bimonth number 2    |
         
     | 
| 
      
 265 
     | 
    
         
            +
            | 2017-05-01   | d.month     | in month number 5      |
         
     | 
| 
      
 266 
     | 
    
         
            +
            | 2017-05-18   | d.semimonth | in semimonth number 10 |
         
     | 
| 
      
 267 
     | 
    
         
            +
            | 2017-05-21   | d.biweek    | in biweek number 10    |
         
     | 
| 
      
 268 
     | 
    
         
            +
            | 2017-07-01   | d.week      | in week number 26      |
         
     | 
| 
      
 269 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 270 
     | 
    
         
            +
             
     | 
| 
      
 271 
     | 
    
         
            +
            *** Parsing American Dates
         
     | 
| 
      
 272 
     | 
    
         
            +
            Americans often write dates in the form M/d/Y, and the normal parse method
         
     | 
| 
      
 273 
     | 
    
         
            +
            will parse such a string as d/M/Y, often resulting in invalid date errors.
         
     | 
| 
      
 274 
     | 
    
         
            +
            ~FatDate~ adds the specialty parsing method, ~Date.parse_american~ to handle
         
     | 
| 
      
 275 
     | 
    
         
            +
            such strings.
         
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
            #+begin_SRC ruby :results output
         
     | 
| 
      
 278 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 279 
     | 
    
         
            +
             
     | 
| 
      
 280 
     | 
    
         
            +
              begin
         
     | 
| 
      
 281 
     | 
    
         
            +
                ss = '9/22/1957'
         
     | 
| 
      
 282 
     | 
    
         
            +
                Date.parse(ss)
         
     | 
| 
      
 283 
     | 
    
         
            +
              rescue Date::Error => ex
         
     | 
| 
      
 284 
     | 
    
         
            +
                puts "Date.parse('#{ss}') raises #{ex.class} (#{ex}), but"
         
     | 
| 
      
 285 
     | 
    
         
            +
                puts "Date.parse_american('#{ss}') => #{Date.parse_american(ss)}"
         
     | 
| 
      
 286 
     | 
    
         
            +
              end
         
     | 
| 
      
 287 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 290 
     | 
    
         
            +
            Date.parse('9/22/1957') raises Date::Error (invalid date), but
         
     | 
| 
      
 291 
     | 
    
         
            +
            Date.parse_american('9/22/1957') => 1957-09-22
         
     | 
| 
      
 292 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 293 
     | 
    
         
            +
             
     | 
| 
      
 294 
     | 
    
         
            +
            *** Holidays and Workdays
         
     | 
| 
      
 295 
     | 
    
         
            +
            **** Federal
         
     | 
| 
      
 296 
     | 
    
         
            +
            One of the original motivations for this library was to provide an easy way to
         
     | 
| 
      
 297 
     | 
    
         
            +
            determine whether a given date is a federal holiday in the United States or,
         
     | 
| 
      
 298 
     | 
    
         
            +
            nearly but not quite the same, a non-trading day on the New York Stock
         
     | 
| 
      
 299 
     | 
    
         
            +
            Exchange.  To that end, ~FatDate~ provides the following methods:
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
            - Date#weekend? -- is this date on a weekend?
         
     | 
| 
      
 302 
     | 
    
         
            +
            - Date#weekday? -- is this date on a week day?
         
     | 
| 
      
 303 
     | 
    
         
            +
            - Date#easter_this_year -- the date of Easter in the Date's year
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
            Methods concerning Federal holidays:
         
     | 
| 
      
 306 
     | 
    
         
            +
             
     | 
| 
      
 307 
     | 
    
         
            +
            - Date#fed_holiday? -- is this date a Federal holiday?  It knows about
         
     | 
| 
      
 308 
     | 
    
         
            +
              obscurities such as holidays decreed by past Presidents, dates of
         
     | 
| 
      
 309 
     | 
    
         
            +
              Presidential funerals, and the Federal rule for when holidays fall on a
         
     | 
| 
      
 310 
     | 
    
         
            +
              weekend, whether it is moved to the prior Friday or the following Monday.
         
     | 
| 
      
 311 
     | 
    
         
            +
            - Date#fed_workday? -- is it a date when Federal government offices are open?,
         
     | 
| 
      
 312 
     | 
    
         
            +
              inverse of Date#fed_holiday?
         
     | 
| 
      
 313 
     | 
    
         
            +
            - Date#add_fed_workdays(n) -- n Federal workdays following (or preceding if n
         
     | 
| 
      
 314 
     | 
    
         
            +
              negative) this date,
         
     | 
| 
      
 315 
     | 
    
         
            +
            - Date#next_fed_workday -- the next Federal workday following this date,
         
     | 
| 
      
 316 
     | 
    
         
            +
            - Date#prior_fed_workday -- the previous Federal workday before this date,
         
     | 
| 
      
 317 
     | 
    
         
            +
            - Date#next_until_fed_workday -- starting with this date, move forward until
         
     | 
| 
      
 318 
     | 
    
         
            +
              we hit a Federal workday
         
     | 
| 
      
 319 
     | 
    
         
            +
            - Date#prior_until_fed_workday -- starting with this date, move back until
         
     | 
| 
      
 320 
     | 
    
         
            +
              we hit a Federal workday
         
     | 
| 
      
 321 
     | 
    
         
            +
             
     | 
| 
      
 322 
     | 
    
         
            +
            #+begin_SRC ruby
         
     | 
| 
      
 323 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 324 
     | 
    
         
            +
             
     | 
| 
      
 325 
     | 
    
         
            +
             
     | 
| 
      
 326 
     | 
    
         
            +
              result = []
         
     | 
| 
      
 327 
     | 
    
         
            +
              result << ['Date', 'Federal Holiday?', 'Comment']
         
     | 
| 
      
 328 
     | 
    
         
            +
              result << nil
         
     | 
| 
      
 329 
     | 
    
         
            +
              result << ['2014-05-18', Date.parse('2014-05-18').fed_holiday?, 'A weekend']
         
     | 
| 
      
 330 
     | 
    
         
            +
              result << ['2014-01-01', Date.parse('2014-05-18').fed_holiday?, 'New Year']
         
     | 
| 
      
 331 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 332 
     | 
    
         
            +
             
     | 
| 
      
 333 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 334 
     | 
    
         
            +
            | Date       | Federal Holiday? | Comment   |
         
     | 
| 
      
 335 
     | 
    
         
            +
            |------------+------------------+-----------|
         
     | 
| 
      
 336 
     | 
    
         
            +
            | 2014-05-18 | true             | A weekend |
         
     | 
| 
      
 337 
     | 
    
         
            +
            | 2014-01-01 | true             | New Year  |
         
     | 
| 
      
 338 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
      
 340 
     | 
    
         
            +
            **** NYSE
         
     | 
| 
      
 341 
     | 
    
         
            +
            And we have similar methods for "holidays" or non-trading days on the NYSE:
         
     | 
| 
      
 342 
     | 
    
         
            +
             
     | 
| 
      
 343 
     | 
    
         
            +
            - Date#nyse_holiday? -- is this date a NYSE holiday?
         
     | 
| 
      
 344 
     | 
    
         
            +
            - Date#nyse_workday? -- is it a date when the NYSE is open for trading?,
         
     | 
| 
      
 345 
     | 
    
         
            +
              inverse of Date#nyse_holiday?
         
     | 
| 
      
 346 
     | 
    
         
            +
            - Date#add_nyse_workdays(n) -- n NYSE workdays following (or preceding if n
         
     | 
| 
      
 347 
     | 
    
         
            +
              negative) this date,
         
     | 
| 
      
 348 
     | 
    
         
            +
            - Date#next_nyse_workday -- the next NYSE workday following this date,
         
     | 
| 
      
 349 
     | 
    
         
            +
            - Date#prior_nyse_workday -- the previous NYSE workday before this date,
         
     | 
| 
      
 350 
     | 
    
         
            +
            - Date#next_until_nyse_~~workday -- starting with this date, move forward until
         
     | 
| 
      
 351 
     | 
    
         
            +
              we hit a NYSE workday
         
     | 
| 
      
 352 
     | 
    
         
            +
            - Date#prior_until_nyse_workday -- starting with this date, move back until
         
     | 
| 
      
 353 
     | 
    
         
            +
              we hit a Federal workday
         
     | 
| 
      
 354 
     | 
    
         
            +
             
     | 
| 
      
 355 
     | 
    
         
            +
             
     | 
| 
      
 356 
     | 
    
         
            +
            Likewise, days on which the NYSE is closed can be gotten with:
         
     | 
| 
      
 357 
     | 
    
         
            +
             
     | 
| 
      
 358 
     | 
    
         
            +
            #+begin_SRC ruby :results output
         
     | 
| 
      
 359 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 360 
     | 
    
         
            +
             
     | 
| 
      
 361 
     | 
    
         
            +
              puts Date.parse('2014-04-18').nyse_holiday?
         
     | 
| 
      
 362 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 363 
     | 
    
         
            +
             
     | 
| 
      
 364 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 365 
     | 
    
         
            +
            true
         
     | 
| 
      
 366 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 367 
     | 
    
         
            +
             
     | 
| 
      
 368 
     | 
    
         
            +
            #+begin_SRC ruby :results value
         
     | 
| 
      
 369 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 370 
     | 
    
         
            +
             
     | 
| 
      
 371 
     | 
    
         
            +
              date_comments = [
         
     | 
| 
      
 372 
     | 
    
         
            +
                ['2014-04-18', 'Good Friday'],
         
     | 
| 
      
 373 
     | 
    
         
            +
                ['2014-05-18', 'Weekend'],
         
     | 
| 
      
 374 
     | 
    
         
            +
                ['2014-05-21', 'Any old day'],
         
     | 
| 
      
 375 
     | 
    
         
            +
                ['2014-01-01', 'New Year']
         
     | 
| 
      
 376 
     | 
    
         
            +
              ]
         
     | 
| 
      
 377 
     | 
    
         
            +
              result = []
         
     | 
| 
      
 378 
     | 
    
         
            +
              result << ['Date', 'Federal Holiday?', 'NYSE Holiday?', 'Comment']
         
     | 
| 
      
 379 
     | 
    
         
            +
              result << nil
         
     | 
| 
      
 380 
     | 
    
         
            +
              date_comments.each do |str, comment|
         
     | 
| 
      
 381 
     | 
    
         
            +
                d = Date.parse(str)
         
     | 
| 
      
 382 
     | 
    
         
            +
                result << [d.org, d.fed_holiday?, d.nyse_holiday?, comment]
         
     | 
| 
      
 383 
     | 
    
         
            +
              end
         
     | 
| 
      
 384 
     | 
    
         
            +
              result
         
     | 
| 
      
 385 
     | 
    
         
            +
            #+end_SRC
         
     | 
| 
      
 386 
     | 
    
         
            +
             
     | 
| 
      
 387 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 388 
     | 
    
         
            +
            | Date             | Federal Holiday? | NYSE Holiday? | Comment     |
         
     | 
| 
      
 389 
     | 
    
         
            +
            |------------------+------------------+---------------+-------------|
         
     | 
| 
      
 390 
     | 
    
         
            +
            | [2014-04-18 Fri] | false            | true          | Good Friday |
         
     | 
| 
      
 391 
     | 
    
         
            +
            | [2014-05-18 Sun] | true             | true          | Weekend     |
         
     | 
| 
      
 392 
     | 
    
         
            +
            | [2014-05-21 Wed] | false            | false         | Any old day |
         
     | 
| 
      
 393 
     | 
    
         
            +
            | [2014-01-01 Wed] | true             | true          | New Year    |
         
     | 
| 
      
 394 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 395 
     | 
    
         
            +
             
     | 
| 
      
 396 
     | 
    
         
            +
            *** Ordinal Weekdays in Month
         
     | 
| 
      
 397 
     | 
    
         
            +
            It is often useful to find the 1st, 2nd, etc, Sunday, Monday, etc. in a given
         
     | 
| 
      
 398 
     | 
    
         
            +
            month.  ~FatDate~ provides the class method ~Date.nth_wday_in_year_month(nth,
         
     | 
| 
      
 399 
     | 
    
         
            +
            wday, year, month)~ to return such dates.  The first parameter can be
         
     | 
| 
      
 400 
     | 
    
         
            +
            negative, which will count from the end of the month.
         
     | 
| 
      
 401 
     | 
    
         
            +
             
     | 
| 
      
 402 
     | 
    
         
            +
            #+begin_src ruby
         
     | 
| 
      
 403 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
              results = []
         
     | 
| 
      
 406 
     | 
    
         
            +
              results << ['n', 'Year', 'Month', 'nth Thursday']
         
     | 
| 
      
 407 
     | 
    
         
            +
              results << nil
         
     | 
| 
      
 408 
     | 
    
         
            +
              (1..4).each do |n|
         
     | 
| 
      
 409 
     | 
    
         
            +
                d = Date.nth_wday_in_year_month(n, 4, 2024, 6)
         
     | 
| 
      
 410 
     | 
    
         
            +
                results << [n, d.year, 'June', d.org]
         
     | 
| 
      
 411 
     | 
    
         
            +
              end
         
     | 
| 
      
 412 
     | 
    
         
            +
              (-4..-1).to_a.reverse.each do |n|
         
     | 
| 
      
 413 
     | 
    
         
            +
                d = Date.nth_wday_in_year_month(n, 4, 2024, 6)
         
     | 
| 
      
 414 
     | 
    
         
            +
                results << [n, d.year, 'June', d.org]
         
     | 
| 
      
 415 
     | 
    
         
            +
              end
         
     | 
| 
      
 416 
     | 
    
         
            +
              results
         
     | 
| 
      
 417 
     | 
    
         
            +
            #+end_src
         
     | 
| 
      
 418 
     | 
    
         
            +
             
     | 
| 
      
 419 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 420 
     | 
    
         
            +
            | n  | Year | Month | nth Thursday     |
         
     | 
| 
      
 421 
     | 
    
         
            +
            |----+------+-------+------------------|
         
     | 
| 
      
 422 
     | 
    
         
            +
            | 1  | 2024 | June  | [2024-06-06 Thu] |
         
     | 
| 
      
 423 
     | 
    
         
            +
            | 2  | 2024 | June  | [2024-06-13 Thu] |
         
     | 
| 
      
 424 
     | 
    
         
            +
            | 3  | 2024 | June  | [2024-06-20 Thu] |
         
     | 
| 
      
 425 
     | 
    
         
            +
            | 4  | 2024 | June  | [2024-06-27 Thu] |
         
     | 
| 
      
 426 
     | 
    
         
            +
            | -1 | 2024 | June  | [2024-06-27 Thu] |
         
     | 
| 
      
 427 
     | 
    
         
            +
            | -2 | 2024 | June  | [2024-06-20 Thu] |
         
     | 
| 
      
 428 
     | 
    
         
            +
            | -3 | 2024 | June  | [2024-06-13 Thu] |
         
     | 
| 
      
 429 
     | 
    
         
            +
            | -4 | 2024 | June  | [2024-06-06 Thu] |
         
     | 
| 
      
 430 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 431 
     | 
    
         
            +
             
     | 
| 
      
 432 
     | 
    
         
            +
            *** Easter
         
     | 
| 
      
 433 
     | 
    
         
            +
            Many holidays in the West are determined by the date of Easter, so FatDate
         
     | 
| 
      
 434 
     | 
    
         
            +
            provides the class method ~Date.easter(year)~ to return the date of Easter for
         
     | 
| 
      
 435 
     | 
    
         
            +
            the given year, using the Julian calendar date before the year of reform, and
         
     | 
| 
      
 436 
     | 
    
         
            +
            using the Gregorian calendar beginning in the year of reform.  By default, it
         
     | 
| 
      
 437 
     | 
    
         
            +
            uses 1582 for the date of reform, but it can take a named parameter,
         
     | 
| 
      
 438 
     | 
    
         
            +
            ~reform_year:~ to specify a different date.  For England, the year of reform
         
     | 
| 
      
 439 
     | 
    
         
            +
            was September, 1752.  So, to get a historically accurate date of Easter for
         
     | 
| 
      
 440 
     | 
    
         
            +
            Anglicans between 1582 and 1752, you should use a reform_year of 1753, since
         
     | 
| 
      
 441 
     | 
    
         
            +
            the reform happened after Easter in 1752.
         
     | 
| 
      
 442 
     | 
    
         
            +
             
     | 
| 
      
 443 
     | 
    
         
            +
            - ~Date.easter(year, reform_year: 1582)~ :: return the date of Easter for the
         
     | 
| 
      
 444 
     | 
    
         
            +
              given ~year~, assuming the given year of calendar reform; return nil for any
         
     | 
| 
      
 445 
     | 
    
         
            +
              year before 30AD.
         
     | 
| 
      
 446 
     | 
    
         
            +
            - Date#easter_this_year :: return the date of Easter for the year in which
         
     | 
| 
      
 447 
     | 
    
         
            +
              the subject Date falls.
         
     | 
| 
      
 448 
     | 
    
         
            +
            - Date#easter? :: return whether the subject Date is Easter.
         
     | 
| 
      
 449 
     | 
    
         
            +
             
     | 
| 
      
 450 
     | 
    
         
            +
            #+begin_src ruby
         
     | 
| 
      
 451 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 452 
     | 
    
         
            +
             
     | 
| 
      
 453 
     | 
    
         
            +
              yrs = [800, 1000, 1200, 1400, 1500, 1600, 1800, 2000]
         
     | 
| 
      
 454 
     | 
    
         
            +
              result = []
         
     | 
| 
      
 455 
     | 
    
         
            +
              result << ['Year', 'Easter Date']
         
     | 
| 
      
 456 
     | 
    
         
            +
              result << nil
         
     | 
| 
      
 457 
     | 
    
         
            +
              yrs.each do |y|
         
     | 
| 
      
 458 
     | 
    
         
            +
                result << [y, Date.easter(y).org ]
         
     | 
| 
      
 459 
     | 
    
         
            +
              end
         
     | 
| 
      
 460 
     | 
    
         
            +
              result
         
     | 
| 
      
 461 
     | 
    
         
            +
            #+end_src
         
     | 
| 
      
 462 
     | 
    
         
            +
             
     | 
| 
      
 463 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 464 
     | 
    
         
            +
            | Year | Easter Date      |
         
     | 
| 
      
 465 
     | 
    
         
            +
            |------+------------------|
         
     | 
| 
      
 466 
     | 
    
         
            +
            |  800 | [0800-04-19 Wed] |
         
     | 
| 
      
 467 
     | 
    
         
            +
            | 1000 | [1000-03-31 Mon] |
         
     | 
| 
      
 468 
     | 
    
         
            +
            | 1200 | [1200-04-09 Sun] |
         
     | 
| 
      
 469 
     | 
    
         
            +
            | 1400 | [1400-04-18 Fri] |
         
     | 
| 
      
 470 
     | 
    
         
            +
            | 1500 | [1500-04-19 Thu] |
         
     | 
| 
      
 471 
     | 
    
         
            +
            | 1600 | [1600-04-02 Sun] |
         
     | 
| 
      
 472 
     | 
    
         
            +
            | 1800 | [1800-04-13 Sun] |
         
     | 
| 
      
 473 
     | 
    
         
            +
            | 2000 | [2000-04-23 Sun] |
         
     | 
| 
      
 474 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 475 
     | 
    
         
            +
             
     | 
| 
      
 476 
     | 
    
         
            +
             
     | 
| 
      
 477 
     | 
    
         
            +
            *** Date Specs
         
     | 
| 
      
 478 
     | 
    
         
            +
            It is often desirable to get the first or last date of a specified time
         
     | 
| 
      
 479 
     | 
    
         
            +
            period.  For this ~FatDate~ provides the ~spec~ method that takes a string and
         
     | 
| 
      
 480 
     | 
    
         
            +
            an optional ~spec_type~ parameter of either ~:from~, indicating that the first
         
     | 
| 
      
 481 
     | 
    
         
            +
            date of the period should be returned or ~:to~, indicating that the last date
         
     | 
| 
      
 482 
     | 
    
         
            +
            of the period should be returned.  It assumes the ~spec_type~ to be ~:from~ by
         
     | 
| 
      
 483 
     | 
    
         
            +
            default.
         
     | 
| 
      
 484 
     | 
    
         
            +
             
     | 
| 
      
 485 
     | 
    
         
            +
            Though many specs, other than those specifying a single day, represent a
         
     | 
| 
      
 486 
     | 
    
         
            +
            period of time longer than one date, the ~Date.spec~ method returns a single
         
     | 
| 
      
 487 
     | 
    
         
            +
            date, either the first or last day of the period described by the spec.  See
         
     | 
| 
      
 488 
     | 
    
         
            +
            the library ~FatPeriod~ where the ~Date.spec~ method is put to good use in
         
     | 
| 
      
 489 
     | 
    
         
            +
            defining a ~Period~ type to represent ranges of time.
         
     | 
| 
      
 490 
     | 
    
         
            +
             
     | 
| 
      
 491 
     | 
    
         
            +
            The ~spec~ method supports a rich set of ways to specify periods of time.  The
         
     | 
| 
      
 492 
     | 
    
         
            +
            following sections catalog them all.
         
     | 
| 
      
 493 
     | 
    
         
            +
             
     | 
| 
      
 494 
     | 
    
         
            +
            **** Given Day
         
     | 
| 
      
 495 
     | 
    
         
            +
            - YYYY-MM-DD :: returns a single day given.
         
     | 
| 
      
 496 
     | 
    
         
            +
            - MM-DD :: returns the specified day of the specified month in the current
         
     | 
| 
      
 497 
     | 
    
         
            +
              year.
         
     | 
| 
      
 498 
     | 
    
         
            +
             
     | 
| 
      
 499 
     | 
    
         
            +
            **** Day-of-Year
         
     | 
| 
      
 500 
     | 
    
         
            +
            - YYYY-ddd :: returns the ddd'th day of the specified year. Note that exactly
         
     | 
| 
      
 501 
     | 
    
         
            +
              three digits are needed: with only two digits it would be interpreted as a
         
     | 
| 
      
 502 
     | 
    
         
            +
              month.
         
     | 
| 
      
 503 
     | 
    
         
            +
            - ddd :: returns the ddd'th day of the current year. Again, note that
         
     | 
| 
      
 504 
     | 
    
         
            +
              exactly three digits are needed: two digits would be interpreted as a month,
         
     | 
| 
      
 505 
     | 
    
         
            +
              and four digits as a year.
         
     | 
| 
      
 506 
     | 
    
         
            +
             
     | 
| 
      
 507 
     | 
    
         
            +
            **** Month
         
     | 
| 
      
 508 
     | 
    
         
            +
            The following return the first or last day of the given month.
         
     | 
| 
      
 509 
     | 
    
         
            +
             
     | 
| 
      
 510 
     | 
    
         
            +
            - YYYY-MM :: returns the first or last day of the specified month in the
         
     | 
| 
      
 511 
     | 
    
         
            +
              specified year.
         
     | 
| 
      
 512 
     | 
    
         
            +
            - MM :: returns first or last day of the specified month of the current year.
         
     | 
| 
      
 513 
     | 
    
         
            +
             
     | 
| 
      
 514 
     | 
    
         
            +
            **** Year
         
     | 
| 
      
 515 
     | 
    
         
            +
            - YYYY :: returns the first or last day of the specified year.
         
     | 
| 
      
 516 
     | 
    
         
            +
             
     | 
| 
      
 517 
     | 
    
         
            +
            **** Commercial Weeks-of-Year
         
     | 
| 
      
 518 
     | 
    
         
            +
            - YYYY-Wnn or YYYY-nnW :: returns the first or last day of the nn'th
         
     | 
| 
      
 519 
     | 
    
         
            +
              commercial week of the given year according to the ISO 8601 standard, in
         
     | 
| 
      
 520 
     | 
    
         
            +
              which the week containing the first Thursday of the year counts as the first
         
     | 
| 
      
 521 
     | 
    
         
            +
              commercial week, even if that week started in the prior calendar year,
         
     | 
| 
      
 522 
     | 
    
         
            +
            - Wnn or nnW :: returns the first or last day of the nn'th commercial week of
         
     | 
| 
      
 523 
     | 
    
         
            +
              the current year,
         
     | 
| 
      
 524 
     | 
    
         
            +
             
     | 
| 
      
 525 
     | 
    
         
            +
            **** Halves
         
     | 
| 
      
 526 
     | 
    
         
            +
            - YYYY-1H or YYYY-2H :: returns the first or last day of the specified half
         
     | 
| 
      
 527 
     | 
    
         
            +
              year for the given year,
         
     | 
| 
      
 528 
     | 
    
         
            +
            - 1H or 2H :: returns the first or last day of the specified half year for the
         
     | 
| 
      
 529 
     | 
    
         
            +
              current year,
         
     | 
| 
      
 530 
     | 
    
         
            +
             
     | 
| 
      
 531 
     | 
    
         
            +
            **** Quarters
         
     | 
| 
      
 532 
     | 
    
         
            +
            - YYYY-1Q, YYYY-2Q, etc  :: returns the first or last day of the calendar
         
     | 
| 
      
 533 
     | 
    
         
            +
              quarter for the given year,
         
     | 
| 
      
 534 
     | 
    
         
            +
            - 1Q, 2Q, etc  :: returns the first or last day of the calendar quarter for
         
     | 
| 
      
 535 
     | 
    
         
            +
              the current year,
         
     | 
| 
      
 536 
     | 
    
         
            +
             
     | 
| 
      
 537 
     | 
    
         
            +
            **** Semi-Months
         
     | 
| 
      
 538 
     | 
    
         
            +
            - YYYY-MM-A or YYYY-MM-B :: returns the first or last day of the semi-month
         
     | 
| 
      
 539 
     | 
    
         
            +
              for the given month and year, where the first semi-month always runs from
         
     | 
| 
      
 540 
     | 
    
         
            +
              the 1st to the 15th and the second semi-month always runs from the 16th to
         
     | 
| 
      
 541 
     | 
    
         
            +
              the last day of the given month, regardless of the number of days in the
         
     | 
| 
      
 542 
     | 
    
         
            +
              month.
         
     | 
| 
      
 543 
     | 
    
         
            +
            - MM-A or MM-B :: returns the first or last day of the semi-month of the
         
     | 
| 
      
 544 
     | 
    
         
            +
              current year.
         
     | 
| 
      
 545 
     | 
    
         
            +
            - A or B :: returns the first or last day of the semi-month of the current
         
     | 
| 
      
 546 
     | 
    
         
            +
              year and month.
         
     | 
| 
      
 547 
     | 
    
         
            +
             
     | 
| 
      
 548 
     | 
    
         
            +
            **** Week-of-Month
         
     | 
| 
      
 549 
     | 
    
         
            +
            - YYYY-MM-i or YYYY-MM-ii up to YYYY-MM-vi :: returns the first or last day of
         
     | 
| 
      
 550 
     | 
    
         
            +
              the given week within the month, including any partial weeks,
         
     | 
| 
      
 551 
     | 
    
         
            +
            - MM-i or MM-ii up to MM-vi :: returns the first or last day of the given week
         
     | 
| 
      
 552 
     | 
    
         
            +
              within the month of the current year, including any partial weeks,
         
     | 
| 
      
 553 
     | 
    
         
            +
            - i or ii up to vi :: returns the first or last day of the given week within
         
     | 
| 
      
 554 
     | 
    
         
            +
              the current month of the current year, including any partial weeks,
         
     | 
| 
      
 555 
     | 
    
         
            +
             
     | 
| 
      
 556 
     | 
    
         
            +
            **** Day-of-Week
         
     | 
| 
      
 557 
     | 
    
         
            +
            - YYYY-MM-nSu up to YYYY-MM-nSa  :: returns the single day that is the n'th
         
     | 
| 
      
 558 
     | 
    
         
            +
              Sunday, Monday, etc., in the given month using the first two letters of the
         
     | 
| 
      
 559 
     | 
    
         
            +
              English names for the days of the week,
         
     | 
| 
      
 560 
     | 
    
         
            +
            - MM-nSu up to MM-nSa or MM-nSun up to MM-nSat :: returns the single date that
         
     | 
| 
      
 561 
     | 
    
         
            +
              is the n'th Sunday, Monday, etc., in the given month of the current year
         
     | 
| 
      
 562 
     | 
    
         
            +
              using the first two letters of the English names for the days of the week,
         
     | 
| 
      
 563 
     | 
    
         
            +
            - nSu up to nSa or nSun up to nSat :: returns the single date that is the n'th
         
     | 
| 
      
 564 
     | 
    
         
            +
              Sunday, Monday, etc., in the current month of the current year using the
         
     | 
| 
      
 565 
     | 
    
         
            +
              first two letters of the English names for the days of the week,
         
     | 
| 
      
 566 
     | 
    
         
            +
             
     | 
| 
      
 567 
     | 
    
         
            +
            **** Easter Based
         
     | 
| 
      
 568 
     | 
    
         
            +
            - YYYY-E :: returns the single date of Easter in the Western church for the
         
     | 
| 
      
 569 
     | 
    
         
            +
              given year,
         
     | 
| 
      
 570 
     | 
    
         
            +
            - E :: returns the single date of Easter in the Western church for the current
         
     | 
| 
      
 571 
     | 
    
         
            +
              year,
         
     | 
| 
      
 572 
     | 
    
         
            +
            - YYYY-E-n or YYYY-E+n :: returns the single date that falls n days before (-)
         
     | 
| 
      
 573 
     | 
    
         
            +
              or after (+) Easter in the Western church for the given year,
         
     | 
| 
      
 574 
     | 
    
         
            +
            - E-n or E+n :: returns the single date that falls n days before (-) or after
         
     | 
| 
      
 575 
     | 
    
         
            +
              (+) Easter in the Western church for the current year,
         
     | 
| 
      
 576 
     | 
    
         
            +
             
     | 
| 
      
 577 
     | 
    
         
            +
            **** Relative Dates
         
     | 
| 
      
 578 
     | 
    
         
            +
            - yesterday or yesteryear or lastday or last_year, etc :: the relative
         
     | 
| 
      
 579 
     | 
    
         
            +
              prefixes, 'last' or 'yester' prepended to any chunk name returns the period
         
     | 
| 
      
 580 
     | 
    
         
            +
              named by the chunk that precedes today's date.
         
     | 
| 
      
 581 
     | 
    
         
            +
            - today or toyear or this-year or thissemimonth, etc :: the relative prefixes,
         
     | 
| 
      
 582 
     | 
    
         
            +
              'to' or 'this' prepended to any chunk name returns the period named by
         
     | 
| 
      
 583 
     | 
    
         
            +
              the chunk that contains today's date.
         
     | 
| 
      
 584 
     | 
    
         
            +
            - nextday or nextyear or next-year or nextsemimonth, etc :: the relative
         
     | 
| 
      
 585 
     | 
    
         
            +
              prefixes, 'next' prepended to any chunk name returns the period named by the
         
     | 
| 
      
 586 
     | 
    
         
            +
              chunk that follows today's date. As a special case, 'tomorrow' is treated as
         
     | 
| 
      
 587 
     | 
    
         
            +
              equivalent to 'nextday'.
         
     | 
| 
      
 588 
     | 
    
         
            +
             
     | 
| 
      
 589 
     | 
    
         
            +
            **** Extremes
         
     | 
| 
      
 590 
     | 
    
         
            +
            - forever :: returns Date::BOT for :from, and Date::EOT for :to, which, for
         
     | 
| 
      
 591 
     | 
    
         
            +
              financial applications is meant to stand in for eternity.
         
     | 
| 
      
 592 
     | 
    
         
            +
            - never :: returns nil, representing no date.
         
     | 
| 
      
 593 
     | 
    
         
            +
             
     | 
| 
      
 594 
     | 
    
         
            +
            **** Skip Modifiers
         
     | 
| 
      
 595 
     | 
    
         
            +
            Appended to any of the above specs (other than 'never'), you may add a 'skip
         
     | 
| 
      
 596 
     | 
    
         
            +
            modifier' to change the date to the first day-of-week adjacent to the date
         
     | 
| 
      
 597 
     | 
    
         
            +
            that the spec resolves to.  This is done by appending one of the following to
         
     | 
| 
      
 598 
     | 
    
         
            +
            the spec:
         
     | 
| 
      
 599 
     | 
    
         
            +
             
     | 
| 
      
 600 
     | 
    
         
            +
            - '<Su', '<Mo', ... '<Sa' :: change to the first Sunday, Monday, etc.,
         
     | 
| 
      
 601 
     | 
    
         
            +
              /before/ the date the spec resolves to.
         
     | 
| 
      
 602 
     | 
    
         
            +
            - '<=Su', '<=Mo', ... '<=Sa' :: change to the first Sunday, Monday, etc., /on
         
     | 
| 
      
 603 
     | 
    
         
            +
              or before/ the date the spec resolves to.
         
     | 
| 
      
 604 
     | 
    
         
            +
            - '>Su', '>Mo', ... '>Sa' :: change to the first Sunday, Monday, etc.,
         
     | 
| 
      
 605 
     | 
    
         
            +
              /after/ the date the spec resolves to.
         
     | 
| 
      
 606 
     | 
    
         
            +
            - '>=Su', '>=Mo', ... '>=Sa' :: change to the first Sunday, Monday, etc., /on
         
     | 
| 
      
 607 
     | 
    
         
            +
              or after/ the date the spec resolves to.
         
     | 
| 
      
 608 
     | 
    
         
            +
             
     | 
| 
      
 609 
     | 
    
         
            +
            For example, ~Date.spec('2024<=Tu', :to)~ resolves to the last Tuesday
         
     | 
| 
      
 610 
     | 
    
         
            +
            of 2024, which happens to be December 31, 2024; ~Date.spec('2024<Tu',
         
     | 
| 
      
 611 
     | 
    
         
            +
            :to)~, on the other hand would resolve to December 24, 2024, since it looks
         
     | 
| 
      
 612 
     | 
    
         
            +
            for the first Tuesday strictly /before/ December 31, 2024.
         
     | 
| 
      
 613 
     | 
    
         
            +
             
     | 
| 
      
 614 
     | 
    
         
            +
            **** Conventions
         
     | 
| 
      
 615 
     | 
    
         
            +
            Some things to note with respect to ~Date.spec~:
         
     | 
| 
      
 616 
     | 
    
         
            +
             
     | 
| 
      
 617 
     | 
    
         
            +
            1. The second argument can be either ~:from~ or ~:to~, but it defaults to
         
     | 
| 
      
 618 
     | 
    
         
            +
               ~:from~.  If it is ~:from~, ~spec~ returns the first date of the
         
     | 
| 
      
 619 
     | 
    
         
            +
               specified period; if it is ~:to~, it returns the last date of the specified
         
     | 
| 
      
 620 
     | 
    
         
            +
               period.  When the "period" resolves to a single day, both arguments return
         
     | 
| 
      
 621 
     | 
    
         
            +
               the same date, so ~spec('2024-E', :from)~ and ~spec('2024-E',
         
     | 
| 
      
 622 
     | 
    
         
            +
               :to)~ both result in March 31, 2024.
         
     | 
| 
      
 623 
     | 
    
         
            +
            2. Where relevant, ~spec~ accepts letters of either upper or lower case:
         
     | 
| 
      
 624 
     | 
    
         
            +
               so 2024-1Q can be written 2024-1q and 'yesteryear' can be written
         
     | 
| 
      
 625 
     | 
    
         
            +
               'YeSterYeaR', and likewise for all components of the spec using letters.
         
     | 
| 
      
 626 
     | 
    
         
            +
            3. Date components can be separated with either a hyphen, as in the examples
         
     | 
| 
      
 627 
     | 
    
         
            +
               above, or with a '/' as is common.  Thus, 2024-11-09 can also be
         
     | 
| 
      
 628 
     | 
    
         
            +
               2024/11/09, or indeed, 2024/11-09 or 2024-11/09.
         
     | 
| 
      
 629 
     | 
    
         
            +
            4. The prefixes for relative periods can be separated from the period name by
         
     | 
| 
      
 630 
     | 
    
         
            +
               a hyphen, and underscore, or by nothing at all.  Thus, yester-day,
         
     | 
| 
      
 631 
     | 
    
         
            +
               yester_day, and yesterday are all acceptable.  Neologisms such as
         
     | 
| 
      
 632 
     | 
    
         
            +
               'yestermonth' are quaint, but not harmful.
         
     | 
| 
      
 633 
     | 
    
         
            +
            5. Where the names of days of the week are appropriate, any word that starts
         
     | 
| 
      
 634 
     | 
    
         
            +
               with 'su' counts as Sunday, regardless of case, any word that starts with
         
     | 
| 
      
 635 
     | 
    
         
            +
               'mo' counts as Monday, and so on.
         
     | 
| 
      
 636 
     | 
    
         
            +
            6. 'fortnight' is a synonym for a biweek.
         
     | 
| 
      
 637 
     | 
    
         
            +
             
     | 
| 
      
 638 
     | 
    
         
            +
            **** Examples
         
     | 
| 
      
 639 
     | 
    
         
            +
             
     | 
| 
      
 640 
     | 
    
         
            +
            #+begin_src ruby results :value
         
     | 
| 
      
 641 
     | 
    
         
            +
              require './lib/fat_date'
         
     | 
| 
      
 642 
     | 
    
         
            +
             
     | 
| 
      
 643 
     | 
    
         
            +
              strs = ['today', '2024-07-04', '2024-05', '2024', '2024-333',
         
     | 
| 
      
 644 
     | 
    
         
            +
                     '08', '08-12', '2024-W36', '2024-36W', 'W36', '36W',
         
     | 
| 
      
 645 
     | 
    
         
            +
                     '2024-1H', '2024-2H', '1H', '2H',
         
     | 
| 
      
 646 
     | 
    
         
            +
                     '1957-1Q', '1957-2Q', '1957-3Q', '1957-4Q',
         
     | 
| 
      
 647 
     | 
    
         
            +
                     '1Q', '2Q', '3Q', '4Q',
         
     | 
| 
      
 648 
     | 
    
         
            +
                     '2021-09-I', '2021-09-II',
         
     | 
| 
      
 649 
     | 
    
         
            +
                     '2021-09-i', '2021-09-ii', '2021-09-iii', '2021-09-iv', '2021-09-v',
         
     | 
| 
      
 650 
     | 
    
         
            +
                     '10-i', '10-iii',
         
     | 
| 
      
 651 
     | 
    
         
            +
                     '2016-04-3Tu', '2016-11-4Th', '2016-11-2Th',
         
     | 
| 
      
 652 
     | 
    
         
            +
                     '05-3We', '06-3Wed', '3Su', '4Sa',
         
     | 
| 
      
 653 
     | 
    
         
            +
                     '1830-E', 'E', '2012-E+10', '2024-E+40',
         
     | 
| 
      
 654 
     | 
    
         
            +
                     '2025-E+50>=Su'
         
     | 
| 
      
 655 
     | 
    
         
            +
                     ]
         
     | 
| 
      
 656 
     | 
    
         
            +
              tab = []
         
     | 
| 
      
 657 
     | 
    
         
            +
              tab << ['Spec', 'From', 'To']
         
     | 
| 
      
 658 
     | 
    
         
            +
              tab << nil
         
     | 
| 
      
 659 
     | 
    
         
            +
              strs.each do |s|
         
     | 
| 
      
 660 
     | 
    
         
            +
                tab << ["'#{s}'", Date.spec(s, :from).org, Date.spec(s, :to).org]
         
     | 
| 
      
 661 
     | 
    
         
            +
              end
         
     | 
| 
      
 662 
     | 
    
         
            +
              tab
         
     | 
| 
      
 663 
     | 
    
         
            +
            #+end_src
         
     | 
| 
      
 664 
     | 
    
         
            +
             
     | 
| 
      
 665 
     | 
    
         
            +
            #+begin_example
         
     | 
| 
      
 666 
     | 
    
         
            +
            | Spec            | From             | To               |
         
     | 
| 
      
 667 
     | 
    
         
            +
            |-----------------+------------------+------------------|
         
     | 
| 
      
 668 
     | 
    
         
            +
            | 'today'         | [2025-10-16 Thu] | [2025-10-16 Thu] |
         
     | 
| 
      
 669 
     | 
    
         
            +
            | '2024-07-04'    | [2024-07-04 Thu] | [2024-07-04 Thu] |
         
     | 
| 
      
 670 
     | 
    
         
            +
            | '2024-05'       | [2024-05-01 Wed] | [2024-05-31 Fri] |
         
     | 
| 
      
 671 
     | 
    
         
            +
            | '2024'          | [2024-01-01 Mon] | [2024-12-31 Tue] |
         
     | 
| 
      
 672 
     | 
    
         
            +
            | '2024-333'      | [2024-11-28 Thu] | [2024-11-28 Thu] |
         
     | 
| 
      
 673 
     | 
    
         
            +
            | '08'            | [2025-08-01 Fri] | [2025-08-31 Sun] |
         
     | 
| 
      
 674 
     | 
    
         
            +
            | '08-12'         | [2025-08-12 Tue] | [2025-08-12 Tue] |
         
     | 
| 
      
 675 
     | 
    
         
            +
            | '2024-W36'      | [2024-09-02 Mon] | [2024-09-08 Sun] |
         
     | 
| 
      
 676 
     | 
    
         
            +
            | '2024-36W'      | [2024-09-02 Mon] | [2024-09-08 Sun] |
         
     | 
| 
      
 677 
     | 
    
         
            +
            | 'W36'           | [2025-09-01 Mon] | [2025-09-07 Sun] |
         
     | 
| 
      
 678 
     | 
    
         
            +
            | '36W'           | [2025-09-01 Mon] | [2025-09-07 Sun] |
         
     | 
| 
      
 679 
     | 
    
         
            +
            | '2024-1H'       | [2024-01-01 Mon] | [2024-06-30 Sun] |
         
     | 
| 
      
 680 
     | 
    
         
            +
            | '2024-2H'       | [2024-07-01 Mon] | [2024-12-31 Tue] |
         
     | 
| 
      
 681 
     | 
    
         
            +
            | '1H'            | [2025-01-01 Wed] | [2025-06-30 Mon] |
         
     | 
| 
      
 682 
     | 
    
         
            +
            | '2H'            | [2025-07-01 Tue] | [2025-12-31 Wed] |
         
     | 
| 
      
 683 
     | 
    
         
            +
            | '1957-1Q'       | [1957-01-01 Tue] | [1957-03-31 Sun] |
         
     | 
| 
      
 684 
     | 
    
         
            +
            | '1957-2Q'       | [1957-04-01 Mon] | [1957-06-30 Sun] |
         
     | 
| 
      
 685 
     | 
    
         
            +
            | '1957-3Q'       | [1957-07-01 Mon] | [1957-09-30 Mon] |
         
     | 
| 
      
 686 
     | 
    
         
            +
            | '1957-4Q'       | [1957-10-01 Tue] | [1957-12-31 Tue] |
         
     | 
| 
      
 687 
     | 
    
         
            +
            | '1Q'            | [2025-01-01 Wed] | [2025-03-31 Mon] |
         
     | 
| 
      
 688 
     | 
    
         
            +
            | '2Q'            | [2025-04-01 Tue] | [2025-06-30 Mon] |
         
     | 
| 
      
 689 
     | 
    
         
            +
            | '3Q'            | [2025-07-01 Tue] | [2025-09-30 Tue] |
         
     | 
| 
      
 690 
     | 
    
         
            +
            | '4Q'            | [2025-10-01 Wed] | [2025-12-31 Wed] |
         
     | 
| 
      
 691 
     | 
    
         
            +
            | '2021-09-I'     | [2021-09-01 Wed] | [2021-09-05 Sun] |
         
     | 
| 
      
 692 
     | 
    
         
            +
            | '2021-09-II'    | [2021-09-06 Mon] | [2021-09-12 Sun] |
         
     | 
| 
      
 693 
     | 
    
         
            +
            | '2021-09-i'     | [2021-09-01 Wed] | [2021-09-05 Sun] |
         
     | 
| 
      
 694 
     | 
    
         
            +
            | '2021-09-ii'    | [2021-09-06 Mon] | [2021-09-12 Sun] |
         
     | 
| 
      
 695 
     | 
    
         
            +
            | '2021-09-iii'   | [2021-09-13 Mon] | [2021-09-19 Sun] |
         
     | 
| 
      
 696 
     | 
    
         
            +
            | '2021-09-iv'    | [2021-09-20 Mon] | [2021-09-26 Sun] |
         
     | 
| 
      
 697 
     | 
    
         
            +
            | '2021-09-v'     | [2021-09-27 Mon] | [2021-09-30 Thu] |
         
     | 
| 
      
 698 
     | 
    
         
            +
            | '10-i'          | [2025-10-01 Wed] | [2025-10-05 Sun] |
         
     | 
| 
      
 699 
     | 
    
         
            +
            | '10-iii'        | [2025-10-13 Mon] | [2025-10-19 Sun] |
         
     | 
| 
      
 700 
     | 
    
         
            +
            | '2016-04-3Tu'   | [2016-04-19 Tue] | [2016-04-19 Tue] |
         
     | 
| 
      
 701 
     | 
    
         
            +
            | '2016-11-4Th'   | [2016-11-24 Thu] | [2016-11-24 Thu] |
         
     | 
| 
      
 702 
     | 
    
         
            +
            | '2016-11-2Th'   | [2016-11-10 Thu] | [2016-11-10 Thu] |
         
     | 
| 
      
 703 
     | 
    
         
            +
            | '05-3We'        | [2025-05-21 Wed] | [2025-05-21 Wed] |
         
     | 
| 
      
 704 
     | 
    
         
            +
            | '06-3Wed'       | [2025-06-18 Wed] | [2025-06-18 Wed] |
         
     | 
| 
      
 705 
     | 
    
         
            +
            | '3Su'           | [2025-10-19 Sun] | [2025-10-19 Sun] |
         
     | 
| 
      
 706 
     | 
    
         
            +
            | '4Sa'           | [2025-10-25 Sat] | [2025-10-25 Sat] |
         
     | 
| 
      
 707 
     | 
    
         
            +
            | '1830-E'        | [1830-04-11 Sun] | [1830-04-11 Sun] |
         
     | 
| 
      
 708 
     | 
    
         
            +
            | 'E'             | [2025-04-20 Sun] | [2025-04-20 Sun] |
         
     | 
| 
      
 709 
     | 
    
         
            +
            | '2012-E+10'     | [2012-04-18 Wed] | [2012-04-18 Wed] |
         
     | 
| 
      
 710 
     | 
    
         
            +
            | '2024-E+40'     | [2024-05-10 Fri] | [2024-05-10 Fri] |
         
     | 
| 
      
 711 
     | 
    
         
            +
            | '2025-E+50>=Su' | [2025-06-15 Sun] | [2025-06-15 Sun] |
         
     | 
| 
      
 712 
     | 
    
         
            +
            #+end_example
         
     | 
| 
      
 713 
     | 
    
         
            +
             
     | 
| 
      
 714 
     | 
    
         
            +
            * Contributing
         
     | 
| 
      
 715 
     | 
    
         
            +
             
     | 
| 
      
 716 
     | 
    
         
            +
            1. Fork it ([[http://github.com/ddoherty03/fat_core/fork]]  )
         
     | 
| 
      
 717 
     | 
    
         
            +
            2. Create your feature branch (~git checkout -b my-new-feature~)
         
     | 
| 
      
 718 
     | 
    
         
            +
            3. Commit your changes (~git commit -am 'Add some feature'~)
         
     | 
| 
      
 719 
     | 
    
         
            +
            4. Push to the branch (~git push origin my-new-feature~)
         
     | 
| 
      
 720 
     | 
    
         
            +
            5. Create new Pull Request
         
     |