# ValidatesTimeliness: Date and Time Validation for Rails and ActiveModel

> ValidatesTimeliness adds complete date, time and datetime validation to ActiveModel and Rails 8, with timezone handling, range restrictions and I18n messages. It suits Rails applications that need stricter checks than the built-in validators, but it requires a shim for full ORM support.

**adzap/validates_timeliness** — Date and time validation plugin for ActiveModel and Rails.  Supports multiple ORMs and allows custom date/time formats.

- Repository: https://github.com/adzap/validates_timeliness
- Stars: 1,615 · Forks: 235
- Language: Ruby
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/adzap-validates-timeliness

## What ValidatesTimeliness validates and who it targets

ValidatesTimeliness is a Ruby gem that adds complete validation of dates, times and datetimes to ActiveModel and Rails 8. It handles timezones and type casting of values for you, and the README describes it as the only Rails date and time validation plugin offering complete validation. It targets Rails developers who need more than presence checks on date and time attributes, including range restrictions and custom error messages. The gem uses the timeliness gem as an extensible parser, supports I18n error messages with an optional timeliness-i18n gem for multi-language support, and adds extensions to fix Rails date and time select issues. It also supports older Rails versions on separate branches: 4.x, 5.x, 6.x and 7.x.

## How validation and temporal restrictions work

The core mechanism is a set of validation methods: validates_date, validates_time, validates_datetime and validates with a:timeliness key and a type. Temporal restrictions compare the attribute value against a value of the same type as the validation method. The available restrictions are:is_at,:before,:on_or_before,:after,:on_or_after and:between. Regular options include:allow_nil,:allow_blank,:if,:unless and:on. Special options are:ignore_usec and:format, the latter requiring the plugin parser. A restriction value can be a Date, Time or DateTime object, a Proc or lambda that may take the record as a parameter, a symbol matching a method name in the model, or a string. The README notes that when using validates_date all values are compared as dates.

## Installing ValidatesTimeliness and generating config

Installation starts in the Gemfile.

```ruby
gem 'validates_timeliness', '~> 8.0.0.beta1'
```

Then run bundler.

```bash
$ bundle install
```

Then generate the initializer and locale files.

```bash
$ rails generate validates_timeliness:install
```

The generator creates a configuration initializer with options to customize the plugin, plus locale files. The README suggests enabling the plugin parser and the extensions first, so read those sections before flipping options. A model validation looks like this.

```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
```

Validation can also be declared on a specific record through the ActiveModel API.

## ORM shims and the nil-value problem

The plugin adds date and time validation to ActiveModel for any ORM or ODM that supports the ActiveModel validations component. Most ORMs have a limitation: when an invalid date or time value is assigned to an attribute, they store nil instead. That erases the evidence that a value was present but invalid, so the validation cannot catch the error. ValidatesTimeliness fixes this with a shim per ORM. Shims exist for ActiveRecord and Mongoid, and ActiveRecord is extended by default when loaded. Activation looks like this.

```ruby
ValidatesTimeliness.setup do |config|
  # Extend ORM/ODMs for full support (:active_record).
  config.extend_orms = [ :active_record ]
end
```

Using a shim is optional, but without one invalid values that evaluate to nil will not be caught. Other ORMs require a custom shim, and the README points to a wiki page for details. This is the central trade-off of the gem: complete validation depends on ORM cooperation.

## Parser, timezone and error message configuration

The:format option requires the plugin parser. Error messages use I18n, with keys such as invalid_date, invalid_time, invalid_datetime, is_at, before and on_or_before, where %{restriction} is interpolated. Custom message keys like:before_message are also supported.

## Extensions for Rails date and time selects

The README says the gem adds extensions to fix Rails date and time select issues and advises reading that section before enabling them.

## ValidatesTimeliness versus built-in Rails validations

The alternative is Rails' own date and time validation or a custom validator. Rails built-ins do not offer complete validation of the parsed value and do not handle temporal range restrictions with timezones and type casting in the same way. ValidatesTimeliness adds those capabilities, but at the cost of a gem dependency, a parser to configure and ORM-specific shims. If your needs are limited to presence and format checks, the built-in validators are simpler. If you need range checks, I18n messages and strict parsing, ValidatesTimeliness is the more complete option, provided your ORM has a shim.

## Maintenance, licensing and upgrade cost

The last push to the default master branch was on 2026-10-03. There are no GitHub releases, so versioning relies on gem versions and branches, with Rails 8 on master and older Rails versions on 4-0-stable through 7-0-stable branches. The license is MIT. The gem depends on the timeliness gem for parsing, plus Rails and ActiveModel. Upgrade cost is tied to Rails major versions, since each supported Rails line has its own branch. Consumers should track the branch that matches their Rails version and read the changelog before upgrading.

## Conclusion

Adopt ValidatesTimeliness if you need complete date, time or datetime validation in a Rails 8 or ActiveModel project, especially with range restrictions and I18n messages. Skip it if you only need simple presence checks, because the plugin parser and ORM shims add configuration surface you may not need. Verify first that your ORM is supported by a shim, or accept that invalid values cast to nil will not be caught.

## FAQ

### What is ValidatesTimeliness?

ValidatesTimeliness is a Ruby gem that adds complete validation of dates, times and datetimes to ActiveModel and Rails 8. It handles timezones and type casting and uses the timeliness gem as a parser.

### How do I install ValidatesTimeliness?

Add gem 'validates_timeliness', '~> 8.0.0.beta1' to the Gemfile, run bundle install, then run rails generate validates_timeliness:install to create the initializer and locale files.

### Why are invalid date values not caught by ValidatesTimeliness?

Most ORMs store nil when an invalid date or time is assigned, which hides the invalid value. A shim such as the ActiveRecord shim is needed to cache the original value; without one, invalid values that evaluate to nil are not caught.

## Sources

- [adzap/validates_timeliness on GitHub](https://github.com/adzap/validates_timeliness)
- [Issues](https://github.com/adzap/validates_timeliness/issues)
- [License: MIT](https://github.com/adzap/validates_timeliness/blob/master/LICENSE)
- [README](https://github.com/adzap/validates_timeliness/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/adzap-validates-timeliness
