activesupport 1.4.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (126) hide show
  1. data/CHANGELOG +263 -7
  2. data/lib/active_support.rb +9 -4
  3. data/lib/active_support/basic_object.rb +5 -0
  4. data/lib/active_support/buffered_logger.rb +107 -0
  5. data/lib/active_support/clean_logger.rb +94 -5
  6. data/lib/active_support/core_ext.rb +4 -1
  7. data/lib/active_support/core_ext/array.rb +8 -2
  8. data/lib/active_support/core_ext/array/access.rb +28 -0
  9. data/lib/active_support/core_ext/array/conversions.rb +28 -15
  10. data/lib/active_support/core_ext/array/extract_options.rb +19 -0
  11. data/lib/active_support/core_ext/array/grouping.rb +20 -7
  12. data/lib/active_support/core_ext/array/random_access.rb +12 -0
  13. data/lib/active_support/core_ext/bigdecimal.rb +1 -2
  14. data/lib/active_support/core_ext/bigdecimal/{formatting.rb → conversions.rb} +1 -2
  15. data/lib/active_support/core_ext/blank.rb +2 -8
  16. data/lib/active_support/core_ext/cgi.rb +2 -2
  17. data/lib/active_support/core_ext/class.rb +4 -3
  18. data/lib/active_support/core_ext/class/attribute_accessors.rb +1 -1
  19. data/lib/active_support/core_ext/class/delegating_attributes.rb +40 -0
  20. data/lib/active_support/core_ext/class/inheritable_attributes.rb +3 -3
  21. data/lib/active_support/core_ext/class/removal.rb +2 -2
  22. data/lib/active_support/core_ext/date.rb +5 -1
  23. data/lib/active_support/core_ext/date/behavior.rb +13 -0
  24. data/lib/active_support/core_ext/date/calculations.rb +188 -0
  25. data/lib/active_support/core_ext/date/conversions.rb +69 -13
  26. data/lib/active_support/core_ext/date_time.rb +10 -0
  27. data/lib/active_support/core_ext/date_time/calculations.rb +77 -0
  28. data/lib/active_support/core_ext/date_time/conversions.rb +54 -0
  29. data/lib/active_support/core_ext/duplicable.rb +37 -0
  30. data/lib/active_support/core_ext/enumerable.rb +1 -0
  31. data/lib/active_support/core_ext/exception.rb +2 -2
  32. data/lib/active_support/core_ext/file.rb +21 -0
  33. data/lib/active_support/core_ext/float.rb +5 -0
  34. data/lib/active_support/core_ext/float/rounding.rb +24 -0
  35. data/lib/active_support/core_ext/hash.rb +5 -5
  36. data/lib/active_support/core_ext/hash/conversions.rb +86 -34
  37. data/lib/active_support/core_ext/hash/diff.rb +8 -0
  38. data/lib/active_support/core_ext/hash/except.rb +24 -0
  39. data/lib/active_support/core_ext/hash/indifferent_access.rb +15 -2
  40. data/lib/active_support/core_ext/hash/keys.rb +10 -3
  41. data/lib/active_support/core_ext/hash/reverse_merge.rb +2 -2
  42. data/lib/active_support/core_ext/hash/slice.rb +28 -0
  43. data/lib/active_support/core_ext/integer.rb +2 -2
  44. data/lib/active_support/core_ext/kernel.rb +5 -4
  45. data/lib/active_support/core_ext/kernel/debugger.rb +13 -0
  46. data/lib/active_support/core_ext/module.rb +8 -7
  47. data/lib/active_support/core_ext/module/aliasing.rb +17 -5
  48. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +31 -0
  49. data/lib/active_support/core_ext/module/attribute_accessors.rb +1 -1
  50. data/lib/active_support/core_ext/module/delegation.rb +21 -0
  51. data/lib/active_support/core_ext/name_error.rb +2 -2
  52. data/lib/active_support/core_ext/numeric.rb +2 -2
  53. data/lib/active_support/core_ext/numeric/time.rb +30 -11
  54. data/lib/active_support/core_ext/object.rb +3 -2
  55. data/lib/active_support/core_ext/object/extending.rb +40 -29
  56. data/lib/active_support/core_ext/object/instance_variables.rb +22 -0
  57. data/lib/active_support/core_ext/object/misc.rb +29 -4
  58. data/lib/active_support/core_ext/pathname.rb +1 -1
  59. data/lib/active_support/core_ext/range.rb +7 -1
  60. data/lib/active_support/core_ext/range/blockless_step.rb +22 -0
  61. data/lib/active_support/core_ext/range/conversions.rb +8 -6
  62. data/lib/active_support/core_ext/range/include_range.rb +22 -0
  63. data/lib/active_support/core_ext/range/overlaps.rb +12 -0
  64. data/lib/active_support/core_ext/string.rb +10 -7
  65. data/lib/active_support/core_ext/string/conversions.rb +5 -1
  66. data/lib/active_support/core_ext/string/unicode.rb +2 -2
  67. data/lib/active_support/core_ext/string/xchar.rb +11 -0
  68. data/lib/active_support/core_ext/symbol.rb +12 -10
  69. data/lib/active_support/core_ext/test.rb +1 -0
  70. data/lib/active_support/core_ext/test/unit/assertions.rb +62 -0
  71. data/lib/active_support/core_ext/time.rb +4 -2
  72. data/lib/active_support/core_ext/time/behavior.rb +13 -0
  73. data/lib/active_support/core_ext/time/calculations.rb +87 -54
  74. data/lib/active_support/core_ext/time/conversions.rb +71 -10
  75. data/lib/active_support/dependencies.rb +25 -24
  76. data/lib/active_support/deprecation.rb +4 -2
  77. data/lib/active_support/duration.rb +86 -0
  78. data/lib/active_support/inflections.rb +2 -1
  79. data/lib/active_support/inflector.rb +13 -6
  80. data/lib/active_support/json.rb +22 -39
  81. data/lib/active_support/json/decoding.rb +60 -0
  82. data/lib/active_support/json/encoders/date.rb +5 -0
  83. data/lib/active_support/json/encoders/date_time.rb +5 -0
  84. data/lib/active_support/json/encoders/enumerable.rb +12 -0
  85. data/lib/active_support/json/encoders/false_class.rb +5 -0
  86. data/lib/active_support/json/encoders/hash.rb +50 -0
  87. data/lib/active_support/json/encoders/nil_class.rb +5 -0
  88. data/lib/active_support/json/encoders/numeric.rb +5 -0
  89. data/lib/active_support/json/encoders/object.rb +6 -0
  90. data/lib/active_support/json/encoders/regexp.rb +5 -0
  91. data/lib/active_support/json/encoders/string.rb +30 -0
  92. data/lib/active_support/json/encoders/symbol.rb +5 -0
  93. data/lib/active_support/json/encoders/time.rb +5 -0
  94. data/lib/active_support/json/encoders/true_class.rb +5 -0
  95. data/lib/active_support/json/encoding.rb +38 -0
  96. data/lib/active_support/json/variable.rb +10 -0
  97. data/lib/active_support/multibyte.rb +7 -5
  98. data/lib/active_support/multibyte/chars.rb +6 -0
  99. data/lib/active_support/multibyte/handlers/utf8_handler.rb +115 -5
  100. data/lib/active_support/option_merger.rb +7 -7
  101. data/lib/active_support/ordered_options.rb +22 -17
  102. data/lib/active_support/test_case.rb +5 -0
  103. data/lib/active_support/testing.rb +1 -0
  104. data/lib/active_support/testing/default.rb +12 -0
  105. data/lib/active_support/values/time_zone.rb +3 -3
  106. data/lib/active_support/vendor.rb +14 -0
  107. data/lib/active_support/vendor/builder-2.1.2/blankslate.rb +113 -0
  108. data/lib/active_support/vendor/{builder.rb → builder-2.1.2/builder.rb} +0 -0
  109. data/lib/active_support/vendor/builder-2.1.2/builder/blankslate.rb +20 -0
  110. data/lib/active_support/vendor/builder-2.1.2/builder/css.rb +250 -0
  111. data/lib/active_support/vendor/{builder → builder-2.1.2/builder}/xchar.rb +11 -8
  112. data/lib/active_support/vendor/{builder → builder-2.1.2/builder}/xmlbase.rb +38 -44
  113. data/lib/active_support/vendor/{builder → builder-2.1.2/builder}/xmlevents.rb +1 -1
  114. data/lib/active_support/vendor/{builder → builder-2.1.2/builder}/xmlmarkup.rb +40 -39
  115. data/lib/active_support/vendor/{xml_simple.rb → xml-simple-1.0.11/xmlsimple.rb} +3 -3
  116. data/lib/active_support/version.rb +3 -3
  117. data/lib/active_support/whiny_nil.rb +12 -12
  118. data/lib/activesupport.rb +1 -0
  119. metadata +69 -17
  120. data/lib/active_support/binding_of_caller.rb +0 -84
  121. data/lib/active_support/breakpoint.rb +0 -528
  122. data/lib/active_support/caching_tools.rb +0 -62
  123. data/lib/active_support/json/encoders.rb +0 -25
  124. data/lib/active_support/json/encoders/core.rb +0 -70
  125. data/lib/active_support/reloadable.rb +0 -60
  126. data/lib/active_support/vendor/builder/blankslate.rb +0 -63
