• Stars
    star
    521
  • Rank 84,952 (Top 2 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 15 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Better distance of time in words for Rails

dotiw Ruby

The dotiw library that adds distance_of_time_in_words to any Ruby project, or overrides the default implementation in Rails with more accurate output.

Do you crave accuracy down to the second? So do I. That's why I made this gem.

Install

Add to your Gemfile.

gem 'dotiw'

Run bundle install.

Pure Ruby

require 'dotiw'

include DOTIW::Methods

Rails

require 'dotiw'

include ActionView::Helpers::DateHelper
include ActionView::Helpers::TextHelper
include ActionView::Helpers::NumberHelper

distance_of_time_in_words

Take this for a totally kick-ass example:

>> distance_of_time_in_words(Time.now, Time.now + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds, true)
=> "1 year, 2 months, 3 weeks, 4 days, 5 hours, 6 minutes, and 7 seconds"

Also if one of the measurement is zero it will not output it:

>> distance_of_time_in_words(Time.now, Time.now + 1.year + 2.months + 5.hours + 6.minutes + 7.seconds, true)
=> "1 year, 2 months, 4 days, 6 minutes, and 7 seconds"

Better than "about 1 year", am I right? Of course I am.

"But Ryan!", you say, "What happens if the time is only in seconds but because of the default the seconds aren't shown? Won't it be blank?" "No!" I triumphantly reply:

>> distance_of_time_in_words(Time.now, Time.now + 1.second, false)
=> "1 second"

It also supports numeric arguments like the original Rails version:

>> distance_of_time_in_words(0, 150)
=> "2 minutes and 30 seconds"

as an alternative to:

>> distance_of_time_in_words(Time.now, Time.now + 2.5.minutes)
=> "2 minutes and 30 seconds"

This is useful if you're just interested in "stringifying" the length of time. Alternatively, you can use the #distance_of_time helper as described below.

The third argument for this method is whether or not to include seconds. By default this is false (because in Rails' distance_of_time_in_words it is), you can turn it on though by passing true as the third argument:

>> distance_of_time_in_words(Time.now, Time.now + 1.year + 1.second, true)
=> "1 year, and 1 second"

Yes this could just be merged into the options hash but I'm leaving it here to ensure "backwards-compatibility", because that's just an insanely radical thing to do. \m/

Alternatively this can be included in the options hash as include_seconds: true removing this argument altogether.

The last argument is an optional options hash that can be used to manipulate behavior and (which uses to_sentence).

Don't like having to pass in Time.now all the time? Then use time_ago_in_words or distance_of_time_in_words_to_now which also will rock your world:

>> time_ago_in_words(Time.now + 3.days + 1.second)
=> "3 days, and 1 second"

>> distance_of_time_in_words_to_now(Time.now + 3.days + 1.second)
=> "3 days, and 1 second"

Oh, and did I mention it supports I18n? Oh yeah. Rock on!

Options

:locale

You can pass in a locale and it'll output it in whatever language you want (provided you have translations, otherwise it'll default to your app's default locale (the config.i18n.default_locale you have set in /config/application.rb):

>> distance_of_time_in_words(Time.now, Time.now + 1.minute, false, locale: :es)
=> "1 minuto"

This will also be passed to to_sentence.

:vague

Specify this if you want it to use the old distance_of_time_in_words. The value can be anything except nil or false.

:include_seconds

As described above this option is the equivalent to the third argument whether to include seconds.

:accumulate_on

Specifies the maximum output unit which will accumulate all the surplus. Say you set it to seconds and your time difference is of 2 minutes then the output would be 120 seconds.

>> distance_of_time_in_words(Time.now, Time.now + 2.hours + 70.seconds, true, accumulate_on: :minutes)
=> "121 minutes and 10 seconds"

:only

Only want a specific measurement of time? No problem!

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.minute, false, only: :minutes)
=> "1 minute"

You only want some? No problem too!

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.day + 1.minute, false, only: [:minutes, :hours])
=> "1 hour and 1 minute"

:except

Don't want a measurement of time? No problem!

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.minute, false, except: :minutes)
=> "1 hour"

Culling a whole group of measurements of time:

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.day + 1.minute, false, except: [:minutes, :hours])
=> "1 day"

:highest_measure_only

Deprecated. Use highest_measures: 1 instead.

For times when Rails distance_of_time_in_words is not precise enough and DOTIW is too precise. For instance, if you only want to know the highest time part (measure) that elapsed between two dates.

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.minute + 1.second, true, highest_measure_only: true)
=> "1 hour"

