core_ext 0.0.1

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.
Files changed (175) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +3 -0
  3. data/lib/core_ext/array/access.rb +76 -0
  4. data/lib/core_ext/array/conversions.rb +211 -0
  5. data/lib/core_ext/array/extract_options.rb +29 -0
  6. data/lib/core_ext/array/grouping.rb +116 -0
  7. data/lib/core_ext/array/inquiry.rb +17 -0
  8. data/lib/core_ext/array/prepend_and_append.rb +7 -0
  9. data/lib/core_ext/array/wrap.rb +46 -0
  10. data/lib/core_ext/array.rb +7 -0
  11. data/lib/core_ext/array_inquirer.rb +44 -0
  12. data/lib/core_ext/benchmark.rb +14 -0
  13. data/lib/core_ext/benchmarkable.rb +49 -0
  14. data/lib/core_ext/big_decimal/conversions.rb +14 -0
  15. data/lib/core_ext/big_decimal.rb +1 -0
  16. data/lib/core_ext/builder.rb +6 -0
  17. data/lib/core_ext/callbacks.rb +770 -0
  18. data/lib/core_ext/class/attribute.rb +128 -0
  19. data/lib/core_ext/class/attribute_accessors.rb +4 -0
  20. data/lib/core_ext/class/subclasses.rb +42 -0
  21. data/lib/core_ext/class.rb +2 -0
  22. data/lib/core_ext/concern.rb +142 -0
  23. data/lib/core_ext/configurable.rb +148 -0
  24. data/lib/core_ext/date/acts_like.rb +8 -0
  25. data/lib/core_ext/date/blank.rb +12 -0
  26. data/lib/core_ext/date/calculations.rb +143 -0
  27. data/lib/core_ext/date/conversions.rb +93 -0
  28. data/lib/core_ext/date/zones.rb +6 -0
  29. data/lib/core_ext/date.rb +5 -0
  30. data/lib/core_ext/date_and_time/calculations.rb +328 -0
  31. data/lib/core_ext/date_and_time/zones.rb +40 -0
  32. data/lib/core_ext/date_time/acts_like.rb +14 -0
  33. data/lib/core_ext/date_time/blank.rb +12 -0
  34. data/lib/core_ext/date_time/calculations.rb +177 -0
  35. data/lib/core_ext/date_time/conversions.rb +104 -0
  36. data/lib/core_ext/date_time/zones.rb +6 -0
  37. data/lib/core_ext/date_time.rb +5 -0
  38. data/lib/core_ext/deprecation/behaviors.rb +86 -0
  39. data/lib/core_ext/deprecation/instance_delegator.rb +24 -0
  40. data/lib/core_ext/deprecation/method_wrappers.rb +70 -0
  41. data/lib/core_ext/deprecation/proxy_wrappers.rb +149 -0
  42. data/lib/core_ext/deprecation/reporting.rb +105 -0
  43. data/lib/core_ext/deprecation.rb +43 -0
  44. data/lib/core_ext/digest/uuid.rb +51 -0
  45. data/lib/core_ext/duration.rb +157 -0
  46. data/lib/core_ext/enumerable.rb +106 -0
  47. data/lib/core_ext/file/atomic.rb +68 -0
  48. data/lib/core_ext/file.rb +1 -0
  49. data/lib/core_ext/hash/compact.rb +20 -0
  50. data/lib/core_ext/hash/conversions.rb +261 -0
  51. data/lib/core_ext/hash/deep_merge.rb +38 -0
  52. data/lib/core_ext/hash/except.rb +22 -0
  53. data/lib/core_ext/hash/indifferent_access.rb +23 -0
  54. data/lib/core_ext/hash/keys.rb +170 -0
  55. data/lib/core_ext/hash/reverse_merge.rb +22 -0
  56. data/lib/core_ext/hash/slice.rb +48 -0
  57. data/lib/core_ext/hash/transform_values.rb +29 -0
  58. data/lib/core_ext/hash.rb +9 -0
  59. data/lib/core_ext/hash_with_indifferent_access.rb +298 -0
  60. data/lib/core_ext/inflections.rb +70 -0
  61. data/lib/core_ext/inflector/inflections.rb +244 -0
  62. data/lib/core_ext/inflector/methods.rb +381 -0
  63. data/lib/core_ext/inflector/transliterate.rb +112 -0
  64. data/lib/core_ext/inflector.rb +7 -0
  65. data/lib/core_ext/integer/inflections.rb +29 -0
  66. data/lib/core_ext/integer/multiple.rb +10 -0
  67. data/lib/core_ext/integer/time.rb +29 -0
  68. data/lib/core_ext/integer.rb +3 -0
  69. data/lib/core_ext/json/decoding.rb +67 -0
  70. data/lib/core_ext/json/encoding.rb +127 -0
  71. data/lib/core_ext/json.rb +2 -0
  72. data/lib/core_ext/kernel/agnostics.rb +11 -0
  73. data/lib/core_ext/kernel/concern.rb +10 -0
  74. data/lib/core_ext/kernel/reporting.rb +41 -0
  75. data/lib/core_ext/kernel/singleton_class.rb +6 -0
  76. data/lib/core_ext/kernel.rb +4 -0
  77. data/lib/core_ext/load_error.rb +30 -0
  78. data/lib/core_ext/logger.rb +57 -0
  79. data/lib/core_ext/logger_silence.rb +24 -0
  80. data/lib/core_ext/marshal.rb +19 -0
  81. data/lib/core_ext/module/aliasing.rb +74 -0
  82. data/lib/core_ext/module/anonymous.rb +28 -0
  83. data/lib/core_ext/module/attr_internal.rb +36 -0
  84. data/lib/core_ext/module/attribute_accessors.rb +212 -0
  85. data/lib/core_ext/module/concerning.rb +135 -0
  86. data/lib/core_ext/module/delegation.rb +218 -0
  87. data/lib/core_ext/module/deprecation.rb +23 -0
  88. data/lib/core_ext/module/introspection.rb +62 -0
  89. data/lib/core_ext/module/method_transplanting.rb +3 -0
  90. data/lib/core_ext/module/qualified_const.rb +52 -0
  91. data/lib/core_ext/module/reachable.rb +8 -0
  92. data/lib/core_ext/module/remove_method.rb +35 -0
  93. data/lib/core_ext/module.rb +11 -0
  94. data/lib/core_ext/multibyte/chars.rb +231 -0
  95. data/lib/core_ext/multibyte/unicode.rb +388 -0
  96. data/lib/core_ext/multibyte.rb +21 -0
  97. data/lib/core_ext/name_error.rb +31 -0
  98. data/lib/core_ext/numeric/bytes.rb +64 -0
  99. data/lib/core_ext/numeric/conversions.rb +132 -0
  100. data/lib/core_ext/numeric/inquiry.rb +26 -0
  101. data/lib/core_ext/numeric/time.rb +74 -0
  102. data/lib/core_ext/numeric.rb +4 -0
  103. data/lib/core_ext/object/acts_like.rb +10 -0
  104. data/lib/core_ext/object/blank.rb +140 -0
  105. data/lib/core_ext/object/conversions.rb +4 -0
  106. data/lib/core_ext/object/deep_dup.rb +53 -0
  107. data/lib/core_ext/object/duplicable.rb +98 -0
  108. data/lib/core_ext/object/inclusion.rb +27 -0
  109. data/lib/core_ext/object/instance_variables.rb +28 -0
  110. data/lib/core_ext/object/json.rb +199 -0
  111. data/lib/core_ext/object/to_param.rb +1 -0
  112. data/lib/core_ext/object/to_query.rb +84 -0
  113. data/lib/core_ext/object/try.rb +146 -0
  114. data/lib/core_ext/object/with_options.rb +69 -0
  115. data/lib/core_ext/object.rb +14 -0
  116. data/lib/core_ext/option_merger.rb +25 -0
  117. data/lib/core_ext/ordered_hash.rb +48 -0
  118. data/lib/core_ext/ordered_options.rb +81 -0
  119. data/lib/core_ext/range/conversions.rb +34 -0
  120. data/lib/core_ext/range/each.rb +21 -0
  121. data/lib/core_ext/range/include_range.rb +23 -0
  122. data/lib/core_ext/range/overlaps.rb +8 -0
  123. data/lib/core_ext/range.rb +4 -0
  124. data/lib/core_ext/regexp.rb +5 -0
  125. data/lib/core_ext/rescuable.rb +119 -0
  126. data/lib/core_ext/securerandom.rb +23 -0
  127. data/lib/core_ext/security_utils.rb +20 -0
  128. data/lib/core_ext/string/access.rb +104 -0
  129. data/lib/core_ext/string/behavior.rb +6 -0
  130. data/lib/core_ext/string/conversions.rb +56 -0
  131. data/lib/core_ext/string/exclude.rb +11 -0
  132. data/lib/core_ext/string/filters.rb +102 -0
  133. data/lib/core_ext/string/indent.rb +43 -0
  134. data/lib/core_ext/string/inflections.rb +235 -0
  135. data/lib/core_ext/string/inquiry.rb +13 -0
  136. data/lib/core_ext/string/multibyte.rb +53 -0
  137. data/lib/core_ext/string/output_safety.rb +261 -0
  138. data/lib/core_ext/string/starts_ends_with.rb +4 -0
  139. data/lib/core_ext/string/strip.rb +23 -0
  140. data/lib/core_ext/string/zones.rb +14 -0
  141. data/lib/core_ext/string.rb +13 -0
  142. data/lib/core_ext/string_inquirer.rb +26 -0
  143. data/lib/core_ext/tagged_logging.rb +78 -0
  144. data/lib/core_ext/test_case.rb +88 -0
  145. data/lib/core_ext/testing/assertions.rb +99 -0
  146. data/lib/core_ext/testing/autorun.rb +12 -0
  147. data/lib/core_ext/testing/composite_filter.rb +54 -0
  148. data/lib/core_ext/testing/constant_lookup.rb +50 -0
  149. data/lib/core_ext/testing/declarative.rb +26 -0
  150. data/lib/core_ext/testing/deprecation.rb +36 -0
  151. data/lib/core_ext/testing/file_fixtures.rb +34 -0
  152. data/lib/core_ext/testing/isolation.rb +115 -0
  153. data/lib/core_ext/testing/method_call_assertions.rb +41 -0
  154. data/lib/core_ext/testing/setup_and_teardown.rb +50 -0
  155. data/lib/core_ext/testing/stream.rb +42 -0
  156. data/lib/core_ext/testing/tagged_logging.rb +25 -0
  157. data/lib/core_ext/testing/time_helpers.rb +134 -0
  158. data/lib/core_ext/time/acts_like.rb +8 -0
  159. data/lib/core_ext/time/calculations.rb +284 -0
  160. data/lib/core_ext/time/conversions.rb +66 -0
  161. data/lib/core_ext/time/zones.rb +95 -0
  162. data/lib/core_ext/time.rb +20 -0
  163. data/lib/core_ext/time_with_zone.rb +503 -0
  164. data/lib/core_ext/time_zone.rb +464 -0
  165. data/lib/core_ext/uri.rb +25 -0
  166. data/lib/core_ext/version.rb +3 -0
  167. data/lib/core_ext/xml_mini/jdom.rb +181 -0
  168. data/lib/core_ext/xml_mini/libxml.rb +79 -0
  169. data/lib/core_ext/xml_mini/libxmlsax.rb +85 -0
  170. data/lib/core_ext/xml_mini/nokogiri.rb +83 -0
  171. data/lib/core_ext/xml_mini/nokogirisax.rb +87 -0
  172. data/lib/core_ext/xml_mini/rexml.rb +130 -0
  173. data/lib/core_ext/xml_mini.rb +194 -0
  174. data/lib/core_ext.rb +3 -0
  175. metadata +310 -0
