diff --git a/LICENSE b/LICENSE
index 290fec0..d2acf90 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2008-2010 Adam Meehan
+Copyright (c) 2008-2021 Adam Meehan
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..d849801
--- /dev/null
+++ b/README.md
@@ -0,0 +1,353 @@
+# ValidatesTimeliness [](https://travis-ci.org/adzap/validates_timeliness)
+
+* Source: https://github.com/adzap/validates_timeliness
+* Issues: https://github.com/adzap/validates_timeliness/issues
+
+
+## Description
+
+Complete validation of dates, times and datetimes for Rails 5.x, 6.x, and
+ActiveModel.
+
+If you a looking for the old version for Rails 4.x go here
+[https://github.com/adzap/validates_timeliness/tree/4-0-stable].
+
+## Features
+
+* Adds validation for dates, times and datetimes to ActiveModel
+* Handles timezones and type casting of values for you
+* Only Rails date/time validation plugin offering complete validation (See
+ ORM/ODM support)
+* Uses extensible date/time parser (Using [timeliness
+ gem](https://github.com/adzap/timeliness). See Plugin Parser)
+* Adds extensions to fix Rails date/time select issues (See Extensions)
+* Supports I18n for the error messages. For multi-language support try
+ [timeliness-i18n gem](https://github.com/pedrofurtado/timeliness-i18n).
+* Supports all the Rubies (that any sane person would be using in
+ production).
+
+
+## Installation
+
+```
+# in Gemfile
+gem 'validates_timeliness', '~> 5.0.0.beta1'
+
+# Run bundler
+$ bundle install
+```
+
+Then run
+
+```sh
+$ rails generate validates_timeliness:install
+```
+
+This creates configuration initializer and locale files. In the initializer,
+there are a number of config options to customize the plugin.
+
+NOTE: You may wish to enable the plugin parser and the extensions to start.
+Please read those sections first.
+
+## Examples
+
+```ruby
+validates_datetime :occurred_at
+
+validates_date :date_of_birth, before: lambda { 18.years.ago },
+ before_message: "must be at least 18 years old"
+
+validates_datetime :finish_time, after: :start_time # Method symbol
+
+validates_date :booked_at, on: :create, on_or_after: :today # See Restriction Shorthand.
+
+validates_time :booked_at, between: ['9:00am', '5:00pm'] # On or after 9:00AM and on or before 5:00PM
+validates_time :booked_at, between: '9:00am'..'5:00pm' # The same as previous example
+validates_time :booked_at, between: '9:00am'...'5:00pm' # On or after 9:00AM and strictly before 5:00PM
+
+validates_time :breakfast_time, on_or_after: '6:00am',
+ on_or_after_message: 'must be after opening time',
+ before: :lunchtime,
+ before_message: 'must be before lunch time'
+```
+
+## Usage
+
+To validate a model with a date, time or datetime attribute you just use the
+validation method
+
+```ruby
+class Person < ActiveRecord::Base
+ validates_date :date_of_birth, on_or_before: lambda { Date.current }
+ # or
+ validates :date_of_birth, timeliness: { on_or_before: lambda { Date.current }, type: :date }
+end
+```
+
+or even on a specific record, per ActiveModel API.
+
+```ruby
+@person.validates_date :date_of_birth, on_or_before: lambda { Date.current }
+```
+
+The list of validation methods available are as follows:
+
+```
+validates_date - validate value as date
+validates_time - validate value as time only i.e. '12:20pm'
+validates_datetime - validate value as a full date and time
+validates - use the :timeliness key and set the type in the hash.
+```
+
+The validation methods take the usual options plus some specific ones to
+restrict the valid range of dates or times allowed
+
+Temporal options (or restrictions):
+
+```
+:is_at - Attribute must be equal to value to be valid
+:before - Attribute must be before this value to be valid
+:on_or_before - Attribute must be equal to or before this value to be valid
+:after - Attribute must be after this value to be valid
+:on_or_after - Attribute must be equal to or after this value to be valid
+:between - Attribute must be between the values to be valid. Range or Array of 2 values.
+```
+
+Regular validation options:
+
+```
+:allow_nil - Allow a nil value to be valid
+:allow_blank - Allows a nil or empty string value to be valid
+:if - Execute validation when :if evaluates true
+:unless - Execute validation when :unless evaluates false
+:on - Specify validation context e.g :save, :create or :update. Default is :save.
+```
+
+Special options:
+
+```
+:ignore_usec - Ignores microsecond value on datetime restrictions
+:format - Limit validation to a single format for special cases. Requires plugin parser.
+```
+
+The temporal restrictions can take 4 different value types:
+
+* Date, Time, or DateTime object value
+* Proc or lambda object which may take an optional parameter, being the
+ record object
+* A symbol matching a method name in the model
+* String value
+
+
+When an attribute value is compared to temporal restrictions, they are
+compared as the same type as the validation method type. So using
+validates_date means all values are compared as dates.
+
+## Configuration
+
+### ORM/ODM Support
+
+The plugin adds date/time validation to ActiveModel for any ORM/ODM that
+supports the ActiveModel validations component. However, there is an issue
+with most ORM/ODMs which does not allow 100% date/time validation by default.
+Specifically, when you assign an invalid date/time value to an attribute, most
+ORM/ODMs will only store a nil value for the attribute. This causes an issue
+for date/time validation, since we need to know that a value was assigned but
+was invalid. To fix this, we need to cache the original invalid value to know
+that the attribute is not just nil.
+
+Each ORM/ODM requires a specific shim to fix it. The plugin includes a shim
+for ActiveRecord and Mongoid. You can activate them like so
+
+```ruby
+ValidatesTimeliness.setup do |config|
+ # Extend ORM/ODMs for full support (:active_record).
+ config.extend_orms = [ :active_record ]
+end
+```
+
+By default the plugin extends ActiveRecord if loaded. If you wish to extend
+another ORM then look at the [wiki
+page](https://github.com/adzap/validates_timeliness/wiki/ORM-Support) for more
+information.
+
+It is not required that you use a shim, but you will not catch errors when the
+attribute value is invalid and evaluated to nil.
+
+### Error Messages
+
+Using the I18n system to define new defaults:
+
+```yaml
+en:
+ errors:
+ messages:
+ invalid_date: "is not a valid date"
+ invalid_time: "is not a valid time"
+ invalid_datetime: "is not a valid datetime"
+ is_at: "must be at %{restriction}"
+ before: "must be before %{restriction}"
+ on_or_before: "must be on or before %{restriction}"
+ after: "must be after %{restriction}"
+ on_or_after: "must be on or after %{restriction}"
+```
+
+The `%{restriction}` signifies where the interpolation value for the restriction
+will be inserted.
+
+You can also use validation options for custom error messages. The following
+option keys are available:
+
+```ruby
+:invalid_date_message
+:invalid_time_message
+:invalid_datetime_message
+:is_at_message
+:before_message
+:on_or_before_message
+:after_message
+:on_or_after_message
+```
+
+Note: There is no `:between_message` option. The between error message should be
+defined using the `:on_or_after` and `:on_or_before` (`:before` in case when
+`:between` argument is a Range with excluded high value, see Examples) messages.
+
+It is highly recommended you use the I18n system for error messages.
+
+### Plugin Parser
+
+The plugin uses the [timeliness gem](https://github.com/adzap/timeliness) as a
+fast, configurable and extensible date and time parser. You can add or remove
+valid formats for dates, times, and datetimes. It is also more strict than the
+Ruby parser, which means it won't accept day of the month if it's not a valid
+number for the month.
+
+By default the parser is disabled. To enable it:
+
+```ruby
+# in the setup block
+config.use_plugin_parser = true
+```
+
+Enabling the parser will mean that strings assigned to attributes validated
+with the plugin will be parsed using the gem. See the
+[wiki](https://github.com/adzap/validates_timeliness/wiki/Plugin-Parser) for
+more details about the parser configuration.
+
+### Restriction Shorthand
+
+It is common to restrict an attribute to being on or before the current time
+or current day. To specify this you need to use a lambda as an option value
+e.g. `lambda { Time.current }`. This can be tedious noise amongst your
+validations for something so common. To combat this the plugin allows you to
+use shorthand symbols for often used relative times or dates.
+
+Just provide the symbol as the option value like so:
+
+```ruby
+validates_date :birth_date, on_or_before: :today
+```
+
+The `:today` symbol is evaluated as `lambda { Date.current }`. The `:now` and
+`:today` symbols are pre-configured. Configure your own like so:
+
+```ruby
+# in the setup block
+config.restriction_shorthand_symbols.update(
+ yesterday: lambda { 1.day.ago }
+)
+```
+
+### Default Timezone
+
+The plugin needs to know the default timezone you are using when parsing or
+type casting values. If you are using ActiveRecord then the default is
+automatically set to the same default zone as ActiveRecord. If you are using
+another ORM you may need to change this setting.
+
+```ruby
+# in the setup block
+config.default_timezone = :utc
+```
+
+By default it will be UTC if ActiveRecord is not loaded.
+
+### Dummy Date For Time Types
+
+Given that Ruby has no support for a time-only type, all time type columns are
+evaluated as a regular Time class objects with a dummy date value set. Rails
+defines the dummy date as 2000-01-01. So a time of '12:30' is evaluated as a
+Time value of '2000-01-01 12:30'. If you need to customize this for some
+reason you can do so as follows
+
+```ruby
+# in the setup block
+config.dummy_date_for_time_type = [2009, 1, 1]
+```
+
+The value should be an array of 3 values being year, month and day in that
+order.
+
+### Temporal Restriction Errors
+
+When using the validation temporal restrictions there are times when the
+restriction option value itself may be invalid. This will add an error to the
+model such as 'Error occurred validating birth_date for :before restriction'.
+These can be annoying in development or production as you most likely just
+want to skip the option if no valid value was returned. By default these
+errors are displayed in Rails test mode.
+
+To turn them on/off:
+
+```ruby
+# in the setup block
+config.ignore_restriction_errors = true
+```
+
+## Extensions
+
+### Strict Parsing for Select Helpers
+
+When using date/time select helpers, the component values are handled by
+ActiveRecord using the Time class to instantiate them into a time value. This
+means that some invalid dates, such as 31st June, are shifted forward and
+treated as valid. To handle these cases in a strict way, you can enable the
+plugin extension to treat them as invalid dates.
+
+To activate it, uncomment this line in the initializer:
+
+```ruby
+# in the setup block
+config.enable_multiparameter_extension!
+```
+
+### Display Invalid Values in Select Helpers
+
+The plugin offers an extension for ActionView to allowing invalid date and
+time values to be redisplayed to the user as feedback, instead of a blank
+field which happens by default in Rails. Though the date helpers make this a
+pretty rare occurrence, given the select dropdowns for each date/time
+component, but it may be something of interest.
+
+To activate it, uncomment this line in the initializer:
+
+```ruby
+# in the setup block
+config.enable_date_time_select_extension!
+```
+
+## Contributors
+
+To see the generous people who have contributed code, take a look at the
+[contributors
+list](https://github.com/adzap/validates_timeliness/contributors).
+
+## Maintainers
+
+* [Adam Meehan](https://github.com/adzap)
+
+
+## License
+
+Copyright (c) 2008 Adam Meehan, released under the MIT license
diff --git a/README.rdoc b/README.rdoc
deleted file mode 100644
index 0c7e7f0..0000000
--- a/README.rdoc
+++ /dev/null
@@ -1,299 +0,0 @@
-= ValidatesTimeliness {
}[https://travis-ci.org/adzap/validates_timeliness]
-
-* Source: http://github.com/adzap/validates_timeliness
-* Issues: http://github.com/adzap/validates_timeliness/issues
-
-== Description
-
-Complete validation of dates, times and datetimes for Rails 5.x and ActiveModel.
-
-If you a looking for the old version for Rails 4.x go here [https://github.com/adzap/validates_timeliness/tree/4-0-stable].
-
-
-== Features
-
-* Adds validation for dates, times and datetimes to ActiveModel
-
-* Handles timezones and type casting of values for you
-
-* Only Rails date/time validation plugin offering complete validation (See ORM/ODM support)
-
-* Uses extensible date/time parser (Using {timeliness gem}[http://github.com/adzap/timeliness]. See Plugin Parser)
-
-* Adds extensions to fix Rails date/time select issues (See Extensions)
-
-* Supports I18n for the error messages. For multi-language support try {timeliness-i18n gem}[https://github.com/pedrofurtado/timeliness-i18n].
-
-* Supports all the Rubies (that any sane person would be using in production).
-
-
-== Installation
-
- # in Gemfile
- gem 'validates_timeliness', '~> 5.0.0.beta1'
-
- # Run bundler
- $ bundle install
-
-Then run
-
- $ rails generate validates_timeliness:install
-
-This creates configuration initializer and locale files. In the initializer, there are a number of config
-options to customize the plugin.
-
-NOTE: You may wish to enable the plugin parser and the extensions to start. Please read those sections first.
-
-
-== Examples
-
- validates_datetime :occurred_at
-
- validates_date :date_of_birth, before: lambda { 18.years.ago },
- before_message: "must be at least 18 years old"
-
- validates_datetime :finish_time, after: :start_time # Method symbol
-
- validates_date :booked_at, on: :create, on_or_after: :today # See Restriction Shorthand.
-
- validates_time :booked_at, between: ['9:00am', '5:00pm'] # On or after 9:00AM and on or before 5:00PM
- validates_time :booked_at, between: '9:00am'..'5:00pm' # The same as previous example
- validates_time :booked_at, between: '9:00am'...'5:00pm' # On or after 9:00AM and strictly before 5:00PM
-
- validates_time :breakfast_time, on_or_after: '6:00am',
- on_or_after_message: 'must be after opening time',
- before: :lunchtime,
- before_message: 'must be before lunch time'
-
-
-== Usage
-
-To validate a model with a date, time or datetime attribute you just use the
-validation method
-
- class Person < ActiveRecord::Base
- validates_date :date_of_birth, on_or_before: lambda { Date.current }
- # or
- validates :date_of_birth, timeliness: {on_or_before: lambda { Date.current }, type: :date}
- end
-
-or even on a specific record, per ActiveModel API.
-
- @person.validates_date :date_of_birth, on_or_before: lambda { Date.current }
-
-
-The list of validation methods available are as follows:
- validates_date - validate value as date
- validates_time - validate value as time only i.e. '12:20pm'
- validates_datetime - validate value as a full date and time
- validates - use the :timeliness key and set the type in the hash.
-
-The validation methods take the usual options plus some specific ones to restrict
-the valid range of dates or times allowed
-
-Temporal options (or restrictions):
- :is_at - Attribute must be equal to value to be valid
- :before - Attribute must be before this value to be valid
- :on_or_before - Attribute must be equal to or before this value to be valid
- :after - Attribute must be after this value to be valid
- :on_or_after - Attribute must be equal to or after this value to be valid
- :between - Attribute must be between the values to be valid. Range or Array of 2 values.
-
-Regular validation options:
- :allow_nil - Allow a nil value to be valid
- :allow_blank - Allows a nil or empty string value to be valid
- :if - Execute validation when :if evaluates true
- :unless - Execute validation when :unless evaluates false
- :on - Specify validation context e.g :save, :create or :update. Default is :save.
-
-Special options:
- :ignore_usec - Ignores microsecond value on datetime restrictions
- :format - Limit validation to a single format for special cases. Requires plugin parser.
-
-The temporal restrictions can take 4 different value types:
-
-* Date, Time, or DateTime object value
-* Proc or lambda object which may take an optional parameter, being the record object
-* A symbol matching a method name in the model
-* String value
-
-When an attribute value is compared to temporal restrictions, they are compared as
-the same type as the validation method type. So using validates_date means all
-values are compared as dates.
-
-
-== Configuration
-
-=== ORM/ODM Support
-
-The plugin adds date/time validation to ActiveModel for any ORM/ODM that supports the ActiveModel validations component.
-However, there is an issue with most ORM/ODMs which does not allow 100% date/time validation by default. Specifically, when you
-assign an invalid date/time value to an attribute, most ORM/ODMs will only store a nil value for the attribute. This causes an
-issue for date/time validation, since we need to know that a value was assigned but was invalid. To fix this, we need to cache
-the original invalid value to know that the attribute is not just nil.
-
-Each ORM/ODM requires a specific shim to fix it. The plugin includes a shim for ActiveRecord and Mongoid. You can activate them
-like so
-
- ValidatesTimeliness.setup do |config|
-
- # Extend ORM/ODMs for full support (:active_record).
- config.extend_orms = [ :active_record ]
-
- end
-
-By default the plugin extends ActiveRecord if loaded. If you wish to extend another ORM then look at the {wiki page}[http://github.com/adzap/validates_timeliness/wiki/ORM-Support] for more information.
-
-It is not required that you use a shim, but you will not catch errors when the attribute value is invalid and evaluated to nil.
-
-
-=== Error Messages
-
-Using the I18n system to define new defaults:
-
- en:
- errors:
- messages:
- invalid_date: "is not a valid date"
- invalid_time: "is not a valid time"
- invalid_datetime: "is not a valid datetime"
- is_at: "must be at %{restriction}"
- before: "must be before %{restriction}"
- on_or_before: "must be on or before %{restriction}"
- after: "must be after %{restriction}"
- on_or_after: "must be on or after %{restriction}"
-
-The %{restriction} signifies where the interpolation value for the restriction will be inserted.
-
-You can also use validation options for custom error messages. The following option keys are available:
-
- :invalid_date_message
- :invalid_time_message
- :invalid_datetime_message
- :is_at_message
- :before_message
- :on_or_before_message
- :after_message
- :on_or_after_message
-
-Note: There is no :between_message option. The between error message should be defined using the :on_or_after and :on_or_before
-(:before in case when :between argument is a Range with excluded high value, see Examples) messages.
-
-It is highly recommended you use the I18n system for error messages.
-
-
-=== Plugin Parser
-
-The plugin uses the {timeliness gem}[http://github.com/adzap/timeliness] as a fast, configurable and extensible date and time parser.
-You can add or remove valid formats for dates, times, and datetimes. It is also more strict than the
-Ruby parser, which means it won't accept day of the month if it's not a valid number for the month.
-
-By default the parser is disabled. To enable it:
-
- # in the setup block
- config.use_plugin_parser = true
-
-Enabling the parser will mean that strings assigned to attributes validated with the plugin will be parsed
-using the gem. See the wiki[http://github.com/adzap/validates_timeliness/wiki/Plugin-Parser] for more details about the parser configuration.
-
-
-=== Restriction Shorthand
-
-It is common to restrict an attribute to being on or before the current time or current day.
-To specify this you need to use a lambda as an option value e.g. lambda { Time.current }.
-This can be tedious noise amongst your validations for something so common. To combat this the
-plugin allows you to use shorthand symbols for often used relative times or dates.
-
-Just provide the symbol as the option value like so:
-
- validates_date :birth_date, on_or_before: :today
-
-The :today symbol is evaluated as lambda { Date.today }. The :now and :today
-symbols are pre-configured. Configure your own like so:
-
- # in the setup block
- config.restriction_shorthand_symbols.update(
- yesterday: lambda { 1.day.ago }
- )
-
-
-=== Default Timezone
-
-The plugin needs to know the default timezone you are using when parsing or type casting values. If you are using
-ActiveRecord then the default is automatically set to the same default zone as ActiveRecord. If you are using
-another ORM you may need to change this setting.
-
- # in the setup block
- config.default_timezone = :utc
-
-By default it will be UTC if ActiveRecord is not loaded.
-
-
-=== Dummy Date For Time Types
-
-Given that Ruby has no support for a time-only type, all time type columns are evaluated
-as a regular Time class objects with a dummy date value set. Rails defines the dummy date as
-2000-01-01. So a time of '12:30' is evaluated as a Time value of '2000-01-01 12:30'. If you
-need to customize this for some reason you can do so as follows
-
- # in the setup block
- config.dummy_date_for_time_type = [2009, 1, 1]
-
-The value should be an array of 3 values being year, month and day in that order.
-
-
-=== Temporal Restriction Errors
-
-When using the validation temporal restrictions there are times when the restriction
-option value itself may be invalid. This will add an error to the model such as
-'Error occurred validating birth_date for :before restriction'. These can be annoying
-in development or production as you most likely just want to skip the option if no
-valid value was returned. By default these errors are displayed in Rails test mode.
-
-To turn them on/off:
-
- # in the setup block
- config.ignore_restriction_errors = true
-
-
-== Extensions
-
-=== Strict Parsing for Select Helpers
-
-When using date/time select helpers, the component values are handled by ActiveRecord using
-the Time class to instantiate them into a time value. This means that some invalid dates,
-such as 31st June, are shifted forward and treated as valid. To handle these cases in a strict
-way, you can enable the plugin extension to treat them as invalid dates.
-
-To activate it, uncomment this line in the initializer:
-
- # in the setup block
- config.enable_multiparameter_extension!
-
-
-=== Display Invalid Values in Select Helpers
-
-The plugin offers an extension for ActionView to allowing invalid date and time values to be
-redisplayed to the user as feedback, instead of a blank field which happens by default in
-Rails. Though the date helpers make this a pretty rare occurrence, given the select dropdowns
-for each date/time component, but it may be something of interest.
-
-To activate it, uncomment this line in the initializer:
-
- # in the setup block
- config.enable_date_time_select_extension!
-
-
-== Contributors
-
-To see the generous people who have contributed code, take a look at the {contributors list}[http://github.com/adzap/validates_timeliness/contributors].
-
-
-== Maintainers
-
-* {Adam Meehan}[http://github.com/adzap]
-
-
-== License
-
-Copyright (c) 2008 Adam Meehan, released under the MIT license
diff --git a/Rakefile b/Rakefile
index 1ca3a14..0c2067a 100644
--- a/Rakefile
+++ b/Rakefile
@@ -19,10 +19,11 @@ end
desc 'Generate documentation for plugin.'
Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.main = 'README.md'
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'ValidatesTimeliness'
rdoc.options << '--line-numbers' << '--inline-source'
- rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('README.md')
rdoc.rdoc_files.include('lib/**/*.rb')
end
diff --git a/validates_timeliness.gemspec b/validates_timeliness.gemspec
index 7e4716c..182e573 100644
--- a/validates_timeliness.gemspec
+++ b/validates_timeliness.gemspec
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
s.require_paths = ["lib"]
s.files = `git ls-files`.split("\n") - %w{ .gitignore .rspec Gemfile Gemfile.lock autotest/discover.rb Appraisals Travis.yml } - Dir['gemsfiles/*']
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
- s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc", "LICENSE"]
+ s.extra_rdoc_files = ["README.md", "CHANGELOG.rdoc", "LICENSE"]
s.add_runtime_dependency(%q, [">= 0.3.10", "< 1"])
end