Notice how minutes and seconds were removed from the output. Another example:

>> distance_of_time_in_words(Time.now, Time.now + 1.minute + 1.second, true, highest_measure_only: true)
=> "1 minute"

Minutes are the highest measure, so seconds were discarded from the output.

:highest_measures

When you want variable precision from DOTIW:

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.minute + 1.second, true, highest_measures: 2)
=> "1 hour and 1 minute"

You can also specify what to do with the extra time with the remainder option:

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.minute + 1.second, true, highest_measures: { max: 2, remainder: :ceiling })
=> "1 hour and 2 minutes"

Valid options for remainder are :floor (default), :ceiling and :round. Note that :round is best-effort and makes some simplifying assumptions:

# Only the next-largest unit is examined, which can unexpectedly round down in some situations.
>> distance_of_time_in_words(Time.now, Time.now + 1.week + 3.days + 23.hours, true, highest_measures: { remainder: :round })
=> "1 week"
# The variability of some measures (like months) is ignored and the shortest duration of that measure is used.
>> distance_of_time_in_words(Time.now, Time.now + 1.month + 14.days, true, highest_measures: { remainder: :round })
=> "2 months"

:words_connector

This is an option for to_sentence, defaults to ', '.

Using something other than a comma:

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.minute + 1.second, true, words_connector: ' - ')
=> "1 hour - 1 minute, and 1 second"

:two_words_connector

This is an option for to_sentence, defaults to ' and '.

Using something other than 'and':

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.minute, true, two_words_connector: ' plus ')
=> "1 hour plus 1 minute"

:last_word_connector

This is an option for to_sentence, defaults to ', and '.

Using something other than ', and':

>> distance_of_time_in_words(Time.now, Time.now + 1.hour + 1.minute + 1.second, true, last_word_connector: ', finally ')
=> "1 hour, 1 minute, finally 1 second"

distance_of_time

If you have simply a number of seconds you can get the "stringified" version of this by using distance_of_time:

>> distance_of_time(300)
=> "5 minutes"

distance_of_time_in_words_hash

Don't like any format you're given? That's cool too! Here, have an indifferent hash version:

>> distance_of_time_in_words_hash(Time.now, Time.now + 1.year + 2.months + 3.weeks + 4.days + 5.hours + 6.minutes + 7.seconds)
=> { days: 4, weeks: 3, seconds: 7, minutes: 6, years: 1, hours: 5, months: 2 }

Indifferent means that you can access all keys by their String or Symbol version.

distance_of_time_in_percent

This method is only available with Rails ActionView.

If you want to calculate a distance of time in percent, use distance_of_time_in_percent. The first argument is the beginning time, the second argument the "current" time and the third argument is the end time.

>> distance_of_time_in_percent("04-12-2009".to_time, "29-01-2010".to_time, "04-12-2010".to_time)
=> '15%'

This method takes the same options as number_with_precision.

>> distance_of_time_in_percent("04-12-2009".to_time, "29-01-2010".to_time, "04-12-2010".to_time, precision: 1)
=> '15.3%'

:compact

Pressed for space? Try compact: true.

>> distance_of_time_in_words(Time.now, Time.now + 2.year + 1.day + 1.second, compact: true)
=> "2y1d"

Pairs well with words_connector, last_word_connector, and two_words_connector if you can spare just a little more room:

>> distance_of_time_in_words(Time.now, Time.now + 5.years + 1.day + 23.seconds, words_connector: " ", last_word_connector: " ", two_words_connector: " ", compact: true)
=> "5y 1d 23s"

Contributors

  • chendo - for talking through it with me and drawing on the whiteboard
  • Derander - correct Spanish translations
  • DBA - commits leading up to the 0.7 release
  • Sija - rails 4 support, v2.0 release
  • dblock - Ruby w/o Rails support

More Repositories

1

guides

Guides for Ruby and Elixir and whatever else I feel like
Ruby
1,528
star
2

by_star

Lets you find ActiveRecord + Mongoid objects by year, month, fortnight, week and more!
Ruby
1,045
star
3

humanize

Takes your numbers and makes them *fancy*.
Ruby
466
star
4

rboard

A fully featured forum system compatible with Rails 2.3
Ruby
293
star
5

joyofelixir

A gentle introduction to the Elixir programming language
HTML
139
star
6

twist-v2

A book review tool for Leanpub's Markdown Book Format
Ruby
127
star
7

twist

Book review application for LeanPub's Markdown format
Ruby
103
star
8

