csd 0.0.15 → 0.0.16

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 (256) hide show
  1. data/.gitignore +1 -0
  2. data/COPYING +367 -0
  3. data/Rakefile +10 -10
  4. data/VERSION +1 -1
  5. data/bin/ai +19 -0
  6. data/csd.gemspec +257 -35
  7. data/lib/active_support.rb +75 -0
  8. data/lib/active_support/all.rb +3 -0
  9. data/lib/active_support/backtrace_cleaner.rb +94 -0
  10. data/lib/active_support/base64.rb +42 -0
  11. data/lib/active_support/basic_object.rb +21 -0
  12. data/lib/active_support/benchmarkable.rb +60 -0
  13. data/lib/active_support/buffered_logger.rb +132 -0
  14. data/lib/active_support/builder.rb +6 -0
  15. data/lib/active_support/cache.rb +626 -0
  16. data/lib/active_support/cache/compressed_mem_cache_store.rb +13 -0
  17. data/lib/active_support/cache/file_store.rb +188 -0
  18. data/lib/active_support/cache/mem_cache_store.rb +191 -0
  19. data/lib/active_support/cache/memory_store.rb +159 -0
  20. data/lib/active_support/cache/strategy/local_cache.rb +164 -0
  21. data/lib/active_support/cache/synchronized_memory_store.rb +11 -0
  22. data/lib/active_support/callbacks.rb +600 -0
  23. data/lib/active_support/concern.rb +29 -0
  24. data/lib/active_support/configurable.rb +36 -0
  25. data/lib/active_support/core_ext.rb +3 -0
  26. data/lib/active_support/core_ext/array.rb +7 -0
  27. data/lib/active_support/core_ext/array/access.rb +46 -0
  28. data/lib/active_support/core_ext/array/conversions.rb +164 -0
  29. data/lib/active_support/core_ext/array/extract_options.rb +29 -0
  30. data/lib/active_support/core_ext/array/grouping.rb +100 -0
  31. data/lib/active_support/core_ext/array/random_access.rb +20 -0
  32. data/lib/active_support/core_ext/array/uniq_by.rb +17 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +22 -0
  34. data/lib/active_support/core_ext/benchmark.rb +7 -0
  35. data/lib/active_support/core_ext/big_decimal.rb +1 -0
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +27 -0
  37. data/lib/active_support/core_ext/cgi.rb +1 -0
  38. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +19 -0
  39. data/lib/active_support/core_ext/class.rb +4 -0
  40. data/lib/active_support/core_ext/class/attribute.rb +67 -0
  41. data/lib/active_support/core_ext/class/attribute_accessors.rb +63 -0
  42. data/lib/active_support/core_ext/class/delegating_attributes.rb +44 -0
  43. data/lib/active_support/core_ext/class/inheritable_attributes.rb +232 -0
  44. data/lib/active_support/core_ext/class/subclasses.rb +55 -0
  45. data/lib/active_support/core_ext/date/acts_like.rb +8 -0
  46. data/lib/active_support/core_ext/date/calculations.rb +240 -0
  47. data/lib/active_support/core_ext/date/conversions.rb +99 -0
  48. data/lib/active_support/core_ext/date/freeze.rb +31 -0
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +13 -0
  50. data/lib/active_support/core_ext/date_time/calculations.rb +113 -0
  51. data/lib/active_support/core_ext/date_time/conversions.rb +102 -0
  52. data/lib/active_support/core_ext/date_time/zones.rb +17 -0
  53. data/lib/active_support/core_ext/enumerable.rb +119 -0
  54. data/lib/active_support/core_ext/exception.rb +3 -0
  55. data/lib/active_support/core_ext/file.rb +2 -0
  56. data/lib/active_support/core_ext/file/atomic.rb +41 -0
  57. data/lib/active_support/core_ext/file/path.rb +5 -0
  58. data/lib/active_support/core_ext/float.rb +1 -0
  59. data/lib/active_support/core_ext/float/rounding.rb +19 -0
  60. data/lib/active_support/core_ext/hash.rb +8 -0
  61. data/lib/active_support/core_ext/hash/conversions.rb +150 -0
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +16 -0
  63. data/lib/active_support/core_ext/hash/diff.rb +13 -0
  64. data/lib/active_support/core_ext/hash/except.rb +24 -0
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +14 -0
  66. data/lib/active_support/core_ext/hash/keys.rb +45 -0
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +28 -0
  68. data/lib/active_support/core_ext/hash/slice.rb +38 -0
  69. data/lib/active_support/core_ext/integer.rb +3 -0
  70. data/lib/active_support/core_ext/integer/inflections.rb +14 -0
  71. data/lib/active_support/core_ext/integer/multiple.rb +6 -0
  72. data/lib/active_support/core_ext/integer/time.rb +39 -0
  73. data/lib/active_support/core_ext/kernel.rb +5 -0
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
  75. data/lib/active_support/core_ext/kernel/debugger.rb +16 -0
  76. data/lib/active_support/core_ext/kernel/reporting.rb +62 -0
  77. data/lib/active_support/core_ext/kernel/requires.rb +26 -0
  78. data/lib/active_support/core_ext/kernel/singleton_class.rb +13 -0
  79. data/lib/active_support/core_ext/load_error.rb +23 -0
  80. data/lib/active_support/core_ext/logger.rb +146 -0
  81. data/lib/active_support/core_ext/module.rb +12 -0
  82. data/lib/active_support/core_ext/module/aliasing.rb +70 -0
  83. data/lib/active_support/core_ext/module/anonymous.rb +24 -0
  84. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +31 -0
  85. data/lib/active_support/core_ext/module/attr_internal.rb +32 -0
  86. data/lib/active_support/core_ext/module/attribute_accessors.rb +66 -0
  87. data/lib/active_support/core_ext/module/delegation.rb +146 -0
  88. data/lib/active_support/core_ext/module/deprecation.rb +9 -0
  89. data/lib/active_support/core_ext/module/introspection.rb +88 -0
  90. data/lib/active_support/core_ext/module/method_names.rb +14 -0
  91. data/lib/active_support/core_ext/module/reachable.rb +10 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +6 -0
  93. data/lib/active_support/core_ext/module/synchronization.rb +42 -0
  94. data/lib/active_support/core_ext/name_error.rb +18 -0
  95. data/lib/active_support/core_ext/numeric.rb +2 -0
  96. data/lib/active_support/core_ext/numeric/bytes.rb +44 -0
  97. data/lib/active_support/core_ext/numeric/time.rb +77 -0
  98. data/lib/active_support/core_ext/object.rb +14 -0
  99. data/lib/active_support/core_ext/object/acts_like.rb +10 -0
  100. data/lib/active_support/core_ext/object/blank.rb +76 -0
  101. data/lib/active_support/core_ext/object/conversions.rb +4 -0
  102. data/lib/active_support/core_ext/object/duplicable.rb +65 -0
  103. data/lib/active_support/core_ext/object/extending.rb +11 -0
  104. data/lib/active_support/core_ext/object/instance_variables.rb +67 -0
  105. data/lib/active_support/core_ext/object/misc.rb +2 -0
  106. data/lib/active_support/core_ext/object/returning.rb +42 -0
  107. data/lib/active_support/core_ext/object/to_param.rb +49 -0
  108. data/lib/active_support/core_ext/object/to_query.rb +27 -0
  109. data/lib/active_support/core_ext/object/try.rb +36 -0
  110. data/lib/active_support/core_ext/object/with_options.rb +26 -0
  111. data/lib/active_support/core_ext/proc.rb +14 -0
  112. data/lib/active_support/core_ext/process.rb +1 -0
  113. data/lib/active_support/core_ext/process/daemon.rb +23 -0
  114. data/lib/active_support/core_ext/range.rb +4 -0
  115. data/lib/active_support/core_ext/range/blockless_step.rb +29 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +21 -0
  117. data/lib/active_support/core_ext/range/include_range.rb +21 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +8 -0
  119. data/lib/active_support/core_ext/regexp.rb +5 -0
  120. data/lib/active_support/core_ext/rexml.rb +46 -0
  121. data/lib/active_support/core_ext/string.rb +12 -0
  122. data/lib/active_support/core_ext/string/access.rb +99 -0
  123. data/lib/active_support/core_ext/string/behavior.rb +7 -0
  124. data/lib/active_support/core_ext/string/conversions.rb +61 -0
  125. data/lib/active_support/core_ext/string/encoding.rb +11 -0
  126. data/lib/active_support/core_ext/string/exclude.rb +6 -0
  127. data/lib/active_support/core_ext/string/filters.rb +49 -0
  128. data/lib/active_support/core_ext/string/inflections.rb +149 -0
  129. data/lib/active_support/core_ext/string/interpolation.rb +2 -0
  130. data/lib/active_support/core_ext/string/multibyte.rb +72 -0
  131. data/lib/active_support/core_ext/string/output_safety.rb +109 -0
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
  133. data/lib/active_support/core_ext/string/xchar.rb +18 -0
  134. data/lib/active_support/core_ext/time/acts_like.rb +8 -0
  135. data/lib/active_support/core_ext/time/calculations.rb +282 -0
  136. data/lib/active_support/core_ext/time/conversions.rb +85 -0
  137. data/lib/active_support/core_ext/time/marshal.rb +56 -0
  138. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +10 -0
  139. data/lib/active_support/core_ext/time/zones.rb +78 -0
  140. data/lib/active_support/core_ext/uri.rb +22 -0
  141. data/lib/active_support/dependencies.rb +628 -0
  142. data/lib/active_support/dependencies/autoload.rb +50 -0
  143. data/lib/active_support/deprecation.rb +18 -0
  144. data/lib/active_support/deprecation/behaviors.rb +38 -0
  145. data/lib/active_support/deprecation/method_wrappers.rb +29 -0
  146. data/lib/active_support/deprecation/proxy_wrappers.rb +74 -0
  147. data/lib/active_support/deprecation/reporting.rb +56 -0
  148. data/lib/active_support/duration.rb +105 -0
  149. data/lib/active_support/gzip.rb +25 -0
  150. data/lib/active_support/hash_with_indifferent_access.rb +145 -0
  151. data/lib/active_support/i18n.rb +8 -0
  152. data/lib/active_support/inflections.rb +56 -0
  153. data/lib/active_support/inflector.rb +7 -0
  154. data/lib/active_support/inflector/inflections.rb +211 -0
  155. data/lib/active_support/inflector/methods.rb +141 -0
  156. data/lib/active_support/inflector/transliterate.rb +97 -0
  157. data/lib/active_support/json.rb +2 -0
  158. data/lib/active_support/json/backends/jsongem.rb +43 -0
  159. data/lib/active_support/json/backends/yajl.rb +40 -0
  160. data/lib/active_support/json/backends/yaml.rb +90 -0
  161. data/lib/active_support/json/decoding.rb +51 -0
  162. data/lib/active_support/json/encoding.rb +254 -0
  163. data/lib/active_support/json/variable.rb +11 -0
  164. data/lib/active_support/lazy_load_hooks.rb +27 -0
  165. data/lib/active_support/locale/en.yml +36 -0
  166. data/lib/active_support/memoizable.rb +103 -0
  167. data/lib/active_support/message_encryptor.rb +71 -0
  168. data/lib/active_support/message_verifier.rb +62 -0
  169. data/lib/active_support/multibyte.rb +44 -0
  170. data/lib/active_support/multibyte/chars.rb +480 -0
  171. data/lib/active_support/multibyte/exceptions.rb +8 -0
  172. data/lib/active_support/multibyte/unicode.rb +393 -0
  173. data/lib/active_support/multibyte/utils.rb +60 -0
  174. data/lib/active_support/notifications.rb +81 -0
  175. data/lib/active_support/notifications/fanout.rb +93 -0
  176. data/lib/active_support/notifications/instrumenter.rb +56 -0
  177. data/lib/active_support/option_merger.rb +25 -0
  178. data/lib/active_support/ordered_hash.rb +158 -0
  179. data/lib/active_support/ordered_options.rb +27 -0
  180. data/lib/active_support/railtie.rb +100 -0
  181. data/lib/active_support/rescuable.rb +114 -0
  182. data/lib/active_support/ruby/shim.rb +22 -0
  183. data/lib/active_support/secure_random.rb +199 -0
  184. data/lib/active_support/string_inquirer.rb +21 -0
  185. data/lib/active_support/test_case.rb +42 -0
  186. data/lib/active_support/testing/assertions.rb +82 -0
  187. data/lib/active_support/testing/declarative.rb +40 -0
  188. data/lib/active_support/testing/default.rb +9 -0
  189. data/lib/active_support/testing/deprecation.rb +55 -0
  190. data/lib/active_support/testing/isolation.rb +154 -0
  191. data/lib/active_support/testing/pending.rb +48 -0
  192. data/lib/active_support/testing/performance.rb +455 -0
  193. data/lib/active_support/testing/setup_and_teardown.rb +111 -0
  194. data/lib/active_support/time.rb +34 -0
  195. data/lib/active_support/time/autoload.rb +5 -0
  196. data/lib/active_support/time_with_zone.rb +341 -0
  197. data/lib/active_support/values/time_zone.rb +377 -0
  198. data/lib/active_support/values/unicode_tables.dat +0 -0
  199. data/lib/active_support/version.rb +10 -0
  200. data/lib/active_support/whiny_nil.rb +60 -0
  201. data/lib/active_support/xml_mini.rb +158 -0
  202. data/lib/active_support/xml_mini/jdom.rb +168 -0
  203. data/lib/active_support/xml_mini/libxml.rb +80 -0
  204. data/lib/active_support/xml_mini/libxmlsax.rb +85 -0
  205. data/lib/active_support/xml_mini/nokogiri.rb +78 -0
  206. data/lib/active_support/xml_mini/nokogirisax.rb +83 -0
  207. data/lib/active_support/xml_mini/rexml.rb +129 -0
  208. data/lib/csd.rb +82 -2
  209. data/lib/csd/application.rb +2 -0
  210. data/lib/csd/application/default.rb +51 -0
  211. data/lib/csd/application/default/base.rb +15 -0
  212. data/lib/csd/application/minisip.rb +25 -0
  213. data/lib/csd/application/minisip/about.yml +14 -0
  214. data/lib/csd/application/minisip/base.rb +161 -0
  215. data/lib/csd/application/minisip/error.rb +11 -0
  216. data/lib/csd/application/minisip/options/common.rb +0 -0
  217. data/lib/csd/application/minisip/options/compile.rb +59 -0
  218. data/lib/csd/{applications → application}/minisip/unix/base.rb +10 -11
  219. data/lib/csd/application/opensips/about.yml +2 -0
  220. data/lib/csd/applications.rb +55 -0
  221. data/lib/csd/commands.rb +88 -65
  222. data/lib/csd/error.rb +31 -0
  223. data/lib/csd/extensions.rb +1 -0
  224. data/lib/{extensions → csd/extensions}/core/array.rb +2 -2
  225. data/lib/csd/extensions/core/dir.rb +46 -0
  226. data/lib/{extensions → csd/extensions}/core/file.rb +2 -2
  227. data/lib/{extensions → csd/extensions}/core/object.rb +2 -2
  228. data/lib/csd/extensions/core/option_parser.rb +33 -0
  229. data/lib/{extensions → csd/extensions}/core/pathname.rb +12 -3
  230. data/lib/{extensions → csd/extensions}/core/string.rb +2 -2
  231. data/lib/{extensions → csd/extensions}/gem/platform.rb +6 -2
  232. data/lib/csd/global_open_struct.rb +18 -0
  233. data/lib/csd/options.rb +124 -95
  234. data/lib/csd/path.rb +31 -0
  235. data/lib/csd/ui.rb +1 -0
  236. data/lib/csd/ui/cli.rb +7 -0
  237. data/lib/csd/ui/ui.rb +46 -0
  238. data/lib/csd/version.rb +9 -0
  239. data/lib/term/ansicolor.rb +102 -0
  240. data/lib/term/ansicolor/.keep +0 -0
  241. data/lib/term/ansicolor/version.rb +10 -0
  242. data/test/functional/test_applications.rb +86 -0
  243. data/test/functional/test_commands.rb +42 -29
  244. data/test/functional/test_options.rb +98 -0
  245. data/test/helper.rb +14 -0
  246. data/test/unit/test_dir.rb +38 -0
  247. data/test/unit/test_pathname.rb +32 -0
  248. metadata +253 -40
  249. data/LICENSE +0 -20
  250. data/bin/csd +0 -8
  251. data/lib/csd/applications/base.rb +0 -33
  252. data/lib/csd/applications/minisip/base.rb +0 -125
  253. data/lib/csd/applications/minisip/init.rb +0 -20
  254. data/lib/csd/init.rb +0 -69
  255. data/lib/csd/path_container.rb +0 -15
  256. data/publish +0 -29
