Skip to content

yoshinari-nomura/enumdate

Repository files navigation

enumdate – a small enumerator library to expand recurring dates

https://badge.fury.io/rb/enumdate.svg https://github.com/yoshinari-nomura/enumdate/actions/workflows/main.yml/badge.svg

Description

Enumdate is a small enumerator library to expand recurring dates.

You can get the latest version from:

How to use

Create enumerables

These are simple examples to create enumerables:

#      June 2021
# Su Mo Tu We Th Fr Sa
#        1  2  3  4  5
#  6  7  8  9 10 11 12
# 13 14 15 16 17 18 19
# 20 21 22 23 24 25 26
# 27 28 29 30
#
start = Date.new(2021, 6, 1) # first Tuesday June

# June 1st every year:
Enumdate.yearly_by_monthday(start).lazy.map(&:to_s).take(3).force
# => ["2021-06-01", "2022-06-01", "2023-06-01"]

# First Tuesday June every year:
Enumdate.yearly_by_day(start).lazy.map(&:to_s).take(3).force
# => ["2021-06-01", "2022-06-07", "2023-06-06"]

# 1st monthday every month:
Enumdate.monthly_by_monthday(start).lazy.map(&:to_s).take(3).force
# => ["2021-06-01", "2021-07-01", "2021-08-01"]

# First Tuesday every month:
Enumdate.monthly_by_day(start).lazy.map(&:to_s).take(3).force
# => ["2021-06-01", "2021-07-06", "2021-08-03"]

# every Tuesday:
Enumdate.weekly(start).lazy.map(&:to_s).take(3).force
# => ["2021-06-01", "2021-06-08", "2021-06-15"]

# Everyday:
Enumdate.daily(start).lazy.map(&:to_s).take(3).force
# => ["2021-06-01", "2021-06-02", "2021-06-03"]

These constructor methods can take more complex parameters such as month:, mday:, wday:, nth:, wkst:, interval:. See the gem document for details.

Make finite durations

This code makes infinite loop (every two years forever):

start = Date.new(2021, 6, 1)
Enumdate.yearly_by_monthday(start, interval: 2).each do |date|
  puts date
end

Results:

2021-06-01
2023-06-01
2025-06-01
:

To clip the duration, you can use forward_to and until:

start = Date.new(2021, 6, 1)
Enumdate.yearly_by_monthday(start, interval: 2)
  .forward_to(Date.new(2022, 1, 1))
  .until(Date.new(2025, 12, 31))
  .each do |date|
  puts date
end

Results:

2023-06-01
2025-06-01

Note that the meaning of forward_to is different from that of changing the start parameter.

start = Date.new(2022, 1, 1) # changed as if set forward_to
Enumdate.yearly_by_monthday(start, interval: 2)
  .until(Date.new(2025, 12, 31))
  .each do |date|
  puts date
end

Results:

2022-01-01
2024-01-01

forward_to and until clip concrete occurrences without changing the recurring pattern.

Merge multiple enumerables

Sometimes, you may need to compose more complex recurring patterns. In this case, you can merge multiple enumerables:

first = Date.new(2021, 8, 4) # Wednesday

# Every Monday and Wednesday:
(Enumdate::EnumMerger.new << Enumdate.weekly(first) << Enumdate.weekly(first, wday: 1))
  .lazy.map(&:to_s).take(4).force
# => ["2021-08-04", "2021-08-09", "2021-08-11", "2021-08-16"]

Installation

Add this line to your application’s Gemfile:

gem "enumdate"

And then execute:

$ bundle install

Or install it yourself as:

$ gem install enumdate

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/yoshinari-nomura/enumdate.

License

The gem is available as open source under the terms of the MIT License.

About

A small enumerator library to expand recurring dates written in Ruby

Resources

License

Stars

Watchers

Forks

Packages

No packages published