elastic

A thin veneer over HTTPotion that talks to Elastic Search
Elixir
65
star
9

mtg

Magic: The Gathering, but in Ruby
Ruby
63
star
10

railsbot

The #rubyonrails channel bot
PLSQL
47
star
11

summer

A Tiny IRC Bot framework
Ruby
43
star
12

houser

Lightweight multitenancy gem for Rails 3 and Rails 4
Ruby
32
star
13

chronic

Elixir
30
star
14

saas_book_examples

Ruby
27
star
15

searcher

Fun experiment in parsing search query strings (like Pivotal Tracker does)
Ruby
25
star
16

forem.heroku.com

The application that contains the forem engine example
Ruby
22
star
17

lookup

Lookup for Ruby & Rails api in the terminal
Ruby
20
star
18

surveyor-2

Culture Amp Junior Engineering Program - 2018 Coding Test
Ruby
19
star
19

ryanbigg.com

Jekyll-powered version of ryanbigg.com
HTML
18
star
20

elixir-irc

Naive implementation of an IRC server in Elixir
Elixir
17
star
21

postbin

Postbin written in Sinatra
Ruby
16
star
22

ordinalize

Ordinalize your numbers (like humanize)
Ruby
15
star
23

chirper

Ruby
15
star
24

toy_robot_elixir

Code from leanpub.com/elixir-toyrobot
Elixir
13
star
25

writing-an-interpreter-in-elixir

Elixir
12
star
26

asciidoc-toolchain

Ruby
11
star
27

bix

Ruby
11
star
28

screencasts

Code for the screencasts I record
Ruby
10
star
29

forem-redcarpet

Provides Recarpet markup (with syntax highlighting by pygments.rb) for Forem posts}
Ruby
8
star
30

logs

JavaScript
7
star
31

maintaining-rails-examples

Ruby
6
star
32

exploding-rails-rom-dry-example-app

Ruby
6
star
33

setup

Go
6
star
34

exploding-rails-examples

Ruby
6
star
35

fans

Simple application showing how to do models for user's "favouriting" other users.
Ruby
5
star
36

graphql_book_examples

The code from the book "GraphQL for Rails Developers"
Ruby
5
star
37

jot

A light wrapper around the JWT gem
Ruby
5
star
38

banana

A warden example app
Ruby
4
star
39

find_by_hash

Extension to ActiveRecord to allow you to do findy-thingies with hashes
Ruby
4
star
40

logs.ex

Phoenix application for displaying IRC logs from some select channels
Elixir
4
star
41

numero

Numero language
Ruby
4
star
42

surveyor

Culture Amp's Junior Engineering Program - 2017 Coding Test
Ruby
4
star
43

phoenix-react-websocket-todo

Elixir
3
star
44

debugging_book_examples

Debugging Book Example Code
Ruby
3
star
45

phoenix-views-example

Elixir
3
star
46

cartify

REST / GraphQL demo
Ruby
3
star
47

rails-init

Go
3
star
48

wedding

App for managing wedding seating plan
Ruby
3
star
49

forem-rdiscount

RDiscount formatting support for Forem
Ruby
3
star
50

logs.ex-legacy

The old logs.ex.
JavaScript
3
star
51

promo

Toy project of building a promotion system in Elixir
Elixir
2
star
52

service-vic-qr-code

TypeScript
2
star
53

scrivener_elastic

Elixir
2
star
54

rubyonrailsbook.com

JavaScript
2
star
55

activitypub-spike

Ruby
2
star
56

epub_gen

A small RubyGem to generate epubs
Ruby
2
star
57

rails3book_test

Nothing to see here, move along.
2
star
58

just

For when you're just visiting (someone else's computer)
Ruby
2
star
59

logs-react

JavaScript
1
star
60

buildkite-notifier

Ruby
1
star
61

surveyor-rom

Ruby
1
star
62

http-test

Ruby
1
star
63

trickery

Ruby
1
star
64

yaml-path-finder

CSS
1
star
65

barefoot

JavaScript
1
star
66

webpacker-typescript-css-modules

Ruby
1
star
67

selector

Ruby
1
star
68

jep-mumble

Ruby
1
star
69

toy_robot_example

Ruby
1
star
70

jep-toy-robot

Elixir
1
star
71

rails-init-homebrew-tap

Ruby
1
star
72

sri

A tool to generate Sub-Resource Integrity hashes from the terminal
Ruby
1
star
73

auth_me

Ruby
1
star
74

webpack-example

Ruby
1
star