@@ -0,0 +1,284 @@
1
+ require 'core_ext/duration'
2
+ require 'core_ext/time/conversions'
3
+ require 'core_ext/time_with_zone'
4
+ require 'core_ext/time/zones'
5
+ require 'core_ext/date_and_time/calculations'
6
+ require 'core_ext/date/calculations'
7
+
8
+ class Time
9
+ include DateAndTime::Calculations
10
+
11
+ COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
12
+
13
+ class << self
14
+ # Overriding case equality method so that it returns true for CoreExt::TimeWithZone instances
15
+ def ===(other)
16
+ super || (self == Time && other.is_a?(CoreExt::TimeWithZone))
17
+ end
18
+
19
+ # Returns the number of days in the given month.
20
+ # If no year is specified, it will use the current year.
21
+ def days_in_month(month, year = current.year)
22
+ if month == 2 && ::Date.gregorian_leap?(year)
23
+ 29
24
+ else
25
+ COMMON_YEAR_DAYS_IN_MONTH[month]
26
+ end
27
+ end
28
+
29
+ # Returns the number of days in the given year.
30
+ # If no year is specified, it will use the current year.
31
+ def days_in_year(year = current.year)
32
+ days_in_month(2, year) + 337
33
+ end
34
+
35
+ # Returns <tt>Time.zone.now</tt> when <tt>Time.zone</tt> or <tt>config.time_zone</tt> are set, otherwise just returns <tt>Time.now</tt>.
36
+ def current
37
+ ::Time.zone ? ::Time.zone.now : ::Time.now
38
+ end
39
+
40
+ # Layers additional behavior on Time.at so that CoreExt::TimeWithZone and DateTime
41
+ # instances can be used when called with a single argument
42
+ def at_with_coercion(*args)
43
+ return at_without_coercion(*args) if args.size != 1
44
+
45
+ # Time.at can be called with a time or numerical value
46
+ time_or_number = args.first
47
+
48
+ if time_or_number.is_a?(CoreExt::TimeWithZone) || time_or_number.is_a?(DateTime)
49
+ at_without_coercion(time_or_number.to_f).getlocal
50
+ else
51
+ at_without_coercion(time_or_number)
52
+ end
53
+ end
54
+ alias_method :at_without_coercion, :at
55
+ alias_method :at, :at_with_coercion
56
+ end
57
+
58
+ # Returns the number of seconds since 00:00:00.
59
+ #
60
+ # Time.new(2012, 8, 29, 0, 0, 0).seconds_since_midnight # => 0.0
61
+ # Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296.0
62
+ # Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399.0
63
+ def seconds_since_midnight
64
+ to_i - change(:hour => 0).to_i + (usec / 1.0e+6)
65
+ end
66
+
67
+ # Returns the number of seconds until 23:59:59.
68
+ #
69
+ # Time.new(2012, 8, 29, 0, 0, 0).seconds_until_end_of_day # => 86399
70
+ # Time.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
71
+ # Time.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
72
+ def seconds_until_end_of_day
73
+ end_of_day.to_i - to_i
74
+ end
75
+
76
+ # Returns a new Time where one or more of the elements have been changed according
77
+ # to the +options+ parameter. The time options (<tt>:hour</tt>, <tt>:min</tt>,
78
+ # <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly, so if only
79
+ # the hour is passed, then minute, sec, usec and nsec is set to 0. If the hour
80
+ # and minute is passed, then sec, usec and nsec is set to 0. The +options+
81
+ # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
82
+ # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>
83
+ # <tt>:nsec</tt>. Pass either <tt>:usec</tt> or <tt>:nsec</tt>, not both.
84
+ #
85
+ # Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0)
86
+ # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0)
87
+ # Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
88
+ def change(options)
89
+ new_year = options.fetch(:year, year)
90
+ new_month = options.fetch(:month, month)
91
+ new_day = options.fetch(:day, day)
92
+ new_hour = options.fetch(:hour, hour)
93
+ new_min = options.fetch(:min, options[:hour] ? 0 : min)
94
+ new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
95
+
96
+ if new_nsec = options[:nsec]
97
+ raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
98
+ new_usec = Rational(new_nsec, 1000)
99
+ else
100
+ new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
101
+ end
102
+
103
+ if utc?
104
+ ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
105
+ elsif zone
106
+ ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
107
+ else
108
+ raise ArgumentError, 'argument out of range' if new_usec >= 1000000
109
+ ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
110
+ end
111
+ end
112
+
113
+ # Uses Date to provide precise Time calculations for years, months, and days
114
+ # according to the proleptic Gregorian calendar. The +options+ parameter
115
+ # takes a hash with any of these keys: <tt>:years</tt>, <tt>:months</tt>,
116
+ # <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>, <tt>:minutes</tt>,
117
+ # <tt>:seconds</tt>.
118
+ #
119
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(seconds: 1) # => 2015-08-01 14:35:01 -0700
120
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(minutes: 1) # => 2015-08-01 14:36:00 -0700
121
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(hours: 1) # => 2015-08-01 15:35:00 -0700
122
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(days: 1) # => 2015-08-02 14:35:00 -0700
123
+ # Time.new(2015, 8, 1, 14, 35, 0).advance(weeks: 1) # => 2015-08-08 14:35:00 -0700
124
+ def advance(options)
125
+ unless options[:weeks].nil?
126
+ options[:weeks], partial_weeks = options[:weeks].divmod(1)
127
+ options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
128
+ end
129
+
130
+ unless options[:days].nil?
131
+ options[:days], partial_days = options[:days].divmod(1)
132
+ options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
133
+ end
134
+
135
+ d = to_date.advance(options)
136
+ d = d.gregorian if d.julian?
137
+ time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
138
+ seconds_to_advance = \
139
+ options.fetch(:seconds, 0) +
140
+ options.fetch(:minutes, 0) * 60 +
141
+ options.fetch(:hours, 0) * 3600
142
+
143
+ if seconds_to_advance.zero?
144
+ time_advanced_by_date
145
+ else
146
+ time_advanced_by_date.since(seconds_to_advance)
147
+ end
148
+ end
149
+
150
+ # Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
151
+ def ago(seconds)
152
+ since(-seconds)
153
+ end
154
+
155
+ # Returns a new Time representing the time a number of seconds since the instance time
156
+ def since(seconds)
157
+ self + seconds
158
+ rescue
159
+ to_datetime.since(seconds)
160
+ end
161
+ alias :in :since
162
+
163
+ # Returns a new Time representing the start of the day (0:00)
164
+ def beginning_of_day
165
+ #(self - seconds_since_midnight).change(usec: 0)
166
+ change(:hour => 0)
167
+ end
168
+ alias :midnight :beginning_of_day
169
+ alias :at_midnight :beginning_of_day
170
+ alias :at_beginning_of_day :beginning_of_day
171
+
172
+ # Returns a new Time representing the middle of the day (12:00)
173
+ def middle_of_day
174
+ change(:hour => 12)
175
+ end
176
+ alias :midday :middle_of_day
177
+ alias :noon :middle_of_day
178
+ alias :at_midday :middle_of_day
179
+ alias :at_noon :middle_of_day
180
+ alias :at_middle_of_day :middle_of_day
181
+
182
+ # Returns a new Time representing the end of the day, 23:59:59.999999
183
+ def end_of_day
184
+ change(
185
+ :hour => 23,
186
+ :min => 59,
187
+ :sec => 59,
188
+ :usec => Rational(999999999, 1000)
189
+ )
190
+ end
191
+ alias :at_end_of_day :end_of_day
192
+
193
+ # Returns a new Time representing the start of the hour (x:00)
194
+ def beginning_of_hour
195
+ change(:min => 0)
196
+ end
197
+ alias :at_beginning_of_hour :beginning_of_hour
198
+
199
+ # Returns a new Time representing the end of the hour, x:59:59.999999
200
+ def end_of_hour
201
+ change(
202
+ :min => 59,
203
+ :sec => 59,
204
+ :usec => Rational(999999999, 1000)
205
+ )
206
+ end
207
+ alias :at_end_of_hour :end_of_hour
208
+
209
+ # Returns a new Time representing the start of the minute (x:xx:00)
210
+ def beginning_of_minute
211
+ change(:sec => 0)
212
+ end
213
+ alias :at_beginning_of_minute :beginning_of_minute
214
+
215
+ # Returns a new Time representing the end of the minute, x:xx:59.999999
216
+ def end_of_minute
217
+ change(
218
+ :sec => 59,
219
+ :usec => Rational(999999999, 1000)
220
+ )
221
+ end
222
+ alias :at_end_of_minute :end_of_minute
223
+
224
+ # Returns a Range representing the whole day of the current time.
225
+ def all_day
226
+ beginning_of_day..end_of_day
227
+ end
228
+
229
+ def plus_with_duration(other) #:nodoc:
230
+ if CoreExt::Duration === other
231
+ other.since(self)
232
+ else
233
+ plus_without_duration(other)
234
+ end
235
+ end
236
+ alias_method :plus_without_duration, :+
237
+ alias_method :+, :plus_with_duration
238
+
239
+ def minus_with_duration(other) #:nodoc:
240
+ if CoreExt::Duration === other
241
+ other.until(self)
242
+ else
243
+ minus_without_duration(other)
244
+ end
245
+ end
246
+ alias_method :minus_without_duration, :-
247
+ alias_method :-, :minus_with_duration
248
+
249
+ # Time#- can also be used to determine the number of seconds between two Time instances.
250
+ # We're layering on additional behavior so that CoreExt::TimeWithZone instances
251
+ # are coerced into values that Time#- will recognize
252
+ def minus_with_coercion(other)
253
+ other = other.comparable_time if other.respond_to?(:comparable_time)
254
+ other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other)
255
+ end
256
+ alias_method :minus_without_coercion, :-
257
+ alias_method :-, :minus_with_coercion
258
+
259
+ # Layers additional behavior on Time#<=> so that DateTime and CoreExt::TimeWithZone instances
260
+ # can be chronologically compared with a Time
261
+ def compare_with_coercion(other)
262
+ # we're avoiding Time#to_datetime and Time#to_time because they're expensive
263
+ if other.class == Time
264
+ compare_without_coercion(other)
265
+ elsif other.is_a?(Time)
266
+ compare_without_coercion(other.to_time)
267
+ else
268
+ to_datetime <=> other
269
+ end
270
+ end
271
+ alias_method :compare_without_coercion, :<=>
272
+ alias_method :<=>, :compare_with_coercion
273
+
274
+ # Layers additional behavior on Time#eql? so that CoreExt::TimeWithZone instances
275
+ # can be eql? to an equivalent Time
276
+ def eql_with_coercion(other)
277
+ # if other is an CoreExt::TimeWithZone, coerce a Time instance from it so we can do eql? comparison
278
+ other = other.comparable_time if other.respond_to?(:comparable_time)
279
+ eql_without_coercion(other)
280
+ end
281
+ alias_method :eql_without_coercion, :eql?
282
+ alias_method :eql?, :eql_with_coercion
283
+
284
+ end
@@ -0,0 +1,66 @@
1
+ require 'core_ext/time_zone'
2
+
3
+ class Time
4
+ DATE_FORMATS = {
5
+ :db => '%Y-%m-%d %H:%M:%S',
6
+ :number => '%Y%m%d%H%M%S',
7
+ :nsec => '%Y%m%d%H%M%S%9N',
8
+ :usec => '%Y%m%d%H%M%S%6N',
9
+ :time => '%H:%M',
10
+ :short => '%d %b %H:%M',
11
+ :long => '%B %d, %Y %H:%M',
12
+ :long_ordinal => lambda { |time|
13
+ day_format = CoreExt::Inflector.ordinalize(time.day)
14
+ time.strftime("%B #{day_format}, %Y %H:%M")
15
+ },
16
+ :rfc822 => lambda { |time|
17
+ offset_format = time.formatted_offset(false)
18
+ time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}")
19
+ },
20
+ :iso8601 => lambda { |time| time.iso8601 }
21
+ }
22
+
23
+ # Converts to a formatted string. See DATE_FORMATS for built-in formats.
24
+ #
25
+ # This method is aliased to <tt>to_s</tt>.
26
+ #
27
+ # time = Time.now # => 2007-01-18 06:10:17 -06:00
28
+ #
29
+ # time.to_formatted_s(:time) # => "06:10"
30
+ # time.to_s(:time) # => "06:10"
31
+ #
32
+ # time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
33
+ # time.to_formatted_s(:number) # => "20070118061017"
34
+ # time.to_formatted_s(:short) # => "18 Jan 06:10"
35
+ # time.to_formatted_s(:long) # => "January 18, 2007 06:10"
36
+ # time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
37
+ # time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
38
+ # time.to_formatted_s(:iso8601) # => "2007-01-18T06:10:17-06:00"
39
+ #
40
+ # == Adding your own time formats to +to_formatted_s+
41
+ # You can add your own formats to the Time::DATE_FORMATS hash.
42
+ # Use the format name as the hash key and either a strftime string
43
+ # or Proc instance that takes a time argument as the value.
44
+ #
45
+ # # config/initializers/time_formats.rb
46
+ # Time::DATE_FORMATS[:month_and_year] = '%B %Y'
47
+ # Time::DATE_FORMATS[:short_ordinal] = ->(time) { time.strftime("%B #{time.day.ordinalize}") }
48
+ def to_formatted_s(format = :default)
49
+ if formatter = DATE_FORMATS[format]
50
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
51
+ else
52
+ to_default_s
53
+ end
54
+ end
55
+ alias_method :to_default_s, :to_s
56
+ alias_method :to_s, :to_formatted_s
57
+
58
+ # Returns a formatted string of the offset from UTC, or an alternative
59
+ # string if the time zone is already UTC.
60
+ #
61
+ # Time.local(2000).formatted_offset # => "-06:00"
62
+ # Time.local(2000).formatted_offset(false) # => "-0600"
63
+ def formatted_offset(colon = true, alternate_utc_string = nil)
64
+ utc? && alternate_utc_string || CoreExt::TimeZone.seconds_to_utc_offset(utc_offset, colon)
65
+ end
66
+ end
@@ -0,0 +1,95 @@
1
+ require 'core_ext/time_with_zone'
2
+ require 'core_ext/time/acts_like'
3
+ require 'core_ext/date_and_time/zones'
4
+
5
+ class Time
6
+ include DateAndTime::Zones
7
+ class << self
8
+ attr_accessor :zone_default
9
+
10
+ # Returns the TimeZone for the current request, if this has been set (via Time.zone=).
11
+ # If <tt>Time.zone</tt> has not been set for the current request, returns the TimeZone specified in <tt>config.time_zone</tt>.
12
+ def zone
13
+ Thread.current[:time_zone] || zone_default
14
+ end
15
+
16
+ # Sets <tt>Time.zone</tt> to a TimeZone object for the current request/thread.
17
+ #
18
+ # This method accepts any of the following:
19
+ #
20
+ # * A Rails TimeZone object.
21
+ # * An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", <tt>-5.hours</tt>).
22
+ # * A TZInfo::Timezone object.
23
+ # * An identifier for a TZInfo::Timezone object (e.g., "America/New_York").
24
+ #
25
+ # Here's an example of how you might set <tt>Time.zone</tt> on a per request basis and reset it when the request is done.
26
+ # <tt>current_user.time_zone</tt> just needs to return a string identifying the user's preferred time zone:
27
+ #
28
+ # class ApplicationController < ActionController::Base
29
+ # around_action :set_time_zone
30
+ #
31
+ # def set_time_zone
32
+ # if logged_in?
33
+ # Time.use_zone(current_user.time_zone) { yield }
34
+ # else
35
+ # yield
36
+ # end
37
+ # end
38
+ # end
39
+ def zone=(time_zone)
40
+ Thread.current[:time_zone] = find_zone!(time_zone)
41
+ end
42
+
43
+ # Allows override of <tt>Time.zone</tt> locally inside supplied block; resets <tt>Time.zone</tt> to existing value when done.
44
+ def use_zone(time_zone)
45
+ new_zone = find_zone!(time_zone)
46
+ begin
47
+ old_zone, ::Time.zone = ::Time.zone, new_zone
48
+ yield
49
+ ensure
50
+ ::Time.zone = old_zone
51
+ end
52
+ end
53
+
54
+ # Returns a TimeZone instance matching the time zone provided.
55
+ # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
56
+ # Raises an +ArgumentError+ for invalid time zones.
57
+ #
58
+ # Time.find_zone! "America/New_York" # => #<CoreExt::TimeZone @name="America/New_York" ...>
59
+ # Time.find_zone! "EST" # => #<CoreExt::TimeZone @name="EST" ...>
60
+ # Time.find_zone! -5.hours # => #<CoreExt::TimeZone @name="Bogota" ...>
61
+ # Time.find_zone! nil # => nil
62
+ # Time.find_zone! false # => false
63
+ # Time.find_zone! "NOT-A-TIMEZONE" # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
64
+ def find_zone!(time_zone)
65
+ if !time_zone || time_zone.is_a?(CoreExt::TimeZone)
66
+ time_zone
67
+ else
68
+ # Look up the timezone based on the identifier (unless we've been
69
+ # passed a TZInfo::Timezone)
70
+ unless time_zone.respond_to?(:period_for_local)
71
+ time_zone = CoreExt::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
72
+ end
73
+
74
+ # Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
75
+ if time_zone.is_a?(CoreExt::TimeZone)
76
+ time_zone
77
+ else
78
+ CoreExt::TimeZone.create(time_zone.name, nil, time_zone)
79
+ end
80
+ end
81
+ rescue TZInfo::InvalidTimezoneIdentifier
82
+ raise ArgumentError, "Invalid Timezone: #{time_zone}"
83
+ end
84
+
85
+ # Returns a TimeZone instance matching the time zone provided.
86
+ # Accepts the time zone in any format supported by <tt>Time.zone=</tt>.
87
+ # Returns +nil+ for invalid time zones.
88
+ #
89
+ # Time.find_zone "America/New_York" # => #<CoreExt::TimeZone @name="America/New_York" ...>
90
+ # Time.find_zone "NOT-A-TIMEZONE" # => nil
91
+ def find_zone(time_zone)
92
+ find_zone!(time_zone) rescue nil
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,20 @@
1
+ require 'date'
2
+ require 'time'
3
+
4
+ require 'core_ext/duration'
5
+ require 'core_ext/time_with_zone'
6
+ require 'core_ext/time_zone'
7
+
8
+ require 'core_ext/time/acts_like.rb'
9
+ require 'core_ext/time/calculations.rb'
10
+ require 'core_ext/time/conversions.rb'
11
+ require 'core_ext/time/zones.rb'
12
+
13
+ require 'core_ext/date'
14
+ require 'core_ext/date_time'
15
+
16
+ require 'core_ext/integer/time'
17
+ require 'core_ext/numeric/time'
18
+
19
+ require 'core_ext/string/conversions'
20
+ require 'core_ext/string/zones'