activesupport 2.0.5 → 2.1.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 (236) hide show
  1. data/CHANGELOG +183 -5
  2. data/lib/active_support.rb +6 -2
  3. data/lib/active_support/base64.rb +5 -0
  4. data/lib/active_support/basic_object.rb +23 -4
  5. data/lib/active_support/buffered_logger.rb +17 -3
  6. data/lib/active_support/cache.rb +145 -0
  7. data/lib/active_support/cache/compressed_mem_cache_store.rb +15 -0
  8. data/lib/active_support/cache/drb_store.rb +15 -0
  9. data/lib/active_support/cache/file_store.rb +70 -0
  10. data/lib/active_support/cache/mem_cache_store.rb +100 -0
  11. data/lib/active_support/cache/memory_store.rb +38 -0
  12. data/lib/active_support/callbacks.rb +275 -0
  13. data/lib/active_support/core_ext/array/access.rb +2 -4
  14. data/lib/active_support/core_ext/array/conversions.rb +89 -5
  15. data/lib/active_support/core_ext/array/extract_options.rb +2 -1
  16. data/lib/active_support/core_ext/array/grouping.rb +3 -8
  17. data/lib/active_support/core_ext/array/random_access.rb +1 -1
  18. data/lib/active_support/core_ext/base64.rb +4 -0
  19. data/lib/active_support/core_ext/base64/encoding.rb +13 -0
  20. data/lib/active_support/core_ext/benchmark.rb +12 -0
  21. data/lib/active_support/core_ext/bigdecimal.rb +4 -0
  22. data/lib/active_support/core_ext/bigdecimal/conversions.rb +39 -4
  23. data/lib/active_support/core_ext/blank.rb +5 -2
  24. data/lib/active_support/core_ext/class/attribute_accessors.rb +7 -1
  25. data/lib/active_support/core_ext/class/delegating_attributes.rb +7 -1
  26. data/lib/active_support/core_ext/class/inheritable_attributes.rb +1 -1
  27. data/lib/active_support/core_ext/class/removal.rb +26 -0
  28. data/lib/active_support/core_ext/date/calculations.rb +28 -1
  29. data/lib/active_support/core_ext/date/conversions.rb +1 -0
  30. data/lib/active_support/core_ext/date_time.rb +2 -0
  31. data/lib/active_support/core_ext/date_time/calculations.rb +37 -2
  32. data/lib/active_support/core_ext/date_time/conversions.rb +27 -14
  33. data/lib/active_support/core_ext/enumerable.rb +16 -9
  34. data/lib/active_support/core_ext/exception.rb +8 -0
  35. data/lib/active_support/core_ext/file.rb +6 -6
  36. data/lib/active_support/core_ext/hash/conversions.rb +26 -8
  37. data/lib/active_support/core_ext/hash/indifferent_access.rb +35 -0
  38. data/lib/active_support/core_ext/hash/reverse_merge.rb +4 -1
  39. data/lib/active_support/core_ext/integer/even_odd.rb +10 -5
  40. data/lib/active_support/core_ext/integer/inflections.rb +0 -1
  41. data/lib/active_support/core_ext/kernel/daemonizing.rb +2 -10
  42. data/lib/active_support/core_ext/kernel/reporting.rb +8 -0
  43. data/lib/active_support/core_ext/module/attr_internal.rb +4 -3
  44. data/lib/active_support/core_ext/module/attribute_accessors.rb +11 -1
  45. data/lib/active_support/core_ext/module/delegation.rb +5 -3
  46. data/lib/active_support/core_ext/module/inclusion.rb +19 -0
  47. data/lib/active_support/core_ext/module/introspection.rb +50 -16
  48. data/lib/active_support/core_ext/module/loading.rb +10 -0
  49. data/lib/active_support/core_ext/numeric.rb +3 -1
  50. data/lib/active_support/core_ext/numeric/conversions.rb +19 -0
  51. data/lib/active_support/core_ext/object/instance_variables.rb +52 -0
  52. data/lib/active_support/core_ext/object/misc.rb +1 -1
  53. data/lib/active_support/core_ext/process.rb +1 -0
  54. data/lib/active_support/core_ext/process/daemon.rb +25 -0
  55. data/lib/active_support/core_ext/range/conversions.rb +5 -1
  56. data/lib/active_support/core_ext/range/include_range.rb +8 -0
  57. data/lib/active_support/core_ext/range/overlaps.rb +3 -0
  58. data/lib/active_support/core_ext/string.rb +5 -10
  59. data/lib/active_support/core_ext/string/access.rb +72 -48
  60. data/lib/active_support/core_ext/string/conversions.rb +4 -4
  61. data/lib/active_support/core_ext/string/filters.rb +26 -0
  62. data/lib/active_support/core_ext/string/inflections.rb +56 -64
  63. data/lib/active_support/core_ext/string/iterators.rb +4 -0
  64. data/lib/active_support/core_ext/string/starts_ends_with.rb +12 -4
  65. data/lib/active_support/core_ext/string/unicode.rb +14 -7
  66. data/lib/active_support/core_ext/symbol.rb +1 -1
  67. data/lib/active_support/core_ext/time.rb +2 -0
  68. data/lib/active_support/core_ext/time/calculations.rb +75 -23
  69. data/lib/active_support/core_ext/time/conversions.rb +22 -35
  70. data/lib/active_support/core_ext/time/zones.rb +86 -0
  71. data/lib/active_support/dependencies.rb +92 -80
  72. data/lib/active_support/deprecation.rb +2 -16
  73. data/lib/active_support/duration.rb +4 -4
  74. data/lib/active_support/gzip.rb +25 -0
  75. data/lib/active_support/inflector.rb +92 -69
  76. data/lib/active_support/json.rb +17 -25
  77. data/lib/active_support/json/decoding.rb +1 -1
  78. data/lib/active_support/json/encoders/date.rb +11 -2
  79. data/lib/active_support/json/encoders/date_time.rb +11 -2
  80. data/lib/active_support/json/encoders/enumerable.rb +2 -2
  81. data/lib/active_support/json/encoders/hash.rb +3 -6
  82. data/lib/active_support/json/encoders/object.rb +1 -1
  83. data/lib/active_support/json/encoders/string.rb +8 -2
  84. data/lib/active_support/json/encoders/time.rb +11 -2
  85. data/lib/active_support/json/encoding.rb +0 -1
  86. data/lib/active_support/multibyte/chars.rb +8 -6
  87. data/lib/active_support/multibyte/handlers/utf8_handler.rb +11 -11
  88. data/lib/active_support/ordered_hash.rb +43 -0
  89. data/lib/active_support/ordered_options.rb +0 -38
  90. data/lib/active_support/test_case.rb +10 -2
  91. data/lib/active_support/testing/default.rb +3 -6
  92. data/lib/active_support/testing/setup_and_teardown.rb +93 -0
  93. data/lib/active_support/time_with_zone.rb +283 -0
  94. data/lib/active_support/values/time_zone.rb +336 -123
  95. data/lib/active_support/vendor.rb +12 -0
  96. data/lib/active_support/vendor/memcache-client-1.5.0/memcache.rb +849 -0
  97. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo.rb +33 -0
  98. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/data_timezone.rb +47 -0
  99. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/data_timezone_info.rb +226 -0
  100. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Africa/Algiers.rb +55 -0
  101. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Africa/Cairo.rb +219 -0
  102. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Africa/Casablanca.rb +38 -0
  103. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Africa/Harare.rb +18 -0
  104. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Africa/Johannesburg.rb +25 -0
  105. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Africa/Monrovia.rb +22 -0
  106. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Africa/Nairobi.rb +23 -0
  107. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Argentina/Buenos_Aires.rb +166 -0
  108. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Argentina/San_Juan.rb +170 -0
  109. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Bogota.rb +23 -0
  110. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Caracas.rb +23 -0
  111. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Chicago.rb +283 -0
  112. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Chihuahua.rb +136 -0
  113. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Denver.rb +204 -0
  114. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Godthab.rb +161 -0
  115. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Guatemala.rb +27 -0
  116. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Halifax.rb +274 -0
  117. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Indiana/Indianapolis.rb +149 -0
  118. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Juneau.rb +194 -0
  119. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/La_Paz.rb +22 -0
  120. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Lima.rb +35 -0
  121. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Los_Angeles.rb +232 -0
  122. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Mazatlan.rb +139 -0
  123. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Mexico_City.rb +144 -0
  124. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Monterrey.rb +131 -0
  125. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/New_York.rb +282 -0
  126. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Phoenix.rb +30 -0
  127. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Regina.rb +74 -0
  128. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Santiago.rb +205 -0
  129. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/St_Johns.rb +288 -0
  130. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/America/Tijuana.rb +196 -0
  131. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Almaty.rb +67 -0
  132. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Baghdad.rb +73 -0
  133. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Baku.rb +161 -0
  134. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Bangkok.rb +20 -0
  135. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Chongqing.rb +33 -0
  136. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Dhaka.rb +27 -0
  137. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Hong_Kong.rb +87 -0
  138. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Irkutsk.rb +165 -0
  139. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Jakarta.rb +30 -0
  140. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Jerusalem.rb +163 -0
  141. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Kabul.rb +20 -0
  142. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Kamchatka.rb +163 -0
  143. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Karachi.rb +28 -0
  144. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Katmandu.rb +20 -0
  145. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Kolkata.rb +25 -0
  146. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Krasnoyarsk.rb +163 -0
  147. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Kuala_Lumpur.rb +31 -0
  148. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Kuwait.rb +18 -0
  149. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Magadan.rb +163 -0
  150. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Muscat.rb +18 -0
  151. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Novosibirsk.rb +164 -0
  152. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Rangoon.rb +24 -0
  153. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Riyadh.rb +18 -0
  154. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Seoul.rb +34 -0
  155. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Shanghai.rb +35 -0
  156. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Singapore.rb +33 -0
  157. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Taipei.rb +59 -0
  158. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Tashkent.rb +47 -0
  159. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Tbilisi.rb +78 -0
  160. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Tehran.rb +121 -0
  161. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Tokyo.rb +30 -0
  162. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Ulaanbaatar.rb +65 -0
  163. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Urumqi.rb +33 -0
  164. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Vladivostok.rb +164 -0
  165. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Yakutsk.rb +163 -0
  166. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Yekaterinburg.rb +165 -0
  167. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Asia/Yerevan.rb +165 -0
  168. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Atlantic/Azores.rb +270 -0
  169. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Atlantic/Cape_Verde.rb +23 -0
  170. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Atlantic/South_Georgia.rb +18 -0
  171. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Australia/Adelaide.rb +187 -0
  172. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Australia/Brisbane.rb +35 -0
  173. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Australia/Darwin.rb +29 -0
  174. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Australia/Hobart.rb +193 -0
  175. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Australia/Melbourne.rb +185 -0
  176. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Australia/Perth.rb +37 -0
  177. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Australia/Sydney.rb +185 -0
  178. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Etc/UTC.rb +16 -0
  179. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Amsterdam.rb +228 -0
  180. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Athens.rb +185 -0
  181. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Belgrade.rb +163 -0
  182. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Berlin.rb +188 -0
  183. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Bratislava.rb +13 -0
  184. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Brussels.rb +232 -0
  185. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Bucharest.rb +181 -0
  186. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Budapest.rb +197 -0
  187. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Copenhagen.rb +179 -0
  188. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Dublin.rb +276 -0
  189. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Helsinki.rb +163 -0
  190. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Istanbul.rb +218 -0
  191. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Kiev.rb +168 -0
  192. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Lisbon.rb +268 -0
  193. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Ljubljana.rb +13 -0
  194. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/London.rb +288 -0
  195. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Madrid.rb +211 -0
  196. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Minsk.rb +170 -0
  197. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Moscow.rb +181 -0
  198. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Paris.rb +232 -0
  199. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Prague.rb +187 -0
  200. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Riga.rb +176 -0
  201. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Rome.rb +215 -0
  202. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Sarajevo.rb +13 -0
  203. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Skopje.rb +13 -0
  204. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Sofia.rb +173 -0
  205. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Stockholm.rb +165 -0
  206. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Tallinn.rb +172 -0
  207. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Vienna.rb +183 -0
  208. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Vilnius.rb +170 -0
  209. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Warsaw.rb +212 -0
  210. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Europe/Zagreb.rb +13 -0
  211. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Auckland.rb +202 -0
  212. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Fiji.rb +23 -0
  213. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Guam.rb +22 -0
  214. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Honolulu.rb +28 -0
  215. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Majuro.rb +20 -0
  216. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Midway.rb +25 -0
  217. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Noumea.rb +25 -0
  218. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Pago_Pago.rb +26 -0
  219. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Port_Moresby.rb +20 -0
  220. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/definitions/Pacific/Tongatapu.rb +27 -0
  221. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/info_timezone.rb +52 -0
  222. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/linked_timezone.rb +51 -0
  223. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/linked_timezone_info.rb +44 -0
  224. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/offset_rationals.rb +95 -0
  225. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/time_or_datetime.rb +292 -0
  226. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/timezone.rb +508 -0
  227. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/timezone_definition.rb +56 -0
  228. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/timezone_info.rb +40 -0
  229. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/timezone_offset_info.rb +94 -0
  230. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/timezone_period.rb +198 -0
  231. data/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/timezone_transition_info.rb +138 -0
  232. data/lib/active_support/version.rb +2 -2
  233. data/lib/active_support/whiny_nil.rb +30 -10
  234. metadata +175 -5
  235. data/lib/active_support/core_ext/rexml.rb +0 -38
  236. data/lib/active_support/testing.rb +0 -1