@@ -23,7 +23,7 @@ class Class # :nodoc:
23
23
  end
24
24
 
25
25
  def class_inheritable_writer(*syms)
26
- options = syms.last.is_a?(Hash) ? syms.pop : {}
26
+ options = syms.extract_options!
27
27
  syms.each do |sym|
28
28
  class_eval <<-EOS
29
29
  def self.#{sym}=(obj)
@@ -40,7 +40,7 @@ class Class # :nodoc:
40
40
  end
41
41
 
42
42
  def class_inheritable_array_writer(*syms)
43
- options = syms.last.is_a?(Hash) ? syms.pop : {}
43
+ options = syms.extract_options!
44
44
  syms.each do |sym|
45
45
  class_eval <<-EOS
46
46
  def self.#{sym}=(obj)
@@ -57,7 +57,7 @@ class Class # :nodoc:
57
57
  end
58
58
 
59
59
  def class_inheritable_hash_writer(*syms)
60
- options = syms.last.is_a?(Hash) ? syms.pop : {}
60
+ options = syms.extract_options!
61
61
  syms.each do |sym|
62
62
  class_eval <<-EOS
63
63
  def self.#{sym}=(obj)
@@ -17,8 +17,8 @@ class Class #:nodoc:
17
17
 
18
18
  # Skip this class if it does not match the current one bound to this name
