Module: Merb::Helpers::DateAndTime

Included in:
Controller
Defined in:
lib/merb_helpers/date_time_helpers.rb

Overview

Provides a number of methods for displaying and dealing with dates and times

Parts were strongly based on ar-code.svn.engineyard.com/plugins/relative_time_helpers/, and active_support

The key methods are ‘relative_date`, `relative_date_span`, and `relative_time_span`. This also gives you the Rails style Time DSL for working with numbers eg. 3.months.ago or 5.days.until(1.year.from_now)

Constant Summary collapse

@@time_class =
Time
@@time_output =
{
  :today          => 'today',
  :yesterday      => 'yesterday',
  :tomorrow       => 'tomorrow',
  :initial_format => '%b %d',
  :year_format    => ', %Y'
}
@@date_formats =
{
  :db           => "%Y-%m-%d %H:%M:%S",
  :time         => "%H:%M",
  :short        => "%d %b %H:%M",
  :long         => "%B %d, %Y %H:%M",
  :long_ordinal => lambda { |time| time.strftime("%B #{time.day.ordinalize}, %Y %H:%M") },
  :rfc822       => "%a, %d %b %Y %H:%M:%S %z"
}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.date_formatsObject



42
43
44
# File 'lib/merb_helpers/date_time_helpers.rb', line 42

def self.date_formats
  @@date_formats
end

.time_classObject



28
29
30
# File 'lib/merb_helpers/date_time_helpers.rb', line 28

def self.time_class
  @@time_class
end

.time_output(format, locale = nil) ⇒ Object

Parameters

format<Symbol>

time format to use

locale<String, Symbol>

An optional value which can be used by localization plugins

Returns

String

a string used to format time using #strftime



38
39
40
# File 'lib/merb_helpers/date_time_helpers.rb', line 38

def self.time_output(format, locale=nil)
  @@time_output[format]
end

Instance Method Details

#prettier_time(time, ampm = true, locale = nil) ⇒ Object



192
193
194
# File 'lib/merb_helpers/date_time_helpers.rb', line 192

def prettier_time(time, ampm=true, locale=nil)
  time.strftime("%I:%M#{" %p" if ampm}").sub(/^0/, '')
end

#relative_date(time, locale = nil) ⇒ Object

Gives you a relative date in an attractive format

Parameters

time<~to_date>

The Date or Time to test

locale<String, Symbol>

An optional value which can be used by localization plugins

Returns

String

Relative date

Examples

relative_date(Time.now.utc) => "today"
relative_date(5.days.ago) => "March 5th"
relative_date(1.year.ago) => "March 10th, 2007"


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/merb_helpers/date_time_helpers.rb', line 59

def relative_date(time, locale=nil)
  date  = time.to_date
  today = DateAndTime.time_class.now.to_date
  if date == today
    DateAndTime.time_output(:today, locale)
  elsif date == (today - 1)
    DateAndTime.time_output(:yesterday, locale)
  elsif date == (today + 1)
    DateAndTime.time_output(:tomorrow, locale)
  else
    fmt  = DateAndTime.time_output(:initial_format, locale).dup
    fmt << DateAndTime.time_output(:year_format, locale) unless date.year == today.year
    time.strftime_ordinalized(fmt, locale)
  end
end

#relative_date_span(times) ⇒ Object

Gives you a relative date span in an attractive format

Parameters

times<~first,~last>

The Dates or Times to test

Returns

String

The sexy relative date span

Examples

relative_date([1.second.ago, 10.seconds.ago]) => "March 10th"
relative_date([1.year.ago, 1.year.ago) => "March 10th, 2007"
relative_date([Time.now, 1.day.from_now]) => "March 10th - 11th"
relative_date([Time.now, 1.year.ago]) => "March 10th, 2007 - March 10th, 2008"


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/merb_helpers/date_time_helpers.rb', line 88

def relative_date_span(times)
  times = [times.first, times.last].collect! { |t| t.to_date }
  times.sort!
  if times.first == times.last
    relative_date(times.first)
  else
    first = times.first; last = times.last; now = DateAndTime.time_class.now
    arr = [first.strftime_ordinalized('%b %d')]
    arr << ", #{first.year}" unless first.year == last.year
    arr << ' - '
    arr << last.strftime('%b') << ' ' unless first.year == last.year && first.month == last.month
    arr << last.day.ordinalize
    arr << ", #{last.year}" unless first.year == last.year && last.year == now.year
    arr.to_s
  end
end

#relative_time_span(times) ⇒ Object

Gives you a relative date span in an attractive format

Parameters

times<~first,~last>

The Dates or Times to test

Returns

String

The sexy relative time span

Examples

relative_time_span([1.second.ago, 10.seconds.ago]) => "12:00 - 12:09 AM March 10th"
relative_time_span([1.year.ago, 1.year.ago) => "12:09 AM March 10th, 2007"
relative_time_span([Time.now, 13.hours.from_now]) => "12:09 AM - 1:09 PM March 10th"
relative_time_span([Time.now, 1.year.ago]) => "12:09 AM March 10th, 2007 - 12:09 AM March 10th, 2008"


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/merb_helpers/date_time_helpers.rb', line 118

def relative_time_span(times)
  times = [times.first, times.last].collect! { |t| t.to_time }
  times.sort!
  if times.first == times.last
    "#{prettier_time(times.first)} #{relative_date(times.first)}"
  elsif times.first.to_date == times.last.to_date
      same_half = (times.first.hour/12 == times.last.hour/12)
      "#{prettier_time(times.first, !same_half)} - #{prettier_time(times.last)} #{relative_date(times.first)}"

  else
    first = times.first; last = times.last; now = DateAndTime.time_class.now        
    arr = [prettier_time(first)]
    arr << ' '
    arr << first.strftime_ordinalized('%b %d')
    arr << ", #{first.year}" unless first.year == last.year
    arr << ' - '
    arr << prettier_time(last)
    arr << ' '
    arr << last.strftime('%b') << ' ' unless first.year == last.year && first.month == last.month
    arr << last.day.ordinalize
    arr << ", #{last.year}" unless first.year == last.year && last.year == now.year
    arr.to_s
  end
end

#time_lost_in_words(from_time, to_time = Time.now.utc, include_seconds = false, locale = nil) ⇒ Object Also known as: time_ago_in_words

Condenses time… very similar to time_ago_in_words in ActionPack

Parameters

from_time<~to_time>

The Date or Time to start from

to_time<~to_time>

The Date or Time to go to, Defaults to Time.now.utc

include_seconds<Boolean>

Count the seconds initially, Defaults to false

locale<String, Symbol>

An optional value which can be used by localization plugins

Returns

String

The time distance

Examples

time_lost_in_words(3.minutes.from_now) # => 3 minutes time_lost_in_words(Time.now - 15.hours) # => 15 hours time_lost_in_words(Time.now, 3.minutes.from_now) # => 3 minutes time_lost_in_words(Time.now) # => less than a minute time_lost_in_words(Time.now, Time.now, true) # => less than 5 seconds



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/merb_helpers/date_time_helpers.rb', line 161

def time_lost_in_words(from_time, to_time = Time.now.utc, include_seconds = false, locale=nil)
  from_time = from_time.to_time if from_time.respond_to?(:to_time)
  to_time = to_time.to_time if to_time.respond_to?(:to_time)
  distance_in_minutes = (((to_time - from_time).abs)/60).round
  distance_in_seconds = ((to_time - from_time).abs).round

  case distance_in_minutes
    when 0..1
      return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
      case distance_in_seconds
        when 0..4   then 'less than 5 seconds'
        when 5..9   then 'less than 10 seconds'
        when 10..19 then 'less than 20 seconds'
        when 20..39 then 'half a minute'
        when 40..59 then 'less than a minute'
        else             '1 minute'
      end

    when 2..44           then "#{distance_in_minutes} minutes"
    when 45..89          then 'about 1 hour'
    when 90..1439        then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
    when 1440..2879      then '1 day'
    when 2880..43199     then "#{(distance_in_minutes / 1440).round} days"
    when 43200..86399    then 'about 1 month'
    when 86400..525599   then "#{(distance_in_minutes / 43200).round} months"
    when 525600..1051199 then 'about 1 year'
    else                      "over #{(distance_in_minutes / 525600).round} years"
  end
end