<commit_before># Repeatable

[![Build Status](https://img.shields.io/travis/molawson/repeatable.svg)](https://travis-ci.org/molawson/repeatable)
[![Code Climate](https://img.shields.io/codeclimate/github/molawson/repeatable.svg)](https://codeclimate.com/github/molawson/repeatable)
[![Code Climate Coverage](https://img.shields.io/codeclimate/coverage/github/molawson/repeatable.svg)](https://codeclimate.com/github/molawson/repeatable)

Ruby implementation of Martin Fowler's [Recurring Events for Calendars](http://martinfowler.com/apsupp/recurring.pdf) paper.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'repeatable'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install repeatable

## Requirements

Because this gem relies heavily on required keyword arguments, especially to make dumping and parsing of schedules simpler, this code will only work on **Ruby 2.1** and higher.

## Usage

### Building a Schedule

You can create a schedule in one of two ways.

#### Composed objects

Instantiate and compose each of the `Repeatable::Expression` objects manually.

```ruby
second_monday = Repeatabe::Expression::WeekdayInMonth.new(weekday: 1, count: 2)
oct_thru_dec = Repeatable::Expression::RangeInYear.new(start_month: 10, end_month: 12)
intersection = Repeatable::Expresson::Intersection.new(second_monday, oct_thru_dec)

schedule = Repeatable::Schedule.new(intersection)
```


#### Hash

Or describe the same structure with a `Hash`, and the gem will handle instantiating and composing the objects.

```ruby
arg = {
  intersection: [
    { weekday_in_month: { weekday: 1, count: 2 } },
    { range_in_year: { start_month: 10, end_month: 12 } }
  ]
}

schedule = Repeatable::Schedule.new(arg)
```

- - -

#### Time Expressions

There are a number of time expressions available which, when combined, can describe most any schedule.

```ruby
# SETS

# Any conditions can be met
{ union: [] }
Repeatable::Expression::Union.new(expressions)

# All conditions must be met
{ intersection: [] }
Repeatable::Expression::Intersection.new(expressions)
<commit_msg>Update README with Expression::Difference<commit_after># Repeatable

[![Build Status](https://img.shields.io/travis/molawson/repeatable.svg)](https://travis-ci.org/molawson/repeatable)
[![Code Climate](https://img.shields.io/codeclimate/github/molawson/repeatable.svg)](https://codeclimate.com/github/molawson/repeatable)
[![Code Climate Coverage](https://img.shields.io/codeclimate/coverage/github/molawson/repeatable.svg)](https://codeclimate.com/github/molawson/repeatable)

Ruby implementation of Martin Fowler's [Recurring Events for Calendars](http://martinfowler.com/apsupp/recurring.pdf) paper.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'repeatable'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install repeatable

## Requirements

Because this gem relies heavily on required keyword arguments, especially to make dumping and parsing of schedules simpler, this code will only work on **Ruby 2.1** and higher.

## Usage

### Building a Schedule

You can create a schedule in one of two ways.

#### Composed objects

Instantiate and compose each of the `Repeatable::Expression` objects manually.

```ruby
second_monday = Repeatabe::Expression::WeekdayInMonth.new(weekday: 1, count: 2)
oct_thru_dec = Repeatable::Expression::RangeInYear.new(start_month: 10, end_month: 12)
intersection = Repeatable::Expresson::Intersection.new(second_monday, oct_thru_dec)

schedule = Repeatable::Schedule.new(intersection)
```


#### Hash

Or describe the same structure with a `Hash`, and the gem will handle instantiating and composing the objects.

```ruby
arg = {
  intersection: [
    { weekday_in_month: { weekday: 1, count: 2 } },
    { range_in_year: { start_month: 10, end_month: 12 } }
  ]
}

schedule = Repeatable::Schedule.new(arg)
```

- - -

#### Time Expressions

There are a number of time expressions available which, when combined, can describe most any schedule.

```ruby
# SETS

# Any conditions can be met
{ union: [] }
Repeatable::Expression::Union.new(expressions)

# All conditions must be met
{ intersection: [] }
Repeatable::Expression::Intersection.new(expressions)

# Date is part of the first set (`included`) but not part of the second set (`excluded`)
{ difference: { included: expression, excluded: another_expression } }
Repeatable::Expression::Difference.new(included: expression, excluded: another_expression)

{'fraction_non_alphanumeric': 0.12234513274336282, 'fraction_numerical': 0.006194690265486726, 'mean_word_length': 5.331932773109243, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 12, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1904027', 'n_tokens_mistral': 1492, 'n_tokens_neox': 1363, 'n_words': 388}