19
19
  next unless parent.const_defined?(basename) && klass = parent.const_get(basename)
20
-
21
- parent.send :remove_const, basename unless parent == klass
20
+
21
+ parent.instance_eval { remove_const basename } unless parent == klass
22
22
  end
23
23
  end
24
24
  end
@@ -1,6 +1,10 @@
1
1
  require 'date'
2
- require File.dirname(__FILE__) + '/date/conversions'
2
+ require 'active_support/core_ext/date/behavior'
3
+ require 'active_support/core_ext/date/calculations'
4
+ require 'active_support/core_ext/date/conversions'
3
5
 
4
6
  class Date#:nodoc:
7
+ include ActiveSupport::CoreExtensions::Date::Behavior
8
+ include ActiveSupport::CoreExtensions::Date::Calculations
5
9
  include ActiveSupport::CoreExtensions::Date::Conversions
6
10
  end
@@ -0,0 +1,13 @@
1
+ module ActiveSupport #:nodoc:
2
+ module CoreExtensions #:nodoc:
3
+ module Date #:nodoc:
4
+ module Behavior
5
+ # Enable more predictable duck-typing on Date-like classes. See
6
+ # Object#acts_like?.
7
+ def acts_like_date?
8
+ true
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,188 @@
1
+ module ActiveSupport #:nodoc:
2
+ module CoreExtensions #:nodoc:
3
+ module Date #:nodoc:
4
+ # Enables the use of time calculations within Time itself
5
+ module Calculations
6
+ def self.included(base) #:nodoc:
7
+ base.extend ClassMethods
8
+
9
+ base.instance_eval do
10
+ alias_method :plus_without_duration, :+
11
+ alias_method :+, :plus_with_duration
12
+
13
+ alias_method :minus_without_duration, :-
14
+ alias_method :-, :minus_with_duration
15
+ end
16
+ end
17
+
18
+ module ClassMethods
19
+ def yesterday
20
+ ::Date.today.yesterday
21
+ end
22
+
23
+ def tomorrow
24
+ ::Date.today.tomorrow
25
+ end
26
+ end
27
+
28
+ # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
29
+ # and then subtracts the specified number of seconds
30
+ def ago(seconds)
31
+ to_time.since(-seconds)
32
+ end
33
+
34
+ # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
35
+ # and then adds the specified number of seconds
36
+ def since(seconds)
37
+ to_time.since(seconds)
38
+ end
39
+ alias :in :since
40
+
41
+ # Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)
42
+ def beginning_of_day
43
+ to_time
44
+ end
45
+ alias :midnight :beginning_of_day
46
+ alias :at_midnight :beginning_of_day
47
+ alias :at_beginning_of_day :beginning_of_day
48
+
49
+ # Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59)
50
+ def end_of_day
51
+ to_time.end_of_day
52
+ end
53
+
54
+ def plus_with_duration(other) #:nodoc:
55
+ if ActiveSupport::Duration === other
56
+ other.since(self)
57
+ else
58
+ plus_without_duration(other)
59
+ end
60
+ end
61
+
62
+ def minus_with_duration(other) #:nodoc:
63
+ if ActiveSupport::Duration === other
64
+ plus_with_duration(-other)
65
+ else
66
+ minus_without_duration(other)
67
+ end
68
+ end
69
+
70
+ # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
71
+ # any of these keys: :years, :months, :weeks, :days.
72
+ def advance(options)
73
+ d = self
74
+ d = d >> options.delete(:years) * 12 if options[:years]
75
+ d = d >> options.delete(:months) if options[:months]
76
+ d = d + options.delete(:weeks) * 7 if options[:weeks]
77
+ d = d + options.delete(:days) if options[:days]
78
+ d
79
+ end
80
+
81
+ # Returns a new Date where one or more of the elements have been changed according to the +options+ parameter.
82
+ #
83
+ # Examples:
84
+ #
85
+ # Date.new(2007, 5, 12).change(:day => 1) # => Date.new(2007, 5, 1)
86
+ # Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12)
87
+ def change(options)
88
+ ::Date.new(
89
+ options[:year] || self.year,
90
+ options[:month] || self.month,
91
+ options[:day] || self.day
92
+ )
93
+ end
94
+
95
+ # Returns a new Date/DateTime representing the time a number of specified months ago
96
+ def months_ago(months)
97
+ advance(:months => -months)
98
+ end
99
+
100
+ # Returns a new Date/DateTime representing the time a number of specified months in the future
101
+ def months_since(months)
102
+ advance(:months => months)
103
+ end
104
+
105
+ # Returns a new Date/DateTime representing the time a number of specified years ago
106
+ def years_ago(years)
107
+ advance(:years => -years)
108
+ end
109
+
110
+ # Returns a new Date/DateTime representing the time a number of specified years in the future
111
+ def years_since(years)
112
+ advance(:years => years)
113
+ end
114
+
115
+ # Short-hand for years_ago(1)
116
+ def last_year
117
+ years_ago(1)
118
+ end
119
+
120
+ # Short-hand for years_since(1)
121
+ def next_year
122
+ years_since(1)
123
+ end
124
+
125
+ # Short-hand for months_ago(1)
126
+ def last_month
127
+ months_ago(1)
128
+ end
129
+
130
+ # Short-hand for months_since(1)
131
+ def next_month
132
+ months_since(1)
133
+ end
134
+
135
+ # Returns a new Date/DateTime representing the "start" of this week (i.e, Monday; DateTime objects will have time set to 0:00)
136
+ def beginning_of_week
137
+ days_to_monday = self.wday!=0 ? self.wday-1 : 6
138
+ result = self - days_to_monday
139
+ self.acts_like?(:time) ? result.midnight : result
140
+ end
141
+ alias :monday :beginning_of_week
142
+ alias :at_beginning_of_week :beginning_of_week
143
+
144
+ # Returns a new Date/DateTime representing the start of the given day in next week (default is Monday).
145
+ def next_week(day = :monday)
146
+ days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
147
+ result = (self + 7).beginning_of_week + days_into_week[day]
148
+ self.acts_like?(:time) ? result.change(:hour => 0) : result
149
+ end
150
+
151
+ # Returns a new ; DateTime objects will have time set to 0:00DateTime representing the start of the month (1st of the month; DateTime objects will have time set to 0:00)
152
+ def beginning_of_month
153
+ self.acts_like?(:time) ? change(:day => 1,:hour => 0, :min => 0, :sec => 0) : change(:day => 1)
154
+ end
155
+ alias :at_beginning_of_month :beginning_of_month
156
+
157
+ # Returns a new Date/DateTime representing the end of the month (last day of the month; DateTime objects will have time set to 0:00)
158
+ def end_of_month
159
+ last_day = ::Time.days_in_month( self.month, self.year )
160
+ self.acts_like?(:time) ? change(:day => last_day, :hour => 23, :min => 59, :sec => 59) : change(:day => last_day)
161
+ end
162
+ alias :at_end_of_month :end_of_month
163
+
164
+ # 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)
165
+ def beginning_of_quarter
166
+ beginning_of_month.change(:month => [10, 7, 4, 1].detect { |m| m <= self.month })
167
+ end
168
+ alias :at_beginning_of_quarter :beginning_of_quarter
169
+
170
+ # Returns a new Date/DateTime representing the start of the year (1st of january; DateTime objects will have time set to 0:00)
171
+ def beginning_of_year
172
+ self.acts_like?(:time) ? change(:month => 1, :day => 1, :hour => 0, :min => 0, :sec => 0) : change(:month => 1, :day => 1)
173
+ end
174
+ alias :at_beginning_of_year :beginning_of_year
175
+
176
+ # Convenience method which returns a new Date/DateTime representing the time 1 day ago
177
+ def yesterday
178
+ self - 1
179
+ end
180
+
181
+ # Convenience method which returns a new Date/DateTime representing the time 1 day since the instance time
182
+ def tomorrow
183
+ self + 1
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -4,32 +4,88 @@ module ActiveSupport #:nodoc:
4
4
  # Getting dates in different convenient string representations and other objects