@@ -0,0 +1,111 @@
1
+ require 'active_support/concern'
2
+ require 'active_support/callbacks'
3
+
4
+ module ActiveSupport
5
+ module Testing
6
+ module SetupAndTeardown
7
+ extend ActiveSupport::Concern
8
+
9
+ included do
10
+ include ActiveSupport::Callbacks
11
+ define_callbacks :setup, :teardown
12
+
13
+ if defined?(MiniTest::Assertions) && TestCase < MiniTest::Assertions
14
+ include ForMiniTest
15
+ else
16
+ include ForClassicTestUnit
17
+ end
18
+ end
19
+
20
+ module ClassMethods
21
+ def setup(*args, &block)
22
+ set_callback(:setup, :before, *args, &block)
23
+ end
24
+
25
+ def teardown(*args, &block)
26
+ set_callback(:teardown, :after, *args, &block)
27
+ end
28
+ end
29
+
30
+ module ForMiniTest
31
+ def run(runner)
32
+ result = '.'
33
+ begin
34
+ _run_setup_callbacks do
35
+ result = super
36
+ end
37
+ rescue Exception => e
38
+ result = runner.puke(self.class, method_name, e)
39
+ ensure
40
+ begin
41
+ _run_teardown_callbacks
42
+ rescue Exception => e
43
+ result = runner.puke(self.class, method_name, e)
44
+ end
45
+ end
46
+ result
47
+ end
48
+ end
49
+
50
+ module ForClassicTestUnit
51
+ # For compatibility with Ruby < 1.8.6
52
+ PASSTHROUGH_EXCEPTIONS = Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS rescue [NoMemoryError, SignalException, Interrupt, SystemExit]
53
+
54
+ # This redefinition is unfortunate but test/unit shows us no alternative.
55
+ # Doubly unfortunate: hax to support Mocha's hax.
56
+ def run(result)
57
+ return if @method_name.to_s == "default_test"
58
+
59
+ mocha_counter = retrieve_mocha_counter(result)
60
+ yield(Test::Unit::TestCase::STARTED, name)
61
+ @_result = result
62
+
63
+ begin
64
+ begin
65
+ _run_setup_callbacks do
66
+ setup
67
+ __send__(@method_name)
68
+ mocha_verify(mocha_counter) if mocha_counter
69
+ end
70
+ rescue Mocha::ExpectationError => e
71
+ add_failure(e.message, e.backtrace)
72
+ rescue Test::Unit::AssertionFailedError => e
73
+ add_failure(e.message, e.backtrace)
74
+ rescue Exception => e
75
+ raise if PASSTHROUGH_EXCEPTIONS.include?(e.class)
76
+ add_error(e)
77
+ ensure
78
+ begin
79
+ teardown
80
+ _run_teardown_callbacks
81
+ rescue Test::Unit::AssertionFailedError => e
82
+ add_failure(e.message, e.backtrace)
83
+ rescue Exception => e
84
+ raise if PASSTHROUGH_EXCEPTIONS.include?(e.class)
85
+ add_error(e)
86
+ end
87
+ end
88
+ ensure
89
+ mocha_teardown if mocha_counter
90
+ end
91
+
92
+ result.add_run
93
+ yield(Test::Unit::TestCase::FINISHED, name)
94
+ end
95
+
96
+ protected
97
+
98
+ def retrieve_mocha_counter(result) #:nodoc:
99
+ if using_mocha = respond_to?(:mocha_verify)
100
+ if defined?(Mocha::TestCaseAdapter::AssertionCounter)
101
+ Mocha::TestCaseAdapter::AssertionCounter.new(result)
102
+ else
103
+ Mocha::Integration::TestUnit::AssertionCounter.new(result)
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,34 @@
1
+ require 'active_support'
2
+
3
+ module ActiveSupport
4
+ autoload :Duration, 'active_support/duration'
5
+ autoload :TimeWithZone, 'active_support/time_with_zone'
6
+ autoload :TimeZone, 'active_support/values/time_zone'
7
+
8
+ on_load_all do
9
+ [Duration, TimeWithZone, TimeZone]
10
+ end
11
+ end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ require 'active_support/core_ext/time/publicize_conversion_methods'
17
+ require 'active_support/core_ext/time/marshal'
18
+ require 'active_support/core_ext/time/acts_like'
19
+ require 'active_support/core_ext/time/calculations'
20
+ require 'active_support/core_ext/time/conversions'
21
+ require 'active_support/core_ext/time/zones'
22
+
23
+ require 'active_support/core_ext/date/acts_like'
24
+ require 'active_support/core_ext/date/freeze'
25
+ require 'active_support/core_ext/date/calculations'
26
+ require 'active_support/core_ext/date/conversions'
27
+
28
+ require 'active_support/core_ext/date_time/acts_like'
29
+ require 'active_support/core_ext/date_time/calculations'
30
+ require 'active_support/core_ext/date_time/conversions'
31
+ require 'active_support/core_ext/date_time/zones'
32
+
33
+ require 'active_support/core_ext/integer/time'
34
+ require 'active_support/core_ext/numeric/time'
@@ -0,0 +1,5 @@
1
+ module ActiveSupport
2
+ autoload :Duration, 'active_support/duration'
3
+ autoload :TimeWithZone, 'active_support/time_with_zone'
4
+ autoload :TimeZone, 'active_support/values/time_zone'
5
+ end
@@ -0,0 +1,341 @@
1
+ require "active_support/values/time_zone"
2
+ require 'active_support/core_ext/object/acts_like'
3
+
4
+ module ActiveSupport
5
+ # A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are
6
+ # limited to UTC and the system's <tt>ENV['TZ']</tt> zone.
7
+ #
8
+ # You shouldn't ever need to create a TimeWithZone instance directly via <tt>new</tt> -- instead, Rails provides the methods
9
+ # +local+, +parse+, +at+ and +now+ on TimeZone instances, and +in_time_zone+ on Time and DateTime instances, for a more
10
+ # user-friendly syntax. Examples:
11
+ #
12
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
13
+ # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
14
+ # Time.zone.parse('2007-02-01 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
15
+ # Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
16
+ # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
17
+ # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
18
+ #
19
+ # See Time and TimeZone for further documentation of these methods.
20
+ #
21
+ # TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangable. Examples:
22
+ #
23
+ # t = Time.zone.now # => Sun, 18 May 2008 13:27:25 EDT -04:00
24
+ # t.hour # => 13
25
+ # t.dst? # => true
26
+ # t.utc_offset # => -14400
27
+ # t.zone # => "EDT"
28
+ # t.to_s(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400"
29
+ # t + 1.day # => Mon, 19 May 2008 13:27:25 EDT -04:00
30
+ # t.beginning_of_year # => Tue, 01 Jan 2008 00:00:00 EST -05:00
31
+ # t > Time.utc(1999) # => true
32
+ # t.is_a?(Time) # => true
33
+ # t.is_a?(ActiveSupport::TimeWithZone) # => true
34
+ class TimeWithZone
35
+ def self.name
36
+ 'Time' # Report class name as 'Time' to thwart type checking
37
+ end
38
+
39
+ include Comparable
40
+ attr_reader :time_zone
41
+
42
+ def initialize(utc_time, time_zone, local_time = nil, period = nil)
43
+ @utc, @time_zone, @time = utc_time, time_zone, local_time
44
+ @period = @utc ? period : get_period_and_ensure_valid_local_time
45
+ end
46
+
47
+ # Returns a Time or DateTime instance that represents the time in +time_zone+.
48
+ def time
49
+ @time ||= period.to_local(@utc)
50
+ end
51
+
52
+ # Returns a Time or DateTime instance that represents the time in UTC.
53
+ def utc
54
+ @utc ||= period.to_utc(@time)
55
+ end
56
+ alias_method :comparable_time, :utc
57
+ alias_method :getgm, :utc
58
+ alias_method :getutc, :utc
59
+ alias_method :gmtime, :utc
60
+
61
+ # Returns the underlying TZInfo::TimezonePeriod.
62
+ def period
63
+ @period ||= time_zone.period_for_utc(@utc)
64
+ end
65
+
66
+ # Returns the simultaneous time in <tt>Time.zone</tt>, or the specified zone.
67
+ def in_time_zone(new_zone = ::Time.zone)
68
+ return self if time_zone == new_zone
69
+ utc.in_time_zone(new_zone)
70
+ end
71
+
72
+ # Returns a <tt>Time.local()</tt> instance of the simultaneous time in your system's <tt>ENV['TZ']</tt> zone
73
+ def localtime
74
+ utc.getlocal
75
+ end
76
+ alias_method :getlocal, :localtime
77
+
78
+ def dst?
79
+ period.dst?
80
+ end
81
+ alias_method :isdst, :dst?
82
+
83
+ def utc?
84
+ time_zone.name == 'UTC'
85
+ end
86
+ alias_method :gmt?, :utc?
87
+
88
+ def utc_offset
89
+ period.utc_total_offset
90
+ end
91
+ alias_method :gmt_offset, :utc_offset
92
+ alias_method :gmtoff, :utc_offset
93
+
94
+ def formatted_offset(colon = true, alternate_utc_string = nil)
95
+ utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
96
+ end
97
+
98
+ # Time uses +zone+ to display the time zone abbreviation, so we're duck-typing it.
99
+ def zone
100
+ period.zone_identifier.to_s
101
+ end
102
+
103
+ def inspect
104
+ "#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
105
+ end
106
+
107
+ def xmlschema(fraction_digits = 0)
108
+ fraction = if fraction_digits > 0
109
+ ".%i" % time.usec.to_s[0, fraction_digits]
110
+ end
111
+
112
+ "#{time.strftime("%Y-%m-%dT%H:%M:%S")}#{fraction}#{formatted_offset(true, 'Z')}"
113
+ end
114
+ alias_method :iso8601, :xmlschema
115
+
116
+ # Coerces the date to a string for JSON encoding. The default format is ISO 8601. You can get
117
+ # %Y/%m/%d %H:%M:%S +offset style by setting ActiveSupport::JSON::Encoding.use_standard_json_time_format
118
+ # to false.
119
+ #
120
+ # ==== Examples
121
+ #
122
+ # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
123
+ # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
124
+ # # => "2005-02-01T15:15:10Z"
125
+ #
126
+ # # With ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
127
+ # Time.utc(2005,2,1,15,15,10).in_time_zone.to_json
128
+ # # => "2005/02/01 15:15:10 +0000"
129
+ def as_json(options = nil)
130
+ if ActiveSupport::JSON::Encoding.use_standard_json_time_format
131
+ xmlschema
132
+ else
133
+ %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
134
+ end
135
+ end
136
+
137
+ def to_yaml(options = {})
138
+ if options.kind_of?(YAML::Emitter)
139
+ utc.to_yaml(options)
140
+ else
141
+ time.to_yaml(options).gsub('Z', formatted_offset(true, 'Z'))
142
+ end
143
+ end
144
+
145
+ def httpdate
146
+ utc.httpdate
147
+ end
148
+
149
+ def rfc2822
150
+ to_s(:rfc822)
151
+ end
152
+ alias_method :rfc822, :rfc2822
153
+
154
+ # <tt>:db</tt> format outputs time in UTC; all others output time in local.
155
+ # Uses TimeWithZone's +strftime+, so <tt>%Z</tt> and <tt>%z</tt> work correctly.
156
+ def to_s(format = :default)
157
+ if format == :db
158
+ utc.to_s(format)
159
+ elsif formatter = ::Time::DATE_FORMATS[format]
160
+ formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
161
+ else
162
+ "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby 1.9 Time#to_s format
163
+ end
164
+ end
165
+ alias_method :to_formatted_s, :to_s
166
+
167
+ # Replaces <tt>%Z</tt> and <tt>%z</tt> directives with +zone+ and +formatted_offset+, respectively, before passing to
168
+ # Time#strftime, so that zone information is correct
169
+ def strftime(format)
170
+ format = format.gsub('%Z', zone).gsub('%z', formatted_offset(false))
171
+ time.strftime(format)
172
+ end
173
+
174
+ # Use the time in UTC for comparisons.
175
+ def <=>(other)
176
+ utc <=> other
177
+ end
178
+
179
+ def between?(min, max)
180
+ utc.between?(min, max)
181
+ end
182
+
183
+ def past?
184
+ utc.past?
185
+ end
186
+
187
+ def today?
188
+ time.today?
189
+ end
190
+
191
+ def future?
192
+ utc.future?
193
+ end
194
+
195
+ def eql?(other)
196
+ utc == other
197
+ end
198
+
199
+ def +(other)
200
+ # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
201
+ # otherwise move forward from #utc, for accuracy when moving across DST boundaries
202
+ if duration_of_variable_length?(other)
203
+ method_missing(:+, other)
204
+ else
205
+ result = utc.acts_like?(:date) ? utc.since(other) : utc + other rescue utc.since(other)
206
+ result.in_time_zone(time_zone)
207
+ end
208
+ end
209
+
210
+ def -(other)
211
+ # If we're subtracting a Duration of variable length (i.e., years, months, days), move backwards from #time,
212
+ # otherwise move backwards #utc, for accuracy when moving across DST boundaries
213
+ if other.acts_like?(:time)
214
+ utc.to_f - other.to_f
215
+ elsif duration_of_variable_length?(other)
216
+ method_missing(:-, other)
217
+ else
218
+ result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other)
219
+ result.in_time_zone(time_zone)
220
+ end
221
+ end
222
+
223
+ def since(other)
224
+ # If we're adding a Duration of variable length (i.e., years, months, days), move forward from #time,
225
+ # otherwise move forward from #utc, for accuracy when moving across DST boundaries
226
+ if duration_of_variable_length?(other)
227
+ method_missing(:since, other)
228
+ else
229
+ utc.since(other).in_time_zone(time_zone)
230
+ end
231
+ end
232
+
233
+ def ago(other)
234
+ since(-other)
235
+ end
236
+
237
+ def advance(options)
238
+ # If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
239
+ # otherwise advance from #utc, for accuracy when moving across DST boundaries
240
+ if options.values_at(:years, :weeks, :months, :days).any?
241
+ method_missing(:advance, options)
242
+ else
243
+ utc.advance(options).in_time_zone(time_zone)
244
+ end
245
+ end
246
+
247
+ %w(year mon month day mday wday yday hour min sec to_date).each do |method_name|
248
+ class_eval <<-EOV, __FILE__, __LINE__ + 1
249
+ def #{method_name} # def month
250
+ time.#{method_name} # time.month
251
+ end # end
252
+ EOV
253
+ end
254
+
255
+ def usec
256
+ time.respond_to?(:usec) ? time.usec : 0
257
+ end
258
+
259
+ def to_a
260
+ [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
261
+ end
262
+
263
+ def to_f
264
+ utc.to_f
265
+ end
266
+
267
+ def to_i
268
+ utc.to_i
269
+ end
270
+ alias_method :hash, :to_i
271
+ alias_method :tv_sec, :to_i
272
+
273
+ # A TimeWithZone acts like a Time, so just return +self+.
274
+ def to_time
275
+ self
276
+ end
277
+
278
+ def to_datetime
279
+ utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
280
+ end
281
+
282
+ # So that +self+ <tt>acts_like?(:time)</tt>.
283
+ def acts_like_time?
284
+ true
285
+ end
286
+
287
+ # Say we're a Time to thwart type checking.
288
+ def is_a?(klass)
289
+ klass == ::Time || super
290
+ end
291
+ alias_method :kind_of?, :is_a?
292
+
293
+ def freeze
294
+ period; utc; time # preload instance variables before freezing
295
+ super
296
+ end
297
+
298
+ def marshal_dump
299
+ [utc, time_zone.name, time]
300
+ end
301
+
302
+ def marshal_load(variables)
303
+ initialize(variables[0].utc, ::Time.__send__(:get_zone, variables[1]), variables[2].utc)
304
+ end
305
+
306
+ # Ensure proxy class responds to all methods that underlying time instance responds to.
307
+ def respond_to?(sym, include_priv = false)
308
+ # consistently respond false to acts_like?(:date), regardless of whether #time is a Time or DateTime
309
+ return false if sym.to_s == 'acts_like_date?'
310
+ super || time.respond_to?(sym, include_priv)
311
+ end
312
+
313
+ # Send the missing method to +time+ instance, and wrap result in a new TimeWithZone with the existing +time_zone+.
314
+ def method_missing(sym, *args, &block)
315
+ result = time.__send__(sym, *args, &block)
316
+ result.acts_like?(:time) ? self.class.new(nil, time_zone, result) : result
317
+ end
318
+
319
+ private
320
+ def get_period_and_ensure_valid_local_time
321
+ # we don't want a Time.local instance enforcing its own DST rules as well,
322
+ # so transfer time values to a utc constructor if necessary
323
+ @time = transfer_time_values_to_utc_constructor(@time) unless @time.utc?
324
+ begin
325
+ @time_zone.period_for_local(@time)
326
+ rescue ::TZInfo::PeriodNotFound
327
+ # time is in the "spring forward" hour gap, so we're moving the time forward one hour and trying again
328
+ @time += 1.hour
329
+ retry
330
+ end
331
+ end
332
+
333
+ def transfer_time_values_to_utc_constructor(time)
334
+ ::Time.utc_time(time.year, time.month, time.day, time.hour, time.min, time.sec, time.respond_to?(:usec) ? time.usec : 0)
335
+ end
336
+
337
+ def duration_of_variable_length?(obj)
338
+ ActiveSupport::Duration === obj && obj.parts.any? {|p| [:years, :months, :days].include? p[0] }
339
+ end
340
+ end
341
+ end