@@ -2,8 +2,8 @@ module Enumerable
2
2
  # Returns a JSON string representing the enumerable. Any +options+
3
3
  # given will be passed on to its elements. For example:
4
4
  #
5
- # users = User.find(:all)
6
- # users.to_json(:only => :name)
5
+ # users = User.find(:all)
6
+ # # => users.to_json(:only => :name)
7
7
  #
8
8
  # will pass the <tt>:only => :name</tt> option to each user.
9
9
  def to_json(options = {}) #:nodoc:
@@ -5,8 +5,7 @@ class Hash
5
5
  # the hash keys. For example:
6
6
  #
7
7
  # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json
8
- #
9
- # {"name": "Konata Izumi", 1: 2, "age": 16}
8
+ # # => {"name": "Konata Izumi", 1: 2, "age": 16}
10
9
  #
11
10
  # The keys in the JSON string are unordered due to the nature of hashes.
12
11
  #
@@ -14,12 +13,10 @@ class Hash
14
13
  # attributes included, and will accept 1 or more hash keys to include/exclude.
15
14
  #
16
15
  # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json(:only => [:name, 'age'])
17
- #
18
- # {"name": "Konata Izumi", "age": 16}
16
+ # # => {"name": "Konata Izumi", "age": 16}
19
17
  #