5
5
  module Conversions
6
6
  DATE_FORMATS = {
7
- :short => "%e %b",
8
- :long => "%B %e, %Y"
7
+ :short => "%e %b",
8
+ :long => "%B %e, %Y",
9
+ :db => "%Y-%m-%d",
10
+ :long_ordinal => lambda { |date| date.strftime("%B #{date.day.ordinalize}, %Y") }, # => "April 25th, 2007"
11
+ :rfc822 => "%e %b %Y"
9
12
  }
10
13
 
11
- def self.included(klass) #:nodoc:
12
- klass.send(:alias_method, :to_default_s, :to_s)
13
- klass.send(:alias_method, :to_s, :to_formatted_s)
14
+ def self.included(base) #:nodoc:
15
+ base.instance_eval do
16
+ alias_method :to_default_s, :to_s
17
+ alias_method :to_s, :to_formatted_s
18
+ alias_method :default_inspect, :inspect
19
+ alias_method :inspect, :readable_inspect
20
+
21
+ # Ruby 1.9 has Date#to_time which converts to localtime only.
22
+ remove_method :to_time if base.instance_methods.include?(:to_time)
23
+ end
14
24
  end
15
25
 
26
+ # Convert to a formatted string - see DATE_FORMATS for predefined formats.
27
+ # You can also add your own formats to the DATE_FORMATS constant and use them with this method.
28
+ #
29
+ # This method is also aliased as <tt>to_s</tt>.
30
+ #
31
+ # ==== Examples:
32
+ # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
33
+ #
34
+ # date.to_formatted_s(:db) # => "2007-11-10"
35
+ # date.to_s(:db) # => "2007-11-10"
36
+ #
37
+ # date.to_formatted_s(:short) # => "10 Nov"
38
+ # date.to_formatted_s(:long) # => "November 10, 2007"
39
+ # date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
40
+ # date.to_formatted_s(:rfc822) # => "10 Nov 2007"
16
41
  def to_formatted_s(format = :default)
