kelredd-useful 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/useful/ruby_extensions/date.rb +18 -0
- data/lib/useful/ruby_extensions/false_class.rb +19 -0
- data/lib/useful/ruby_extensions/fixnum.rb +1 -1
- data/lib/useful/ruby_extensions/hash.rb +5 -36
- data/lib/useful/ruby_extensions/numeric.rb +5 -4
- data/lib/useful/ruby_extensions/object.rb +0 -4
- data/lib/useful/ruby_extensions/string.rb +0 -4
- data/lib/useful/ruby_extensions/true_class.rb +19 -0
- data/lib/useful/ruby_extensions.rb +3 -7
- data/lib/useful/ruby_extensions_from_rails/date.rb +244 -0
- data/lib/useful/ruby_extensions_from_rails/duration.rb +99 -0
- data/lib/useful/ruby_extensions_from_rails/fixnum.rb +32 -0
- data/lib/useful/ruby_extensions_from_rails/hash.rb +50 -0
- data/lib/useful/ruby_extensions_from_rails/numeric.rb +60 -0
- data/lib/useful/ruby_extensions_from_rails/object.rb +79 -0
- data/lib/useful/ruby_extensions_from_rails/string.rb +166 -0
- data/lib/useful/ruby_extensions_from_rails/time.rb +320 -0
- data/lib/useful/ruby_extensions_from_rails.rb +3 -0
- data/lib/useful/sinatra_helpers.rb +3 -4
- data/lib/useful/version.rb +1 -1
- metadata +15 -2
@@ -0,0 +1,18 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensions
|
3
|
+
module Date
|
4
|
+
|
5
|
+
def week_days_until(end_date)
|
6
|
+
week_days = (1..5)
|
7
|
+
raise ::ArgumentError, "End date cannot be nil." if end_date.nil?
|
8
|
+
raise ::ArgumentError, "End date cannot come before questioned date." if end_date < self
|
9
|
+
(self..end_date).to_a.select{|date| week_days.include?(date.wday)}.length
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Date
|
17
|
+
include Useful::RubyExtensions::Date
|
18
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
|
3
1
|
module Useful
|
4
2
|
module RubyExtensions
|
5
3
|
module Hash
|
@@ -11,18 +9,6 @@ module Useful
|
|
11
9
|
|
12
10
|
module ClassMethods
|
13
11
|
|
14
|
-
# inspired by ActiveSupport::CoreExtensions::Hash::Keys (http://api.rubyonrails.org/)
|
15
|
-
def stringify_keys(hash)
|
16
|
-
hash.keys.each{ |key| hash[(key.to_s rescue key)] ||= hash.delete(key) }
|
17
|
-
hash
|
18
|
-
end
|
19
|
-
|
20
|
-
# inspired by from ActiveSupport::CoreExtensions::Hash::Keys (http://api.rubyonrails.org/)
|
21
|
-
def symbolize_keys(hash)
|
22
|
-
hash.keys.each{ |key| hash[(key.to_sym rescue key)] ||= hash.delete(key) }
|
23
|
-
hash
|
24
|
-
end
|
25
|
-
|
26
12
|
def only(hash, *keys)
|
27
13
|
hash.delete_if{ |k,v| !keys.flatten.include?(k) }
|
28
14
|
hash
|
@@ -35,24 +21,6 @@ module Useful
|
|
35
21
|
|
36
22
|
end
|
37
23
|
|
38
|
-
# Return a new hash with all keys converted to strings.
|
39
|
-
def stringify_keys
|
40
|
-
self.class.stringify_keys(self.clone)
|
41
|
-
end
|
42
|
-
# Destructively convert all keys to strings.
|
43
|
-
def stringify_keys!
|
44
|
-
self.class.stringify_keys(self)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Return a new hash with all keys converted to strings.
|
48
|
-
def symbolize_keys
|
49
|
-
self.class.symbolize_keys(self.clone)
|
50
|
-
end
|
51
|
-
# Destructively convert all keys to strings.
|
52
|
-
def symbolize_keys!
|
53
|
-
self.class.symbolize_keys(self)
|
54
|
-
end
|
55
|
-
|
56
24
|
# Return a new hash with only keys in *keys
|
57
25
|
def only(*keys)
|
58
26
|
self.class.only(self.clone, keys)
|
@@ -87,11 +55,12 @@ module Useful
|
|
87
55
|
|
88
56
|
# Returns string formatted for HTTP URL encoded name-value pairs.
|
89
57
|
# For example,
|
90
|
-
# {:id => 'thomas_hardy'}.
|
91
|
-
# # => "id=thomas_hardy"
|
92
|
-
# {:id => 23423, :since => Time.now}.
|
93
|
-
# # => "since=Thu,%2021%20Jun%202007%2012:10:05%20-0500&id=23423"
|
58
|
+
# {:id => 'thomas_hardy'}.to_http_query_str
|
59
|
+
# # => "?id=thomas_hardy"
|
60
|
+
# {:id => 23423, :since => Time.now}.to_http_query_str
|
61
|
+
# # => "?since=Thu,%2021%20Jun%202007%2012:10:05%20-0500&id=23423"
|
94
62
|
def to_http_query_str(opts = {})
|
63
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
95
64
|
opts[:prepend] ||= '?'
|
96
65
|
opts[:append] ||= ''
|
97
66
|
self.empty? ? '' : "#{opts[:prepend]}#{self.collect{|key, val| "#{key.to_s}=#{CGI.escape(val.to_s)}"}.join('&')}#{opts[:append]}"
|
@@ -1,10 +1,10 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'object')
|
2
|
-
require File.join(File.dirname(__FILE__), '
|
3
|
-
require File.join(File.dirname(__FILE__), '
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'ruby_extensions_from_rails', 'object') unless Object.new.respond_to?(:blank?)
|
2
|
+
require File.join(File.dirname(__FILE__), '..', 'ruby_extensions_from_rails', 'hash') unless Hash.new.respond_to?(:symbolize_keys!)
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'ruby_extensions_from_rails', 'string') unless String.new.respond_to?(:starts_with?)
|
4
4
|
|
5
5
|
module Useful
|
6
6
|
module RubyExtensions
|
7
|
-
module Numeric
|
7
|
+
module Numeric
|
8
8
|
|
9
9
|
LOCALES = {
|
10
10
|
:en => {
|
@@ -144,6 +144,7 @@ module Useful
|
|
144
144
|
# 1234567890.50.to_currency(:unit => "£", :separator => ",", :delimiter => "", :format => "%n %u")
|
145
145
|
# # => 1234567890,50 £
|
146
146
|
def to_currency(opts = {})
|
147
|
+
return opts[:zero_display] if opts[:zero_display] && self == 0
|
147
148
|
opts.symbolize_keys!
|
148
149
|
opts[:locale] ||= :en
|
149
150
|
locale = LOCALES[opts.delete(:locale)]
|
@@ -1,7 +1,3 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
4
|
-
require 'ruby_extensions/string'
|
5
|
-
require 'ruby_extensions/fixnum'
|
6
|
-
require 'ruby_extensions/numeric'
|
7
|
-
require 'ruby_extensions/object'
|
1
|
+
Dir[File.join(File.dirname(__FILE__), "ruby_extensions" ,"*.rb")].each do |file|
|
2
|
+
require file
|
3
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'object') unless Object.new.respond_to?(:acts_like?)
|
2
|
+
require File.join(File.dirname(__FILE__), 'duration')
|
3
|
+
|
4
|
+
module Useful
|
5
|
+
module RubyExtensionsFromRails
|
6
|
+
module Date
|
7
|
+
|
8
|
+
DATE_FORMATS = {
|
9
|
+
:short => "%e %b",
|
10
|
+
:long => "%B %e, %Y",
|
11
|
+
:db => "%Y-%m-%d",
|
12
|
+
:number => "%Y%m%d",
|
13
|
+
:long_ordinal => lambda { |date| date.strftime("%B #{date.day.ordinalize}, %Y") }, # => "April 25th, 2007"
|
14
|
+
:rfc822 => "%e %b %Y"
|
15
|
+
}
|
16
|
+
|
17
|
+
module ClassMethods; end
|
18
|
+
def self.included(klass)
|
19
|
+
klass.extend(ClassMethods) if klass.kind_of?(Class)
|
20
|
+
|
21
|
+
klass.instance_eval do
|
22
|
+
alias_method :to_default_s, :to_s
|
23
|
+
alias_method :to_s, :to_formatted_s
|
24
|
+
alias_method :default_inspect, :inspect
|
25
|
+
alias_method :inspect, :readable_inspect
|
26
|
+
|
27
|
+
# Ruby 1.9 has Date#to_time which converts to localtime only.
|
28
|
+
remove_method :to_time if klass.instance_methods.include?(:to_time)
|
29
|
+
|
30
|
+
# Ruby 1.9 has Date#xmlschema which converts to a string without the time component.
|
31
|
+
remove_method :xmlschema if klass.instance_methods.include?(:xmlschema)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
|
37
|
+
# Returns a new Date representing the date 1 day ago (i.e. yesterday's date).
|
38
|
+
def yesterday
|
39
|
+
::Date.today.yesterday
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a new Date representing the date 1 day after today (i.e. tomorrow's date).
|
43
|
+
def tomorrow
|
44
|
+
::Date.today.tomorrow
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns Date.today.
|
48
|
+
def current
|
49
|
+
::Date.today
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
# Enable more predictable duck-typing on Date-like classes. See
|
55
|
+
# Object#acts_like?.
|
56
|
+
def acts_like_date?
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
# Tells whether the Date object's date lies in the past
|
61
|
+
def past?
|
62
|
+
self < ::Date.current
|
63
|
+
end
|
64
|
+
|
65
|
+
# Tells whether the Date object's date is today
|
66
|
+
def today?
|
67
|
+
self.to_date == ::Date.current # we need the to_date because of DateTime
|
68
|
+
end
|
69
|
+
|
70
|
+
# Tells whether the Date object's date lies in the future
|
71
|
+
def future?
|
72
|
+
self > ::Date.current
|
73
|
+
end
|
74
|
+
|
75
|
+
# Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
|
76
|
+
# any of these keys: <tt>:years</tt>, <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>.
|
77
|
+
def advance(options)
|
78
|
+
d = self
|
79
|
+
d = d >> options.delete(:years) * 12 if options[:years]
|
80
|
+
d = d >> options.delete(:months) if options[:months]
|
81
|
+
d = d + options.delete(:weeks) * 7 if options[:weeks]
|
82
|
+
d = d + options.delete(:days) if options[:days]
|
83
|
+
d
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns a new Date where one or more of the elements have been changed according to the +options+ parameter.
|
87
|
+
#
|
88
|
+
# Examples:
|
89
|
+
#
|
90
|
+
# Date.new(2007, 5, 12).change(:day => 1) # => Date.new(2007, 5, 1)
|
91
|
+
# Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12)
|
92
|
+
def change(options)
|
93
|
+
::Date.new(
|
94
|
+
options[:year] || self.year,
|
95
|
+
options[:month] || self.month,
|
96
|
+
options[:day] || self.day
|
97
|
+
)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
|
101
|
+
def beginning_of_day
|
102
|
+
to_time
|
103
|
+
end
|
104
|
+
alias :midnight :beginning_of_day
|
105
|
+
alias :at_midnight :beginning_of_day
|
106
|
+
alias :at_beginning_of_day :beginning_of_day
|
107
|
+
|
108
|
+
# Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59)
|
109
|
+
def end_of_day
|
110
|
+
to_time.end_of_day
|
111
|
+
end
|
112
|
+
alias :at_end_of_day :end_of_day
|
113
|
+
|
114
|
+
# Returns a new Date representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
|
115
|
+
def beginning_of_week
|
116
|
+
days_to_monday = self.wday!=0 ? self.wday-1 : 6
|
117
|
+
self - days_to_monday
|
118
|
+
end
|
119
|
+
alias :monday :beginning_of_week
|
120
|
+
alias :at_beginning_of_week :beginning_of_week
|
121
|
+
|
122
|
+
# Returns a new Date representing the end of this week (Sunday, DateTime objects will have time set to 23:59:59)
|
123
|
+
def end_of_week
|
124
|
+
days_to_sunday = self.wday!=0 ? 7-self.wday : 0
|
125
|
+
self + days_to_sunday.days
|
126
|
+
end
|
127
|
+
alias :at_end_of_week :end_of_week
|
128
|
+
|
129
|
+
# Returns a new Date representing the start of the given day in next week (default is Monday).
|
130
|
+
def next_week(day = :monday)
|
131
|
+
days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
|
132
|
+
(self + 7).beginning_of_week + days_into_week[day]
|
133
|
+
end
|
134
|
+
|
135
|
+
# Returns a new Date representing the start of the month (1st of the month)
|
136
|
+
def beginning_of_month
|
137
|
+
change(:day => 1)
|
138
|
+
end
|
139
|
+
alias :at_beginning_of_month :beginning_of_month
|
140
|
+
|
141
|
+
# Returns a new Date representing the end of the month (last day of the month)
|
142
|
+
def end_of_month
|
143
|
+
change(:day => ::Time.days_in_month( self.month, self.year ))
|
144
|
+
end
|
145
|
+
alias :at_end_of_month :end_of_month
|
146
|
+
|
147
|
+
# Returns a new Date/DateTime representing the start of the quarter (1st of january, april, july, october; DateTime objects will have time set to 0:00)
|
148
|
+
def beginning_of_quarter
|
149
|
+
beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
|
150
|
+
end
|
151
|
+
alias :at_beginning_of_quarter :beginning_of_quarter
|
152
|
+
|
153
|
+
# Returns a new Date/DateTime representing the end of the quarter (last day of march, june, september, december; DateTime objects will have time set to 23:59:59)
|
154
|
+
def end_of_quarter
|
155
|
+
beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= self.month }).end_of_month
|
156
|
+
end
|
157
|
+
alias :at_end_of_quarter :end_of_quarter
|
158
|
+
|
159
|
+
# Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00)
|
160
|
+
def beginning_of_year
|
161
|
+
change(:month => 1, :day => 1)
|
162
|
+
end
|
163
|
+
alias :at_beginning_of_year :beginning_of_year
|
164
|
+
|
165
|
+
# Returns a new Time representing the end of the year (31st of december; DateTime objects will have time set to 23:59:59)
|
166
|
+
def end_of_year
|
167
|
+
change(:month => 12, :day => 31)
|
168
|
+
end
|
169
|
+
alias :at_end_of_year :end_of_year
|
170
|
+
|
171
|
+
# Convenience method which returns a new Date/DateTime representing the time 1 day ago
|
172
|
+
def yesterday
|
173
|
+
self - 1
|
174
|
+
end
|
175
|
+
|
176
|
+
# Convenience method which returns a new Date/DateTime representing the time 1 day since the instance time
|
177
|
+
def tomorrow
|
178
|
+
self + 1
|
179
|
+
end
|
180
|
+
|
181
|
+
# Convert to a formatted string. See DATE_FORMATS for predefined formats.
|
182
|
+
#
|
183
|
+
# This method is aliased to <tt>to_s</tt>.
|
184
|
+
#
|
185
|
+
# ==== Examples
|
186
|
+
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
187
|
+
#
|
188
|
+
# date.to_formatted_s(:db) # => "2007-11-10"
|
189
|
+
# date.to_s(:db) # => "2007-11-10"
|
190
|
+
#
|
191
|
+
# date.to_formatted_s(:short) # => "10 Nov"
|
192
|
+
# date.to_formatted_s(:long) # => "November 10, 2007"
|
193
|
+
# date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
|
194
|
+
# date.to_formatted_s(:rfc822) # => "10 Nov 2007"
|
195
|
+
#
|
196
|
+
# == Adding your own time formats to to_formatted_s
|
197
|
+
# You can add your own formats to the Date::DATE_FORMATS hash.
|
198
|
+
# Use the format name as the hash key and either a strftime string
|
199
|
+
# or Proc instance that takes a date argument as the value.
|
200
|
+
#
|
201
|
+
# # config/initializers/time_formats.rb
|
202
|
+
# Date::DATE_FORMATS[:month_and_year] = "%B %Y"
|
203
|
+
# Date::DATE_FORMATS[:short_ordinal] = lambda { |date| date.strftime("%B #{date.day.ordinalize}") }
|
204
|
+
def to_formatted_s(format = :default)
|
205
|
+
if formatter = DATE_FORMATS[format]
|
206
|
+
if formatter.respond_to?(:call)
|
207
|
+
formatter.call(self).to_s
|
208
|
+
else
|
209
|
+
strftime(formatter)
|
210
|
+
end
|
211
|
+
else
|
212
|
+
to_default_s
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
|
217
|
+
def readable_inspect
|
218
|
+
strftime("%a, %d %b %Y")
|
219
|
+
end
|
220
|
+
|
221
|
+
# Converts a Date instance to a Time, where the time is set to the beginning of the day.
|
222
|
+
# The timezone can be either :local or :utc (default :local).
|
223
|
+
#
|
224
|
+
# ==== Examples
|
225
|
+
# date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
|
226
|
+
#
|
227
|
+
# date.to_time # => Sat Nov 10 00:00:00 0800 2007
|
228
|
+
# date.to_time(:local) # => Sat Nov 10 00:00:00 0800 2007
|
229
|
+
#
|
230
|
+
# date.to_time(:utc) # => Sat Nov 10 00:00:00 UTC 2007
|
231
|
+
def to_time(form = :local)
|
232
|
+
::Time.send("#{form}_time", year, month, day)
|
233
|
+
end
|
234
|
+
|
235
|
+
def xmlschema
|
236
|
+
to_time.xmlschema
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
class Date
|
243
|
+
include Useful::RubyExtensionsFromRails::Date
|
244
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensionsFromRails
|
3
|
+
# Provides accurate date and time measurements using Date#advance and
|
4
|
+
# Time#advance, respectively. It mainly supports the methods on Numeric,
|
5
|
+
# such as in this example:
|
6
|
+
#
|
7
|
+
# 1.month.ago # equivalent to Time.now.advance(:months => -1)
|
8
|
+
class Duration
|
9
|
+
attr_accessor :value, :parts
|
10
|
+
|
11
|
+
def initialize(value, parts) #:nodoc:
|
12
|
+
@value, @parts = value, parts
|
13
|
+
end
|
14
|
+
|
15
|
+
# Adds another Duration or a Numeric to this Duration. Numeric values
|
16
|
+
# are treated as seconds.
|
17
|
+
def +(other)
|
18
|
+
if Duration === other
|
19
|
+
Duration.new(value + other.value, @parts + other.parts)
|
20
|
+
else
|
21
|
+
Duration.new(value + other, @parts + [[:seconds, other]])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Subtracts another Duration or a Numeric from this Duration. Numeric
|
26
|
+
# values are treated as seconds.
|
27
|
+
def -(other)
|
28
|
+
self + (-other)
|
29
|
+
end
|
30
|
+
|
31
|
+
def -@ #:nodoc:
|
32
|
+
Duration.new(-value, parts.map { |type,number| [type, -number] })
|
33
|
+
end
|
34
|
+
|
35
|
+
def is_a?(klass) #:nodoc:
|
36
|
+
klass == Duration || super
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns true if <tt>other</tt> is also a Duration instance with the
|
40
|
+
# same <tt>value</tt>, or if <tt>other == value</tt>.
|
41
|
+
def ==(other)
|
42
|
+
if Duration === other
|
43
|
+
other.value == value
|
44
|
+
else
|
45
|
+
other == value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.===(other) #:nodoc:
|
50
|
+
other.is_a?(Duration) rescue super
|
51
|
+
end
|
52
|
+
|
53
|
+
# Calculates a new Time or Date that is as far in the future
|
54
|
+
# as this Duration represents.
|
55
|
+
def since(time = ::Time.current)
|
56
|
+
sum(1, time)
|
57
|
+
end
|
58
|
+
alias :from_now :since
|
59
|
+
|
60
|
+
# Calculates a new Time or Date that is as far in the past
|
61
|
+
# as this Duration represents.
|
62
|
+
def ago(time = ::Time.current)
|
63
|
+
sum(-1, time)
|
64
|
+
end
|
65
|
+
alias :until :ago
|
66
|
+
|
67
|
+
def inspect #:nodoc:
|
68
|
+
consolidated = parts.inject(::Hash.new(0)) { |h,part| h[part.first] += part.last; h }
|
69
|
+
[:years, :months, :days, :minutes, :seconds].map do |length|
|
70
|
+
n = consolidated[length]
|
71
|
+
"#{n} #{n == 1 ? length.to_s.singularize : length.to_s}" if n.nonzero?
|
72
|
+
end.compact.join(',')
|
73
|
+
end
|
74
|
+
|
75
|
+
protected
|
76
|
+
|
77
|
+
def sum(sign, time = ::Time.current) #:nodoc:
|
78
|
+
parts.inject(time) do |t,(type,number)|
|
79
|
+
if t.acts_like?(:time) || t.acts_like?(:date)
|
80
|
+
if type == :seconds
|
81
|
+
t.since(sign * number)
|
82
|
+
else
|
83
|
+
t.advance(type => sign * number)
|
84
|
+
end
|
85
|
+
else
|
86
|
+
raise ::ArgumentError, "expected a time or date, got #{time.inspect}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def method_missing(method, *args, &block) #:nodoc:
|
94
|
+
value.send(method, *args)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensionsFromRails
|
3
|
+
module Fixnum
|
4
|
+
|
5
|
+
# Turns a number into an ordinal string used to denote the position in an
|
6
|
+
# ordered sequence such as 1st, 2nd, 3rd, 4th.
|
7
|
+
#
|
8
|
+
# Examples:
|
9
|
+
# 1.ordinalize # => "1st"
|
10
|
+
# 2.ordinalize # => "2nd"
|
11
|
+
# 1003.ordinalize # => "1003rd"
|
12
|
+
# 1004.ordinalize # => "1004th"
|
13
|
+
def ordinalize
|
14
|
+
if (11..13).include?(self.to_i % 100)
|
15
|
+
"#{number}th"
|
16
|
+
else
|
17
|
+
case self.to_i % 10
|
18
|
+
when 1; "#{number}st"
|
19
|
+
when 2; "#{number}nd"
|
20
|
+
when 3; "#{number}rd"
|
21
|
+
else "#{number}th"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Fixnum
|
31
|
+
include Useful::RubyExtensionsFromRails::Fixnum
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensionsFromRails
|
3
|
+
module Hash
|
4
|
+
|
5
|
+
module ClassMethods; end
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend(ClassMethods) if klass.kind_of?(Class)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# inspired by ActiveSupport::CoreExtensions::Hash::Keys (http://api.rubyonrails.org/)
|
13
|
+
def stringify_keys(hash)
|
14
|
+
hash.keys.each{ |key| hash[(key.to_s rescue key)] ||= hash.delete(key) }
|
15
|
+
hash
|
16
|
+
end
|
17
|
+
|
18
|
+
# inspired by from ActiveSupport::CoreExtensions::Hash::Keys (http://api.rubyonrails.org/)
|
19
|
+
def symbolize_keys(hash)
|
20
|
+
hash.keys.each{ |key| hash[(key.to_sym rescue key)] ||= hash.delete(key) }
|
21
|
+
hash
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
# Return a new hash with all keys converted to strings.
|
27
|
+
def stringify_keys
|
28
|
+
self.class.stringify_keys(self.clone)
|
29
|
+
end
|
30
|
+
# Destructively convert all keys to strings.
|
31
|
+
def stringify_keys!
|
32
|
+
self.class.stringify_keys(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Return a new hash with all keys converted to strings.
|
36
|
+
def symbolize_keys
|
37
|
+
self.class.symbolize_keys(self.clone)
|
38
|
+
end
|
39
|
+
# Destructively convert all keys to strings.
|
40
|
+
def symbolize_keys!
|
41
|
+
self.class.symbolize_keys(self)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Hash
|
49
|
+
include Useful::RubyExtensionsFromRails::Hash
|
50
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'duration')
|
2
|
+
|
3
|
+
module Useful
|
4
|
+
module RubyExtensionsFromRails
|
5
|
+
module Numeric
|
6
|
+
|
7
|
+
def seconds
|
8
|
+
Useful::RubyExtensionsFromRails::Duration.new(self, [[:seconds, self]])
|
9
|
+
end
|
10
|
+
alias :second :seconds
|
11
|
+
|
12
|
+
def minutes
|
13
|
+
Useful::RubyExtensionsFromRails::Duration.new(self * 60, [[:seconds, self * 60]])
|
14
|
+
end
|
15
|
+
alias :minute :minutes
|
16
|
+
|
17
|
+
def hours
|
18
|
+
Useful::RubyExtensionsFromRails::Duration.new(self * 3600, [[:seconds, self * 3600]])
|
19
|
+
end
|
20
|
+
alias :hour :hours
|
21
|
+
|
22
|
+
def days
|
23
|
+
Useful::RubyExtensionsFromRails::Duration.new(self * 24.hours, [[:days, self]])
|
24
|
+
end
|
25
|
+
alias :day :days
|
26
|
+
|
27
|
+
def weeks
|
28
|
+
Useful::RubyExtensionsFromRails::Duration.new(self * 7.days, [[:days, self * 7]])
|
29
|
+
end
|
30
|
+
alias :week :weeks
|
31
|
+
|
32
|
+
def fortnights
|
33
|
+
Useful::RubyExtensionsFromRails::Duration.new(self * 2.weeks, [[:days, self * 14]])
|
34
|
+
end
|
35
|
+
alias :fortnight :fortnights
|
36
|
+
|
37
|
+
# Reads best without arguments: 10.minutes.ago
|
38
|
+
def ago(time = ::Time.now)
|
39
|
+
time - self
|
40
|
+
end
|
41
|
+
|
42
|
+
# Reads best with argument: 10.minutes.until(time)
|
43
|
+
alias :until :ago
|
44
|
+
|
45
|
+
# Reads best with argument: 10.minutes.since(time)
|
46
|
+
def since(time = ::Time.now)
|
47
|
+
time + self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Reads best without arguments: 10.minutes.from_now
|
51
|
+
alias :from_now :since
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
class Numeric
|
59
|
+
include Useful::RubyExtensionsFromRails::Numeric
|
60
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensionsFromRails
|
3
|
+
module Object
|
4
|
+
|
5
|
+
def blank?
|
6
|
+
self.nil? || (self.respond_to?(:empty?) ? self.empty? : false)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns +value+ after yielding +value+ to the block. This simplifies the
|
10
|
+
# process of constructing an object, performing work on the object, and then
|
11
|
+
# returning the object from a method. It is a Ruby-ized realization of the K
|
12
|
+
# combinator, courtesy of Mikael Brockman.
|
13
|
+
#
|
14
|
+
# ==== Examples
|
15
|
+
#
|
16
|
+
# # Without returning
|
17
|
+
# def foo
|
18
|
+
# values = []
|
19
|
+
# values << "bar"
|
20
|
+
# values << "baz"
|
21
|
+
# return values
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# foo # => ['bar', 'baz']
|
25
|
+
#
|
26
|
+
# # returning with a local variable
|
27
|
+
# def foo
|
28
|
+
# returning values = [] do
|
29
|
+
# values << 'bar'
|
30
|
+
# values << 'baz'
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# foo # => ['bar', 'baz']
|
35
|
+
#
|
36
|
+
# # returning with a block argument
|
37
|
+
# def foo
|
38
|
+
# returning [] do |values|
|
39
|
+
# values << 'bar'
|
40
|
+
# values << 'baz'
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# foo # => ['bar', 'baz']
|
45
|
+
def returning(value)
|
46
|
+
yield(value)
|
47
|
+
value
|
48
|
+
end
|
49
|
+
|
50
|
+
# Yields <code>x</code> to the block, and then returns <code>x</code>.
|
51
|
+
# The primary purpose of this method is to "tap into" a method chain,
|
52
|
+
# in order to perform operations on intermediate results within the chain.
|
53
|
+
#
|
54
|
+
# (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
|
55
|
+
# tap { |x| puts "array: #{x.inspect}" }.
|
56
|
+
# select { |x| x%2 == 0 }.
|
57
|
+
# tap { |x| puts "evens: #{x.inspect}" }.
|
58
|
+
# map { |x| x*x }.
|
59
|
+
# tap { |x| puts "squares: #{x.inspect}" }
|
60
|
+
def tap
|
61
|
+
yield self
|
62
|
+
self
|
63
|
+
end unless ::Object.respond_to?(:tap)
|
64
|
+
|
65
|
+
# A duck-type assistant method. For example, Active Support extends Date
|
66
|
+
# to define an acts_like_date? method, and extends Time to define
|
67
|
+
# acts_like_time?. As a result, we can do "x.acts_like?(:time)" and
|
68
|
+
# "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that
|
69
|
+
# we want to act like Time simply need to define an acts_like_time? method.
|
70
|
+
def acts_like?(duck)
|
71
|
+
respond_to? "acts_like_#{duck}?"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Object
|
78
|
+
include Useful::RubyExtensionsFromRails::Object
|
79
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensionsFromRails
|
3
|
+
module String
|
4
|
+
|
5
|
+
module ClassMethods; end
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend(ClassMethods) if klass.kind_of?(Class)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
|
13
|
+
# is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
|
14
|
+
#
|
15
|
+
# +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
|
16
|
+
#
|
17
|
+
# Examples:
|
18
|
+
# "active_record".camelize # => "ActiveRecord"
|
19
|
+
# "active_record".camelize(:lower) # => "activeRecord"
|
20
|
+
# "active_record/errors".camelize # => "ActiveRecord::Errors"
|
21
|
+
# "active_record/errors".camelize(:lower) # => "activeRecord::Errors"
|
22
|
+
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
23
|
+
if first_letter_in_uppercase
|
24
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
25
|
+
else
|
26
|
+
lower_case_and_underscored_word.first.downcase + camelize(lower_case_and_underscored_word)[1..-1]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
|
31
|
+
#
|
32
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
33
|
+
#
|
34
|
+
# Examples:
|
35
|
+
# "ActiveRecord".underscore # => "active_record"
|
36
|
+
# "ActiveRecord::Errors".underscore # => active_record/errors
|
37
|
+
def underscore(camel_cased_word)
|
38
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
39
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
40
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
41
|
+
tr("-", "_").
|
42
|
+
downcase
|
43
|
+
end
|
44
|
+
|
45
|
+
# Replaces underscores with dashes in the string.
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
# "puni_puni" # => "puni-puni"
|
49
|
+
def dasherize(underscored_word)
|
50
|
+
underscored_word.gsub(/_/, '-')
|
51
|
+
end
|
52
|
+
|
53
|
+
# Removes the module part from the expression in the string.
|
54
|
+
#
|
55
|
+
# Examples:
|
56
|
+
# "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections"
|
57
|
+
# "Inflections".demodulize # => "Inflections"
|
58
|
+
def demodulize(class_name_in_module)
|
59
|
+
class_name_in_module.to_s.gsub(/^.*::/, '')
|
60
|
+
end
|
61
|
+
|
62
|
+
# Create a class name from a string like Rails does for table names to models.
|
63
|
+
# Note that this returns a string and not a Class. (To convert to an actual class
|
64
|
+
# follow +classify+ with +constantize+.)
|
65
|
+
#
|
66
|
+
# Examples:
|
67
|
+
# "egg_and_hams".classify # => "EggAndHam"
|
68
|
+
# "posts".classify # => "Post"
|
69
|
+
#
|
70
|
+
# Singular names are not handled correctly:
|
71
|
+
# "business".classify # => "Busines"
|
72
|
+
def classify(class_str)
|
73
|
+
# strip out any leading schema name
|
74
|
+
camelize(class_str.to_s.sub(/.*\./, ''))
|
75
|
+
end
|
76
|
+
|
77
|
+
# Ruby 1.9 introduces an inherit argument for Module#const_get and
|
78
|
+
# #const_defined? and changes their default behavior.
|
79
|
+
if Module.method(:const_get).arity == 1
|
80
|
+
# Tries to find a constant with the name specified in the argument string:
|
81
|
+
#
|
82
|
+
# "Module".constantize # => Module
|
83
|
+
# "Test::Unit".constantize # => Test::Unit
|
84
|
+
#
|
85
|
+
# The name is assumed to be the one of a top-level constant, no matter whether
|
86
|
+
# it starts with "::" or not. No lexical context is taken into account:
|
87
|
+
#
|
88
|
+
# C = 'outside'
|
89
|
+
# module M
|
90
|
+
# C = 'inside'
|
91
|
+
# C # => 'inside'
|
92
|
+
# "C".constantize # => 'outside', same as ::C
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
# NameError is raised when the name is not in CamelCase or the constant is
|
96
|
+
# unknown.
|
97
|
+
def constantize(camel_cased_word)
|
98
|
+
names = camel_cased_word.split('::')
|
99
|
+
names.shift if names.empty? || names.first.empty?
|
100
|
+
|
101
|
+
constant = ::Object
|
102
|
+
names.each do |name|
|
103
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
104
|
+
end
|
105
|
+
constant
|
106
|
+
end
|
107
|
+
else
|
108
|
+
def constantize(camel_cased_word) #:nodoc:
|
109
|
+
names = camel_cased_word.split('::')
|
110
|
+
names.shift if names.empty? || names.first.empty?
|
111
|
+
|
112
|
+
constant = ::Object
|
113
|
+
names.each do |name|
|
114
|
+
constant = constant.const_get(name, false) || constant.const_missing(name)
|
115
|
+
end
|
116
|
+
constant
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end #ClassMethods
|
121
|
+
|
122
|
+
def camelize(first_letter = :upper)
|
123
|
+
case first_letter
|
124
|
+
when :upper then String.camelize(self, true)
|
125
|
+
when :lower then String.camelize(self, false)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
alias_method :camelcase, :camelize
|
129
|
+
|
130
|
+
def underscore
|
131
|
+
self.class.underscore(self)
|
132
|
+
end
|
133
|
+
|
134
|
+
def dasherize
|
135
|
+
self.class.dasherize(self)
|
136
|
+
end
|
137
|
+
|
138
|
+
def demodulize
|
139
|
+
self.class.demodulize(self)
|
140
|
+
end
|
141
|
+
|
142
|
+
def classify
|
143
|
+
self.class.classify(self)
|
144
|
+
end
|
145
|
+
|
146
|
+
def constantize
|
147
|
+
self.class.constantize(self)
|
148
|
+
end
|
149
|
+
|
150
|
+
def ends_with?(suffix)
|
151
|
+
suffix = suffix.to_s
|
152
|
+
self[-suffix.length, suffix.length] == suffix
|
153
|
+
end
|
154
|
+
|
155
|
+
def starts_with?(prefix)
|
156
|
+
prefix = prefix.to_s
|
157
|
+
self[0, prefix.length] == prefix
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class String
|
165
|
+
include Useful::RubyExtensionsFromRails::String
|
166
|
+
end
|
@@ -0,0 +1,320 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'object') unless Object.new.respond_to?(:acts_like?)
|
2
|
+
require File.join(File.dirname(__FILE__), 'duration')
|
3
|
+
require File.join(File.dirname(__FILE__), 'numeric')
|
4
|
+
|
5
|
+
module Useful
|
6
|
+
module RubyExtensionsFromRails
|
7
|
+
module Time
|
8
|
+
|
9
|
+
def self.included(base) #:nodoc:
|
10
|
+
base.extend ClassMethods
|
11
|
+
base.class_eval do
|
12
|
+
alias_method :to_default_s, :to_s
|
13
|
+
alias_method :to_s, :to_formatted_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
18
|
+
DATE_FORMATS = {
|
19
|
+
:db => "%Y-%m-%d %H:%M:%S",
|
20
|
+
:number => "%Y%m%d%H%M%S",
|
21
|
+
:time => "%H:%M",
|
22
|
+
:short => "%d %b %H:%M",
|
23
|
+
:long => "%B %d, %Y %H:%M",
|
24
|
+
:long_ordinal => lambda { |time| time.strftime("%B #{time.day.ordinalize}, %Y %H:%M") },
|
25
|
+
:rfc822 => lambda { |time| time.strftime("%a, %d %b %Y %H:%M:%S #{time.formatted_offset(false)}") }
|
26
|
+
}
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
# Return the number of days in the given month.
|
30
|
+
# If no year is specified, it will use the current year.
|
31
|
+
def days_in_month(month, year = now.year)
|
32
|
+
return 29 if month == 2 && ::Date.gregorian_leap?(year)
|
33
|
+
COMMON_YEAR_DAYS_IN_MONTH[month]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns a new Time if requested year can be accommodated by Ruby's Time class
|
37
|
+
# (i.e., if year is within either 1970..2038 or 1902..2038, depending on system architecture);
|
38
|
+
# otherwise returns a DateTime
|
39
|
+
def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
|
40
|
+
::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:utc</tt>.
|
44
|
+
def utc_time(*args)
|
45
|
+
time_with_datetime_fallback(:utc, *args)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Wraps class method +time_with_datetime_fallback+ with +utc_or_local+ set to <tt>:local</tt>.
|
49
|
+
def local_time(*args)
|
50
|
+
time_with_datetime_fallback(:local, *args)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns Time.now
|
54
|
+
def current
|
55
|
+
::Time.now
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
# Enable more predictable duck-typing on Time-like classes. See
|
61
|
+
# Object#acts_like?.
|
62
|
+
def acts_like_time?
|
63
|
+
true
|
64
|
+
end
|
65
|
+
|
66
|
+
# Tells whether the Time object's time lies in the past
|
67
|
+
def past?
|
68
|
+
self < ::Time.current
|
69
|
+
end
|
70
|
+
|
71
|
+
# Tells whether the Time object's time is today
|
72
|
+
def today?
|
73
|
+
self.to_date == ::Date.current
|
74
|
+
end
|
75
|
+
|
76
|
+
# Tells whether the Time object's time lies in the future
|
77
|
+
def future?
|
78
|
+
self > ::Time.current
|
79
|
+
end
|
80
|
+
|
81
|
+
# Seconds since midnight: Time.now.seconds_since_midnight
|
82
|
+
def seconds_since_midnight
|
83
|
+
self.to_i - self.change(:hour => 0).to_i + (self.usec/1.0e+6)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns a new Time where one or more of the elements have been changed according to the +options+ parameter. The time options
|
87
|
+
# (hour, minute, sec, usec) reset cascadingly, so if only the hour is passed, then minute, sec, and usec is set to 0. If the hour and
|
88
|
+
# minute is passed, then sec and usec is set to 0.
|
89
|
+
def change(options)
|
90
|
+
::Time.send(
|
91
|
+
self.utc? ? :utc_time : :local_time,
|
92
|
+
options[:year] || self.year,
|
93
|
+
options[:month] || self.month,
|
94
|
+
options[:day] || self.day,
|
95
|
+
options[:hour] || self.hour,
|
96
|
+
options[:min] || (options[:hour] ? 0 : self.min),
|
97
|
+
options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec),
|
98
|
+
options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec)
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Uses Date to provide precise Time calculations for years, months, and days.
|
103
|
+
# The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
|
104
|
+
# <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
|
105
|
+
# <tt>:minutes</tt>, <tt>:seconds</tt>.
|
106
|
+
def advance(options)
|
107
|
+
unless options[:weeks].nil?
|
108
|
+
options[:weeks], partial_weeks = options[:weeks].divmod(1)
|
109
|
+
options[:days] = (options[:days] || 0) + 7 * partial_weeks
|
110
|
+
end
|
111
|
+
|
112
|
+
unless options[:days].nil?
|
113
|
+
options[:days], partial_days = options[:days].divmod(1)
|
114
|
+
options[:hours] = (options[:hours] || 0) + 24 * partial_days
|
115
|
+
end
|
116
|
+
|
117
|
+
d = to_date.advance(options)
|
118
|
+
time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
|
119
|
+
seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
|
120
|
+
seconds_to_advance == 0 ? time_advanced_by_date : time_advanced_by_date.since(seconds_to_advance)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
|
124
|
+
def ago(seconds)
|
125
|
+
self.since(-seconds)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns a new Time representing the time a number of seconds since the instance time, this is basically a wrapper around
|
129
|
+
# the Numeric extension.
|
130
|
+
def since(seconds)
|
131
|
+
f = seconds.since(self)
|
132
|
+
if Useful::RubyExtensionsFromRails::Duration === seconds
|
133
|
+
f
|
134
|
+
else
|
135
|
+
initial_dst = self.dst? ? 1 : 0
|
136
|
+
final_dst = f.dst? ? 1 : 0
|
137
|
+
(seconds.abs >= 86400 && initial_dst != final_dst) ? f + (initial_dst - final_dst).hours : f
|
138
|
+
end
|
139
|
+
end
|
140
|
+
alias :in :since
|
141
|
+
|
142
|
+
# Returns a new Time representing the time a number of specified months ago
|
143
|
+
def months_ago(months)
|
144
|
+
advance(:months => -months)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Returns a new Time representing the time a number of specified months in the future
|
148
|
+
def months_since(months)
|
149
|
+
advance(:months => months)
|
150
|
+
end
|
151
|
+
|
152
|
+
# Returns a new Time representing the time a number of specified years ago
|
153
|
+
def years_ago(years)
|
154
|
+
advance(:years => -years)
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns a new Time representing the time a number of specified years in the future
|
158
|
+
def years_since(years)
|
159
|
+
advance(:years => years)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Short-hand for years_ago(1)
|
163
|
+
def last_year
|
164
|
+
years_ago(1)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Short-hand for years_since(1)
|
168
|
+
def next_year
|
169
|
+
years_since(1)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Short-hand for months_ago(1)
|
173
|
+
def last_month
|
174
|
+
months_ago(1)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Short-hand for months_since(1)
|
178
|
+
def next_month
|
179
|
+
months_since(1)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Returns a new Time representing the start of the day (0:00)
|
183
|
+
def beginning_of_day
|
184
|
+
(self - self.seconds_since_midnight).change(:usec => 0)
|
185
|
+
end
|
186
|
+
alias :midnight :beginning_of_day
|
187
|
+
alias :at_midnight :beginning_of_day
|
188
|
+
alias :at_beginning_of_day :beginning_of_day
|
189
|
+
|
190
|
+
# Returns a new Time representing the end of the day (23:59:59)
|
191
|
+
def end_of_day
|
192
|
+
change(:hour => 23, :min => 59, :sec => 59)
|
193
|
+
end
|
194
|
+
alias :at_end_of_day :end_of_day
|
195
|
+
|
196
|
+
# Returns a new Time representing the "start" of this week (Monday, 0:00)
|
197
|
+
def beginning_of_week
|
198
|
+
days_to_monday = self.wday!=0 ? self.wday-1 : 6
|
199
|
+
(self - days_to_monday.days).midnight
|
200
|
+
end
|
201
|
+
alias :monday :beginning_of_week
|
202
|
+
alias :at_beginning_of_week :beginning_of_week
|
203
|
+
|
204
|
+
# Returns a new Time representing the end of this week (Sunday, 23:59:59)
|
205
|
+
def end_of_week
|
206
|
+
days_to_sunday = self.wday!=0 ? 7-self.wday : 0
|
207
|
+
(self + days_to_sunday.days).end_of_day
|
208
|
+
end
|
209
|
+
alias :at_end_of_week :end_of_week
|
210
|
+
|
211
|
+
# Returns a new Time representing the start of the given day in next week (default is Monday).
|
212
|
+
def next_week(day = :monday)
|
213
|
+
days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
|
214
|
+
since(1.week).beginning_of_week.since(days_into_week[day].day).change(:hour => 0)
|
215
|
+
end
|
216
|
+
|
217
|
+
# Returns a new Time representing the start of the month (1st of the month, 0:00)
|
218
|
+
def beginning_of_month
|
219
|
+
#self - ((self.mday-1).days + self.seconds_since_midnight)
|
220
|
+
change(:day => 1,:hour => 0, :min => 0, :sec => 0, :usec => 0)
|
221
|
+
end
|
222
|
+
alias :at_beginning_of_month :beginning_of_month
|
223
|
+
|
224
|
+
# Returns a new Time representing the end of the month (last day of the month, 0:00)
|
225
|
+
def end_of_month
|
226
|
+
#self - ((self.mday-1).days + self.seconds_since_midnight)
|
227
|
+
last_day = ::Time.days_in_month( self.month, self.year )
|
228
|
+
change(:day => last_day, :hour => 23, :min => 59, :sec => 59, :usec => 0)
|
229
|
+
end
|
230
|
+
alias :at_end_of_month :end_of_month
|
231
|
+
|
232
|
+
# Returns a new Time representing the start of the quarter (1st of january, april, july, october, 0:00)
|
233
|
+
def beginning_of_quarter
|
234
|
+
beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
|
235
|
+
end
|
236
|
+
alias :at_beginning_of_quarter :beginning_of_quarter
|
237
|
+
|
238
|
+
# Returns a new Time representing the end of the quarter (last day of march, june, september, december, 23:59:59)
|
239
|
+
def end_of_quarter
|
240
|
+
beginning_of_month.change(:month => [3, 6, 9, 12].detect { |m| m >= self.month }).end_of_month
|
241
|
+
end
|
242
|
+
alias :at_end_of_quarter :end_of_quarter
|
243
|
+
|
244
|
+
# Returns a new Time representing the start of the year (1st of january, 0:00)
|
245
|
+
def beginning_of_year
|
246
|
+
change(:month => 1,:day => 1,:hour => 0, :min => 0, :sec => 0, :usec => 0)
|
247
|
+
end
|
248
|
+
alias :at_beginning_of_year :beginning_of_year
|
249
|
+
|
250
|
+
# Returns a new Time representing the end of the year (31st of december, 23:59:59)
|
251
|
+
def end_of_year
|
252
|
+
change(:month => 12,:day => 31,:hour => 23, :min => 59, :sec => 59)
|
253
|
+
end
|
254
|
+
alias :at_end_of_year :end_of_year
|
255
|
+
|
256
|
+
# Convenience method which returns a new Time representing the time 1 day ago
|
257
|
+
def yesterday
|
258
|
+
advance(:days => -1)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Convenience method which returns a new Time representing the time 1 day since the instance time
|
262
|
+
def tomorrow
|
263
|
+
advance(:days => 1)
|
264
|
+
end
|
265
|
+
|
266
|
+
# Converts to a formatted string. See DATE_FORMATS for builtin formats.
|
267
|
+
#
|
268
|
+
# This method is aliased to <tt>to_s</tt>.
|
269
|
+
#
|
270
|
+
# time = Time.now # => Thu Jan 18 06:10:17 CST 2007
|
271
|
+
#
|
272
|
+
# time.to_formatted_s(:time) # => "06:10:17"
|
273
|
+
# time.to_s(:time) # => "06:10:17"
|
274
|
+
#
|
275
|
+
# time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
|
276
|
+
# time.to_formatted_s(:number) # => "20070118061017"
|
277
|
+
# time.to_formatted_s(:short) # => "18 Jan 06:10"
|
278
|
+
# time.to_formatted_s(:long) # => "January 18, 2007 06:10"
|
279
|
+
# time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
|
280
|
+
# time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
|
281
|
+
#
|
282
|
+
# == Adding your own time formats to +to_formatted_s+
|
283
|
+
# You can add your own formats to the Time::DATE_FORMATS hash.
|
284
|
+
# Use the format name as the hash key and either a strftime string
|
285
|
+
# or Proc instance that takes a time argument as the value.
|
286
|
+
#
|
287
|
+
# # config/initializers/time_formats.rb
|
288
|
+
# Time::DATE_FORMATS[:month_and_year] = "%B %Y"
|
289
|
+
# Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
|
290
|
+
def to_formatted_s(format = :default)
|
291
|
+
return to_default_s unless formatter = DATE_FORMATS[format]
|
292
|
+
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
|
293
|
+
end
|
294
|
+
|
295
|
+
# Returns the UTC offset as an +HH:MM formatted string.
|
296
|
+
#
|
297
|
+
# Time.local(2000).formatted_offset # => "-06:00"
|
298
|
+
# Time.local(2000).formatted_offset(false) # => "-0600"
|
299
|
+
def formatted_offset(colon = true, alternate_utc_string = nil)
|
300
|
+
utc? && alternate_utc_string || utc_offset.to_utc_offset_s(colon)
|
301
|
+
end
|
302
|
+
|
303
|
+
# Converts a Time object to a Date, dropping hour, minute, and second precision.
|
304
|
+
#
|
305
|
+
# my_time = Time.now # => Mon Nov 12 22:59:51 -0500 2007
|
306
|
+
# my_time.to_date # => Mon, 12 Nov 2007
|
307
|
+
#
|
308
|
+
# your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009
|
309
|
+
# your_time.to_date # => Tue, 13 Jan 2009
|
310
|
+
def to_date
|
311
|
+
::Date.new(year, month, day)
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
class Time
|
319
|
+
include Useful::RubyExtensionsFromRails::Time
|
320
|
+
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
|
-
require
|
3
|
-
|
4
|
-
require 'sinatra_helpers/tags'
|
1
|
+
Dir[File.join(File.dirname(__FILE__), "sinatra_helpers" ,"*.rb")].each do |file|
|
2
|
+
require file
|
3
|
+
end
|
data/lib/useful/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kelredd-useful
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kelredd
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-16 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -27,12 +27,25 @@ files:
|
|
27
27
|
- lib/useful
|
28
28
|
- lib/useful/ruby_extensions
|
29
29
|
- lib/useful/ruby_extensions/array.rb
|
30
|
+
- lib/useful/ruby_extensions/date.rb
|
31
|
+
- lib/useful/ruby_extensions/false_class.rb
|
30
32
|
- lib/useful/ruby_extensions/fixnum.rb
|
31
33
|
- lib/useful/ruby_extensions/hash.rb
|
32
34
|
- lib/useful/ruby_extensions/numeric.rb
|
33
35
|
- lib/useful/ruby_extensions/object.rb
|
34
36
|
- lib/useful/ruby_extensions/string.rb
|
37
|
+
- lib/useful/ruby_extensions/true_class.rb
|
35
38
|
- lib/useful/ruby_extensions.rb
|
39
|
+
- lib/useful/ruby_extensions_from_rails
|
40
|
+
- lib/useful/ruby_extensions_from_rails/date.rb
|
41
|
+
- lib/useful/ruby_extensions_from_rails/duration.rb
|
42
|
+
- lib/useful/ruby_extensions_from_rails/fixnum.rb
|
43
|
+
- lib/useful/ruby_extensions_from_rails/hash.rb
|
44
|
+
- lib/useful/ruby_extensions_from_rails/numeric.rb
|
45
|
+
- lib/useful/ruby_extensions_from_rails/object.rb
|
46
|
+
- lib/useful/ruby_extensions_from_rails/string.rb
|
47
|
+
- lib/useful/ruby_extensions_from_rails/time.rb
|
48
|
+
- lib/useful/ruby_extensions_from_rails.rb
|
36
49
|
- lib/useful/sinatra_helpers
|
37
50
|
- lib/useful/sinatra_helpers/environment_tests.rb
|
38
51
|
- lib/useful/sinatra_helpers/erb
|