20
18
  # { :name => "Konata Izumi", 'age' => 16, 1 => 2 }.to_json(:except => 1)
21
- #
22
- # {"name": "Konata Izumi", "age": 16}
19
+ # # => {"name": "Konata Izumi", "age": 16}
23
20
  #
24
21
  # The +options+ also filter down to any hash values. This is particularly
25
22
  # useful for converting hashes containing ActiveRecord objects or any object
@@ -1,5 +1,5 @@
1
1
  class Object
2
- # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
2
+ # Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
3
3
  def to_json(options = {})
4
4
  ActiveSupport::JSON.encode(instance_values, options)
5
5
  end
@@ -1,6 +1,8 @@
1
1
  module ActiveSupport
2
2
  module JSON
3
3
  module Encoding
4
+ mattr_accessor :escape_regex
5
+
4
6
  ESCAPED_CHARS = {
5
7
  "\010" => '\b',
6
8
  "\f" => '\f',
@@ -17,11 +19,15 @@ module ActiveSupport
17
19
  end
18
20
  end
19
21
 
22
+ ActiveSupport.escape_html_entities_in_json = true
23
+
20
24
  class String
21
25
  def to_json(options = nil) #:nodoc:
22
- '"' + gsub(/[\010\f\n\r\t"\\><&]/) { |s|
26
+ json = '"' + gsub(ActiveSupport::JSON::Encoding.escape_regex) { |s|
23
27
  ActiveSupport::JSON::Encoding::ESCAPED_CHARS[s]
24
- }.gsub(/([\xC0-\xDF][\x80-\xBF]|
28
+ }
29
+ json.force_encoding('ascii-8bit') if respond_to?(:force_encoding)
30
+ json.gsub(/([\xC0-\xDF][\x80-\xBF]|
25
31
  [\xE0-\xEF][\x80-\xBF]{2}|
26
32
  [\xF0-\xF7][\x80-\xBF]{3})+/nx) { |s|
27
33
  s.unpack("U*").pack("n*").unpack("H*")[0].gsub(/.{4}/, '\\\\u\&')
@@ -1,5 +1,14 @@
1
1
  class Time
2
- def to_json(options = nil) #:nodoc:
3
- to_datetime.to_json(options)
2
+ # Returns a JSON string representing the time.
3
+ #
4
+ # ==== Example:
5
+ # Time.utc(2005,2,1,15,15,10).to_json
6
+ # # => 2005/02/01 15:15:10 +0000"
7
+ def to_json(options = nil)
8
+ if ActiveSupport.use_standard_json_time_format
9
+ xmlschema.inspect
10
+ else
11
+ %("#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}")
12
+ end
4
13
  end
5
14
  end
@@ -1,5 +1,4 @@
1
1
  require 'active_support/json/variable'
2
-
3
2
  require 'active_support/json/encoders/object' # Require explicitly for rdoc.
4
3
  Dir["#{File.dirname(__FILE__)}/encoders/**/*.rb"].each do |file|
5
4
  basename = File.basename(file, '.rb')
@@ -10,7 +10,7 @@ module ActiveSupport::Multibyte #:nodoc:
10
10
  # String methods are proxied through the Chars object, and can be accessed through the +chars+ method. Methods
11
11
  # which would normally return a String object now return a Chars object so methods can be chained.
12
12
  #
13
- # "The Perfect String ".chars.downcase.strip.normalize #=> "the perfect string"
13
+ # "The Perfect String ".chars.downcase.strip.normalize # => "the perfect string"
14
14
  #
15
15
  # Chars objects are perfectly interchangeable with String objects as long as no explicit class checks are made.
16
16
  # If certain methods do explicitly check the class, call +to_s+ before you pass chars objects to them.
@@ -40,13 +40,15 @@ module ActiveSupport::Multibyte #:nodoc:
40
40
  # core dumps. Don't go there.
41
41
  @string
42
42
  end
43
-
43
+
44
44
  # Make duck-typing with String possible
45
- def respond_to?(method)
46
- super || @string.respond_to?(method) || handler.respond_to?(method) ||
47
- (method.to_s =~ /(.*)!/ && handler.respond_to?($1)) || false
45
+ def respond_to?(method, include_priv = false)
46
+ super || @string.respond_to?(method, include_priv) ||
47
+ handler.respond_to?(method, include_priv) ||
48
+ (method.to_s =~ /(.*)!/ && handler.respond_to?($1, include_priv)) ||
49
+ false
48
50
  end
49
-
51
+
50
52
  # Create a new Chars instance.
51
53
  def initialize(str)
52
54
  @string = str.respond_to?(:string) ? str.string : str
@@ -147,13 +147,11 @@ module ActiveSupport::Multibyte::Handlers #:nodoc:
147
147
  #
148
148
  # s = "Müller"
149
149
  # s.chars[2] = "e" # Replace character with offset 2
150
- # s
151
- # #=> "Müeler"
150
+ # s # => "Müeler"
152
151
  #
153
152
  # s = "Müller"
154
153
  # s.chars[1, 2] = "ö" # Replace 2 characters at character offset 1
155
- # s
156
- # #=> "Möler"
154
+ # s # => "Möler"
157
155
  def []=(str, *args)
158
156
  replace_by = args.pop
159
157
  # Indexed replace with regular expressions already works
@@ -183,10 +181,10 @@ module ActiveSupport::Multibyte::Handlers #:nodoc:
183
181
  # Example:
184
182
  #
185
183
  # "¾ cup".chars.rjust(8).to_s
186
- # #=> " ¾ cup"
184
+ # # => " ¾ cup"
187
185
  #
188
186
  # "¾ cup".chars.rjust(8, " ").to_s # Use non-breaking whitespace
189
- # #=> "   ¾ cup"
187
+ # # => "   ¾ cup"
190
188
  def rjust(str, integer, padstr=' ')
191
189
  justify(str, integer, :right, padstr)
192
190
  end
@@ -196,10 +194,10 @@ module ActiveSupport::Multibyte::Handlers #:nodoc:
196
194
  # Example:
197
195
  #
198
196
  # "¾ cup".chars.rjust(8).to_s
199
- # #=> "¾ cup "
197
+ # # => "¾ cup "
200
198
  #
201
199
  # "¾ cup".chars.rjust(8, " ").to_s # Use non-breaking whitespace
202
- # #=> "¾ cup   "
200
+ # # => "¾ cup   "
203
201
  def ljust(str, integer, padstr=' ')
204
202
  justify(str, integer, :left, padstr)
205
203
  end
@@ -209,10 +207,10 @@ module ActiveSupport::Multibyte::Handlers #:nodoc:
209
207
  # Example:
210
208
  #
211
209
  # "¾ cup".chars.center(8).to_s
212
- # #=> " ¾ cup "
210
+ # # => " ¾ cup "
213
211
  #
214
212
  # "¾ cup".chars.center(8, " ").to_s # Use non-breaking whitespace
215
- # #=> " ¾ cup  "
213
+ # # => " ¾ cup  "
216
214
  def center(str, integer, padstr=' ')
217
215
  justify(str, integer, :center, padstr)
218
216
  end
@@ -284,7 +282,9 @@ module ActiveSupport::Multibyte::Handlers #:nodoc:
284
282
  # passing strings to databases and validations.
285
283
  #
286
284
  # * <tt>str</tt> - The string to perform normalization on.
287
- # * <tt>form</tt> - The form you want to normalize in. Should be one of the following: :c, :kc, :d or :kd.
285
+ # * <tt>form</tt> - The form you want to normalize in. Should be one of the following:
286
+ # <tt>:c</tt>, <tt>:kc</tt>, <tt>:d</tt>, or <tt>:kd</tt>. Default is
287
+ # ActiveSupport::Multibyte::DEFAULT_NORMALIZATION_FORM.
288
288
  def normalize(str, form=ActiveSupport::Multibyte::DEFAULT_NORMALIZATION_FORM)
289
289
  # See http://www.unicode.org/reports/tr15, Table 1
290
290
  codepoints = u_unpack(str)
@@ -0,0 +1,43 @@
1
+ # OrderedHash is namespaced to prevent conflicts with other implementations
2
+ module ActiveSupport
3
+ # Hash is ordered in Ruby 1.9!
4
+ if RUBY_VERSION >= '1.9'
5
+ OrderedHash = ::Hash
6
+ else
7
+ class OrderedHash < Array #:nodoc:
8
+ def []=(key, value)
9
+ if pair = assoc(key)
10
+ pair.pop
11
+ pair << value
12
+ else
13
+ self << [key, value]
14
+ end
15
+ end
16
+
17
+ def [](key)
18
+ pair = assoc(key)
19
+ pair ? pair.last : nil
20
+ end
21
+
22
+ def delete(key)
23
+ pair = assoc(key)
24
+ pair ? array_index = index(pair) : nil
25
+ array_index ? delete_at(array_index).last : nil
26
+ end
27
+
28
+ def keys
29
+ collect { |key, value| key }
30
+ end
31
+
32
+ def values
33
+ collect { |key, value| value }
34
+ end
35
+
36
+ def to_hash
37
+ returning({}) do |hash|
38
+ each { |array| hash[array[0]] = array[1] }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,41 +1,3 @@
1
- # OrderedHash is namespaced to prevent conflicts with other implementations
2
- module ActiveSupport
3
- # Hash is ordered in Ruby 1.9!
4
- if RUBY_VERSION >= '1.9'
5
- OrderedHash = ::Hash
6
- else
7
- class OrderedHash < Array #:nodoc:
8
- def []=(key, value)
9
- if pair = assoc(key)
10
- pair.pop
11
- pair << value
12
- else
13
- self << [key, value]
14
- end
15
- end
16
-
17
- def [](key)
18
- pair = assoc(key)
19
- pair ? pair.last : nil
20
- end
21
-
22
- def keys
23
- collect { |key, value| key }
24
- end
25
-
26
- def values
27
- collect { |key, value| value }
28
- end
29
-
30
- def to_hash
31
- returning({}) do |hash|
32
- each { |array| hash[array[0]] = array[1] }
33
- end
34
- end
35
- end
36
- end
37
- end
38
-
39
1
  class OrderedOptions < ActiveSupport::OrderedHash #:nodoc:
40
2
  def []=(key, value)
41
3
  super(key.to_sym, value)
@@ -1,5 +1,13 @@
1
+ require 'test/unit/testcase'
2
+ require 'active_support/testing/setup_and_teardown'
3
+ require 'active_support/testing/default'
4
+
5
+ # TODO: move to core_ext
6
+ class Test::Unit::TestCase #:nodoc:
7
+ include ActiveSupport::Testing::SetupAndTeardown
8
+ end
9
+
1
10
  module ActiveSupport
2
11
  class TestCase < Test::Unit::TestCase
3
- include ActiveSupport::Testing::Default
4
12
  end
5
- end
13
+ end
@@ -1,12 +1,9 @@
1
1
  module ActiveSupport
2
2
  module Testing
3
- module Default
4
- def run(*args)
5
- #method_name appears to be a symbol on 1.8.4 and a string on 1.8.6
6
- return if @method_name.to_s == "default_test"
7
- super
3
+ module Default #:nodoc:
4
+ # Placeholder so test/unit ignores test cases without any tests.
5
+ def default_test
8
6
  end
9
7
  end
10
8
  end
11
9
  end
12
-
@@ -0,0 +1,93 @@
1
+ module ActiveSupport
2
+ module Testing
3
+ module SetupAndTeardown
4
+ # For compatibility with Ruby < 1.8.6
5
+ PASSTHROUGH_EXCEPTIONS =
6
+ if defined?(Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS)
7
+ Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS
8
+ else
9
+ [NoMemoryError, SignalException, Interrupt, SystemExit]
10
+ end
11
+
12
+ def self.included(base)
13
+ base.send :include, ActiveSupport::Callbacks
14
+ base.define_callbacks :setup, :teardown
15
+
16
+ begin
17
+ require 'mocha'
18
+ base.alias_method_chain :run, :callbacks_and_mocha
19
+ rescue LoadError
20
+ base.alias_method_chain :run, :callbacks
21
+ end
22
+ end
23
+
24
+ # This redefinition is unfortunate but test/unit shows us no alternative.
25
+ def run_with_callbacks(result) #:nodoc:
26
+ return if @method_name.to_s == "default_test"
27
+
28
+ yield(Test::Unit::TestCase::STARTED, name)
29
+ @_result = result
30
+ begin
31
+ run_callbacks :setup
32
+ setup
33
+ __send__(@method_name)
34
+ rescue Test::Unit::AssertionFailedError => e
35
+ add_failure(e.message, e.backtrace)
36
+ rescue *PASSTHROUGH_EXCEPTIONS
37
+ raise
38
+ rescue Exception
39
+ add_error($!)
40
+ ensure
41
+ begin
42
+ teardown
43
+ run_callbacks :teardown, :enumerator => :reverse_each
44
+ rescue Test::Unit::AssertionFailedError => e
45
+ add_failure(e.message, e.backtrace)
46
+ rescue *PASSTHROUGH_EXCEPTIONS
47
+ raise
48
+ rescue Exception
49
+ add_error($!)
50
+ end
51
+ end
52
+ result.add_run
53
+ yield(Test::Unit::TestCase::FINISHED, name)
54
+ end
55
+
56
+ # Doubly unfortunate: mocha does the same so we have to hax their hax.
57
+ def run_with_callbacks_and_mocha(result)
58
+ return if @method_name.to_s == "default_test"
59
+
60
+ yield(Test::Unit::TestCase::STARTED, name)
61
+ @_result = result
62
+ begin
63
+ mocha_setup
64
+ begin
65
+ run_callbacks :setup
66
+ setup
67
+ __send__(@method_name)
68
+ mocha_verify { add_assertion }
69
+ rescue Mocha::ExpectationError => e
70
+ add_failure(e.message, e.backtrace)
71
+ rescue Test::Unit::AssertionFailedError => e
72
+ add_failure(e.message, e.backtrace)
73
+ rescue StandardError, ScriptError
74
+ add_error($!)
75
+ ensure
76
+ begin
77
+ teardown
78
+ run_callbacks :teardown, :enumerator => :reverse_each
79
+ rescue Test::Unit::AssertionFailedError => e
80
+ add_failure(e.message, e.backtrace)
81
+ rescue StandardError, ScriptError
82
+ add_error($!)
83
+ end
84
+ end
85
+ ensure
86
+ mocha_teardown
87
+ end
88
+ result.add_run
89
+ yield(Test::Unit::TestCase::FINISHED, name)
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,283 @@
1
+ require 'tzinfo'
2
+ module ActiveSupport
3
+ # A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are
4
+ # limited to UTC and the system's <tt>ENV['TZ']</tt> zone.
5
+ #
6
+ # You shouldn't ever need to create a TimeWithZone instance directly via <tt>new</tt> -- instead, Rails provides the methods
7
+ # +local+, +parse+, +at+ and +now+ on TimeZone instances, and +in_time_zone+ on Time and DateTime instances, for a more
8
+ # user-friendly syntax. Examples:
9
+ #
10
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
11
+ # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
12
+ # Time.zone.parse('2007-02-01 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
13
+ # Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
14
+ # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
15
+ # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
16
+ #
17
+ # See TimeZone and ActiveSupport::CoreExtensions::Time::Zones for further documentation for these methods.
18
+ #
19
+ # TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangable. Examples:
20
+ #
21
+ # t = Time.zone.now # => Sun, 18 May 2008 13:27:25 EDT -04:00
22
+ # t.hour # => 13
23
+ # t.dst? # => true
24
+ # t.utc_offset # => -14400
25
+ # t.zone # => "EDT"
26
+ # t.to_s(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400"
27
+ # t + 1.day # => Mon, 19 May 2008 13:27:25 EDT -04:00
28
+ # t.beginning_of_year # => Tue, 01 Jan 2008 00:00:00 EST -05:00
29
+ # t > Time.utc(1999) # => true
30
+ # t.is_a?(Time) # => true
31
+ # t.is_a?(ActiveSupport::TimeWithZone) # => true
32
+ class TimeWithZone
33
+ include Comparable
34
+ attr_reader :time_zone
35
+
36
+ def initialize(utc_time, time_zone, local_time = nil, period = nil)
37
+ @utc, @time_zone, @time = utc_time, time_zone, local_time
38
+ @period = @utc ? period : get_period_and_ensure_valid_local_time
39
+ end
40
+
41
+ # Returns a Time or DateTime instance that represents the time in +time_zone+.
42
+ def time
43
+ @time ||= period.to_local(@utc)
44
+ end
45
+
46
+ # Returns a Time or DateTime instance that represents the time in UTC.
47
+ def utc
48
+ @utc ||= period.to_utc(@time)
49
+ end
50
+ alias_method :comparable_time, :utc
51
+ alias_method :getgm, :utc
52
+ alias_method :getutc, :utc
53
+ alias_method :gmtime, :utc
54
+
55
+ # Returns the underlying TZInfo::TimezonePeriod.
56
+ def period
57
+ @period ||= time_zone.period_for_utc(@utc)
58
+ end
59
+
60
+ # Returns the simultaneous time in <tt>Time.zone</tt>, or the specified zone.
61
+ def in_time_zone(new_zone = ::Time.zone)
62
+ return self if time_zone == new_zone
63
+ utc.in_time_zone(new_zone)
64
+ end
65
+
66
+ # Returns a <tt>Time.local()</tt> instance of the simultaneous time in your system's <tt>ENV['TZ']</tt> zone
67
+ def localtime
68
+ utc.getlocal
69
+ end
70
+ alias_method :getlocal, :localtime
71
+
72
+ def dst?
73
+ period.dst?
74
+ end
75
+ alias_method :isdst, :dst?
76
+
77
+ def utc?
78
+ time_zone.name == 'UTC'
79
+ end
80
+ alias_method :gmt?, :utc?
81
+
82
+ def utc_offset
83
+ period.utc_total_offset
84
+ end
85
+ alias_method :gmt_offset, :utc_offset
86
+ alias_method :gmtoff, :utc_offset
87
+
88
+ def formatted_offset(colon = true, alternate_utc_string = nil)
89
+ utc? && alternate_utc_string || utc_offset.to_utc_offset_s(colon)
90
+ end
91
+
92
+ # Time uses +zone+ to display the time zone abbreviation, so we're duck-typing it.
93
+ def zone
94
+ period.zone_identifier.to_s
95
+ end
96
+
97
+ def inspect
98
+ "#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
99
+ end
100
+
101
+ def xmlschema
102
+ "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{formatted_offset(true, 'Z')}"
103
+ end
104
+ alias_method :iso8601, :xmlschema
105
+
106
+ def to_json(options = nil)
107
+ if ActiveSupport.use_standard_json_time_format
108
+ xmlschema.inspect
109
+ else
110
+ %("#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}")
111
+ end
112
+ end
113
+
114
+ def to_yaml(options = {})
115
+ if options.kind_of?(YAML::Emitter)
116
+ utc.to_yaml(options)
117
+ else
118
+ time.to_yaml(options).gsub('Z', formatted_offset(true, 'Z'))
119
+ end
120
+ end
121
+
122
+ def httpdate
123
+ utc.httpdate
124
+ end
125
+
126
+ def rfc2822
127
+ to_s(:rfc822)
128
+ end
129
+ alias_method :rfc822, :rfc2822
130
+
131
+ # <tt>:db</tt> format outputs time in UTC; all others output time in local.
132
+ # Uses TimeWithZone's +strftime+, so <tt>%Z</tt> and <tt>%z</tt> work correctly.
133
+ def to_s(format = :default)
134
+ return utc.to_s(format) if format == :db
135
+ if formatter = ::Time::DATE_FORMATS[format]
136
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
137
+ else
138
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby 1.9 Time#to_s format
139
+ end
140
+ end
141
+
142
+ # Replaces <tt>%Z</tt> and <tt>%z</tt> directives with +zone+ and +formatted_offset+, respectively, before passing to
143
+ # Time#strftime, so that zone information is correct
144
+ def strftime(format)
145
+ format = format.gsub('%Z', zone).gsub('%z', formatted_offset(false))
146
+ time.strftime(format)
147
+ end
148
+
149
+ # Use the time in UTC for comparisons.
150
+ def <=>(other)
151
+ utc <=> other
152
+ end
153
+
154
+ def between?(min, max)
155
+ utc.between?(min, max)
156
+ end
157
+
158
+ def eql?(other)
159
+ utc == other
160
+ end
161
+
162
+ # If wrapped +time+ is a DateTime, use DateTime#since instead of <tt>+</tt>.
163
+ # Otherwise, just pass on to +method_missing+.
164
+ def +(other)
165
+ result = utc.acts_like?(:date) ? utc.since(other) : utc + other rescue utc.since(other)
166
+ result.in_time_zone(time_zone)
167
+ end
168
+
169
+ # If a time-like object is passed in, compare it with +utc+.
170
+ # Else if wrapped +time+ is a DateTime, use DateTime#ago instead of DateTime#-.
171
+ # Otherwise, just pass on to +method_missing+.
172
+ def -(other)
173
+ if other.acts_like?(:time)
174
+ utc - other
175
+ else
176
+ result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other)
177
+ result.in_time_zone(time_zone)
178
+ end
179
+ end
180
+
181
+ def since(other)
182
+ utc.since(other).in_time_zone(time_zone)
183
+ end
184
+
185
+ def ago(other)
186
+ utc.ago(other).in_time_zone(time_zone)
187
+ end
188
+
189
+ def advance(options)
190
+ utc.advance(options).in_time_zone(time_zone)
191
+ end
192
+
193
+ %w(year mon month day mday hour min sec).each do |method_name|
194
+ class_eval <<-EOV
195
+ def #{method_name}
196
+ time.#{method_name}
197
+ end
198
+ EOV
199
+ end
200
+
201
+ def usec
202
+ time.respond_to?(:usec) ? time.usec : 0
203
+ end
204
+
205
+ def to_a
206
+ [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
207
+ end
208
+
209
+ def to_f
210
+ utc.to_f
211
+ end
212
+
213
+ def to_i
214
+ utc.to_i
215
+ end
216
+ alias_method :hash, :to_i
217
+ alias_method :tv_sec, :to_i
218
+
219
+ # A TimeWithZone acts like a Time, so just return +self+.
220
+ def to_time
221
+ self
222
+ end
223
+
224
+ def to_datetime
225
+ utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
226
+ end
227
+
228
+ # So that +self+ <tt>acts_like?(:time)</tt>.
229
+ def acts_like_time?
230
+ true
231
+ end
232
+
233
+ # Say we're a Time to thwart type checking.
234
+ def is_a?(klass)
235
+ klass == ::Time || super
236
+ end
237
+ alias_method :kind_of?, :is_a?
238
+
239
+ # Neuter freeze because freezing can cause problems with lazy loading of attributes.
240
+ def freeze
241
+ self
242
+ end
243
+
244
+ def marshal_dump
245
+ [utc, time_zone.name, time]
246
+ end
247
+
248
+ def marshal_load(variables)
249
+ initialize(variables[0], ::Time.send!(:get_zone, variables[1]), variables[2])
250
+ end
251
+
252
+ # Ensure proxy class responds to all methods that underlying time instance responds to.
253
+ def respond_to?(sym, include_priv = false)
254
+ # consistently respond false to acts_like?(:date), regardless of whether #time is a Time or DateTime
255
+ return false if sym.to_s == 'acts_like_date?'
256
+ super || time.respond_to?(sym, include_priv)
257
+ end
258
+
259
+ # Send the missing method to +time+ instance, and wrap result in a new TimeWithZone with the existing +time_zone+.
260
+ def method_missing(sym, *args, &block)
261
+ result = time.__send__(sym, *args, &block)
262
+ result.acts_like?(:time) ? self.class.new(nil, time_zone, result) : result
263
+ end
264
+
265
+ private
266
+ def get_period_and_ensure_valid_local_time
267
+ # we don't want a Time.local instance enforcing its own DST rules as well,
268
+ # so transfer time values to a utc constructor if necessary
269
+ @time = transfer_time_values_to_utc_constructor(@time) unless @time.utc?
270
+ begin
271
+ @time_zone.period_for_local(@time)
272
+ rescue ::TZInfo::PeriodNotFound
273
+ # time is in the "spring forward" hour gap, so we're moving the time forward one hour and trying again
274
+ @time += 1.hour
275
+ retry
276
+ end
277
+ end
278
+
279
+ def transfer_time_values_to_utc_constructor(time)
280
+ ::Time.utc_time(time.year, time.month, time.day, time.hour, time.min, time.sec, time.respond_to?(:usec) ? time.usec : 0)
281
+ end
282
+ end
283
+ end