17
- DATE_FORMATS[format] ? strftime(DATE_FORMATS[format]).strip : to_default_s
42
+ if formatter = DATE_FORMATS[format]
43
+ if formatter.respond_to?(:call)
44
+ formatter.call(self).to_s
45
+ else
46
+ strftime(formatter)
47
+ end
48
+ else
49
+ to_default_s
50
+ end
51
+ end
52
+
53
+ # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
54
+ def readable_inspect
55
+ strftime("%a, %d %b %Y")
18
56
  end
19
57
 
20
- # To be able to keep Dates and Times interchangeable on conversions
58
+ # A method to keep Time, Date and DateTime instances interchangeable on conversions.
59
+ # In this case, it simply returns +self+.
21
60
  def to_date
22
61
  self
23
- end
62
+ end if RUBY_VERSION < '1.9'
24
63
 
64
+ # Converts a Date instance to a Time, where the time is set to the beginning of the day.
65
+ # The timezone can be either :local or :utc (default :local).
66
+ #
67
+ # ==== Examples:
68
+ # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
69
+ #
70
+ # date.to_time # => Sat Nov 10 00:00:00 0800 2007
71
+ # date.to_time(:local) # => Sat Nov 10 00:00:00 0800 2007
72
+ #
73
+ # date.to_time(:utc) # => Sat Nov 10 00:00:00 UTC 2007
25
74
  def to_time(form = :local)
26
- if respond_to?(:hour)
27
- ::Time.send(form, year, month, day, hour, min, sec)
28
- else
29
- ::Time.send(form, year, month, day)
30
- end
75
+ ::Time.send("#{form}_time", year, month, day)
31
76
  end
32
77
 
78
+ # Converts a Date instance to a DateTime, where the time is set to the beginning of the day
79
+ # and UTC offset is set to 0.
80
+ #
81
+ # ==== Example:
82
+ # date = Date.new(2007, 11, 10) # => Sat, 10 Nov 2007
83
+ #
84
+ # date.to_datetime # => Sat, 10 Nov 2007 00:00:00 0000
85
+ def to_datetime
86
+ ::DateTime.civil(year, month, day, 0, 0, 0, 0)
87
+ end if RUBY_VERSION < '1.9'
88
+
33
89
  def xmlschema
34
90
  to_time.xmlschema
35
91
  end
@@ -0,0 +1,10 @@
1
+ require 'date'
2
+ require 'active_support/core_ext/time/behavior'
3
+ require 'active_support/core_ext/date_time/calculations'
4
+ require 'active_support/core_ext/date_time/conversions'
5
+
6
+ class DateTime
7
+ include ActiveSupport::CoreExtensions::Time::Behavior
8
+ include ActiveSupport::CoreExtensions::DateTime::Calculations
9
+ include ActiveSupport::CoreExtensions::DateTime::Conversions
10
+ end
@@ -0,0 +1,77 @@
1
+ require 'rational'
2
+
3
+ module ActiveSupport #:nodoc:
4
+ module CoreExtensions #:nodoc:
5
+ module DateTime #:nodoc:
6
+ # Enables the use of time calculations within DateTime itself
7
+ module Calculations
8
+ def self.included(base) #:nodoc:
9
+ base.extend ClassMethods
10
+ end
11
+
12
+ module ClassMethods
13
+ # DateTimes aren't aware of DST rules, so use a consistent non-DST offset when creating a DateTime with an offset in the local zone
14
+ def local_offset
15
+ ::Time.local(2007).utc_offset.to_r / 86400
16
+ end
17
+ end
18
+
19
+ # Seconds since midnight: DateTime.now.seconds_since_midnight
20
+ def seconds_since_midnight
21
+ self.sec + (self.min * 60) + (self.hour * 3600)
22
+ end
23
+
24
+ # Returns a new DateTime where one or more of the elements have been changed according to the +options+ parameter. The time options
25
+ # (hour, minute, sec) reset cascadingly, so if only the hour is passed, then minute and sec is set to 0. If the hour and
26
+ # minute is passed, then sec is set to 0.
27
+ def change(options)
28
+ ::DateTime.civil(
29
+ options[:year] || self.year,
30
+ options[:month] || self.month,
31
+ options[:day] || self.day,
32
+ options[:hour] || self.hour,
33
+ options[:min] || (options[:hour] ? 0 : self.min),
34
+ options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec),
35
+ options[:offset] || self.offset,
36
+ options[:start] || self.start
37
+ )
38
+ end
39
+
40
+ # Uses Date to provide precise Time calculations for years, months, and days. The +options+ parameter takes a hash with
41
+ # any of these keys: :years, :months, :weeks, :days, :hours, :minutes, :seconds.
42
+ def advance(options)
43
+ d = to_date.advance(options)
44
+ datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
45
+ seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600
46
+ seconds_to_advance == 0 ? datetime_advanced_by_date : datetime_advanced_by_date.since(seconds_to_advance)
47
+ end
48
+
49
+ # Returns a new DateTime representing the time a number of seconds ago
50
+ # Do not use this method in combination with x.months, use months_ago instead!
51
+ def ago(seconds)
52
+ self.since(-seconds)
53
+ end
54
+
55
+ # Returns a new DateTime representing the time a number of seconds since the instance time
56
+ # Do not use this method in combination with x.months, use months_since instead!
57
+ def since(seconds)
58
+ self + Rational(seconds.round, 86400)
59
+ end
60
+ alias :in :since
61
+
62
+ # Returns a new DateTime representing the start of the day (0:00)
63
+ def beginning_of_day
64
+ change(:hour => 0)
65
+ end
66
+ alias :midnight :beginning_of_day
67
+ alias :at_midnight :beginning_of_day
68
+ alias :at_beginning_of_day :beginning_of_day
69
+
70
+ # Returns a new DateTime representing the end of the day (23:59:59)
71
+ def end_of_day
72
+ change(:hour => 23, :min => 59, :sec => 59)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,54 @@
1
+ module ActiveSupport #:nodoc:
2
+ module CoreExtensions #:nodoc:
3
+ module DateTime #:nodoc:
4
+ # Getting datetimes in different convenient string representations and other objects
5
+ module Conversions
6
+ def self.included(base)
7
+ base.class_eval do
8
+ alias_method :to_datetime_default_s, :to_s
9
+ alias_method :to_s, :to_formatted_s
10
+ alias_method :default_inspect, :inspect
11
+ alias_method :inspect, :readable_inspect
12
+ end
13
+ end
14
+
15
+ def to_formatted_s(format = :default)
16
+ if formatter = ::Time::DATE_FORMATS[format]
17
+ if formatter.respond_to?(:call)
18
+ formatter.call(self).to_s
19
+ else
20
+ strftime(formatter)
21
+ end
22
+ else
23
+ to_datetime_default_s
24
+ end
25
+ end
26
+
27
+ # Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005 14:30:00 +0000"
28
+ def readable_inspect
29
+ to_s(:rfc822)
30
+ end
31
+
32
+ # Converts self to a Ruby Date object; time portion is discarded
33
+ def to_date
34
+ ::Date.new(year, month, day)
35
+ end
36
+
37
+ # Attempts to convert self to a Ruby Time object; returns self if out of range of Ruby Time class
38
+ # If self has an offset other than 0, self will just be returned unaltered, since there's no clean way to map it to a Time
39
+ def to_time
40
+ self.offset == 0 ? ::Time.utc_time(year, month, day, hour, min, sec) : self
41
+ end
42
+
43
+ # To be able to keep Times, Dates and DateTimes interchangeable on conversions
44
+ def to_datetime
45
+ self
46
+ end
47
+
48
+ def xmlschema
49
+ strftime("%Y-%m-%dT%H:%M:%S#{offset == 0 ? 'Z' : '%Z'}")
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end