openwferu 0.9.1 → 0.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. data/{README → README.txt} +16 -13
  2. data/bin/validate-workflow.rb +46 -22
  3. data/examples/README.txt +8 -0
  4. data/examples/homeworkreview.rb +66 -0
  5. data/examples/quotereporter.rb +154 -0
  6. data/lib/{openwferu.rb → openwfe.rb} +6 -8
  7. data/lib/{ru → openwfe}/contextual.rb +11 -3
  8. data/lib/{ru → openwfe/engine}/engine.rb +50 -36
  9. data/lib/{ru/participant.rb → openwfe/engine/file_persisted_engine.rb} +21 -22
  10. data/lib/openwfe/expool/expressionpool.rb +534 -0
  11. data/lib/openwfe/expool/expstorage.rb +184 -0
  12. data/lib/openwfe/expool/journalexpstorage.rb +312 -0
  13. data/lib/openwfe/expool/yamlexpstorage.rb +127 -0
  14. data/lib/{ru → openwfe/expressions}/environment.rb +19 -14
  15. data/lib/{ru → openwfe/expressions}/expressionmap.rb +48 -21
  16. data/lib/{ru → openwfe/expressions}/fe_concurrence.rb +111 -35
  17. data/lib/openwfe/expressions/fe_cursor.rb +236 -0
  18. data/lib/{ru → openwfe/expressions}/fe_define.rb +5 -5
  19. data/lib/openwfe/expressions/fe_fqv.rb +99 -0
  20. data/lib/openwfe/expressions/fe_iterator.rb +182 -0
  21. data/lib/{ru/fe_misc.rb → openwfe/expressions/fe_losfor.rb} +14 -56
  22. data/lib/openwfe/expressions/fe_misc.rb +102 -0
  23. data/lib/{ru → openwfe/expressions}/fe_participant.rb +25 -14
  24. data/lib/{ru → openwfe/expressions}/fe_raw.rb +39 -75
  25. data/lib/{ru/fe_base.rb → openwfe/expressions/fe_sequence.rb} +40 -35
  26. data/lib/{ru → openwfe/expressions}/fe_subprocess.rb +30 -14
  27. data/lib/{ru → openwfe/expressions}/fe_time.rb +59 -31
  28. data/lib/{ru → openwfe/expressions}/fe_utils.rb +42 -26
  29. data/lib/{ru → openwfe/expressions}/fe_value.rb +20 -14
  30. data/lib/openwfe/expressions/flowexpression.rb +434 -0
  31. data/lib/openwfe/expressions/raw_prog.rb +391 -0
  32. data/lib/openwfe/expressions/raw_xml.rb +128 -0
  33. data/lib/openwfe/flowexpressionid.rb +148 -0
  34. data/lib/{ru → openwfe}/logging.rb +10 -6
  35. data/lib/{osocket.rb → openwfe/osocket.rb} +36 -35
  36. data/lib/{otime.rb → openwfe/otime.rb} +71 -21
  37. data/lib/openwfe/participants/atomparticipants.rb +144 -0
  38. data/lib/openwfe/participants/enoparticipant.rb +73 -0
  39. data/lib/openwfe/participants/participant.rb +85 -0
  40. data/lib/{ru → openwfe/participants}/participantmap.rb +40 -12
  41. data/lib/{ru → openwfe/participants}/participants.rb +41 -12
  42. data/lib/openwfe/participants/soapparticipants.rb +96 -0
  43. data/lib/{controlclient.rb → openwfe/rest/controlclient.rb} +12 -13
  44. data/lib/{definitions.rb → openwfe/rest/definitions.rb} +3 -3
  45. data/lib/{exception.rb → openwfe/rest/exception.rb} +3 -3
  46. data/lib/{restclient.rb → openwfe/rest/restclient.rb} +13 -22
  47. data/lib/{worklistclient.rb → openwfe/rest/worklistclient.rb} +33 -46
  48. data/lib/openwfe/rest/xmlcodec.rb +575 -0
  49. data/lib/{ru → openwfe}/rudefinitions.rb +32 -4
  50. data/lib/{ru → openwfe}/service.rb +20 -8
  51. data/lib/openwfe/storage/yamlfilestorage.rb +159 -0
  52. data/lib/{ru → openwfe/util}/dollar.rb +10 -8
  53. data/lib/openwfe/util/lru_cache.rb +149 -0
  54. data/lib/{ru → openwfe/util}/scheduler.rb +18 -10
  55. data/lib/{ru → openwfe/util}/schedulers.rb +7 -7
  56. data/lib/{utils.rb → openwfe/utils.rb} +93 -9
  57. data/lib/openwfe/workitem.rb +366 -0
  58. data/lib/openwfe/worklist/worklists.rb +175 -0
  59. data/test/README.txt +27 -0
  60. data/test/atomtest.rb +99 -0
  61. data/test/crontest.rb +58 -0
  62. data/test/dollartest.rb +3 -3
  63. data/test/feitest.rb +42 -14
  64. data/test/file_persistence_test.rb +93 -0
  65. data/test/flowtestbase.rb +72 -26
  66. data/test/ft_0.rb +1 -97
  67. data/test/ft_0b_sequence.rb +33 -0
  68. data/test/ft_0c_testname.rb +29 -0
  69. data/test/ft_10_loop.rb +48 -0
  70. data/test/ft_11_ppd.rb +292 -0
  71. data/test/ft_12_blockparticipant.rb +45 -0
  72. data/test/ft_13_eno.rb +51 -0
  73. data/test/ft_14_subprocess.rb +90 -0
  74. data/test/ft_14b_subprocess.rb +40 -0
  75. data/test/ft_15_iterator.rb +70 -0
  76. data/test/ft_16_fqv.rb +57 -0
  77. data/test/ft_1_unset.rb +25 -1
  78. data/test/ft_2_concurrence.rb +10 -5
  79. data/test/ft_3_equals.rb +35 -1
  80. data/test/ft_4_misc.rb +16 -1
  81. data/test/ft_5_time.rb +26 -1
  82. data/test/ft_6_lambda.rb +2 -1
  83. data/test/{ft_7_losfor.rb → ft_7_lose.rb} +41 -35
  84. data/test/ft_8_forget.rb +46 -0
  85. data/test/ft_9_cursor.rb +94 -0
  86. data/test/journal_persistence_test.rb +147 -0
  87. data/test/misctest.rb +13 -9
  88. data/test/rake_ptest.rb +18 -0
  89. data/test/rake_qtest.rb +43 -0
  90. data/test/{fulltest.rb → rake_test.rb} +2 -2
  91. data/test/raw_prog_test.rb +236 -0
  92. data/test/rest_test.rb +189 -0
  93. data/test/rutest_utils.rb +1 -1
  94. data/test/timetest.rb +42 -34
  95. metadata +125 -82
  96. data/lib/codec.rb +0 -573
  97. data/lib/flowexpressionid.rb +0 -139
  98. data/lib/ru/expressionpool.rb +0 -382
  99. data/lib/ru/expressionstorage.rb +0 -99
  100. data/lib/ru/flowexpression.rb +0 -272
  101. data/lib/ru/ruutils.rb +0 -70
  102. data/lib/test.rb +0 -222
  103. data/lib/workitem.rb +0 -249
  104. data/test/quicktest.rb +0 -21
@@ -0,0 +1,148 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2005-2007, John Mettraux, OpenWFE.org
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # . Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # . Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # . Neither the name of the "OpenWFE" nor the names of its contributors may be
17
+ # used to endorse or promote products derived from this software without
18
+ # specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #++
32
+ #
33
+ # $Id: workitem.rb 3555 2006-11-13 00:47:53Z jmettraux $
34
+ #
35
+
36
+ #
37
+ # "hecho en Costa Rica"
38
+ # enhanced in Japan
39
+ #
40
+ # john.mettraux@openwfe.org
41
+ #
42
+
43
+
44
+ module OpenWFE
45
+
46
+ #
47
+ # FlowExpressionId
48
+ #
49
+ class FlowExpressionId
50
+
51
+ attr_accessor \
52
+ :owfe_version, \
53
+ :engine_id, \
54
+ :initial_engine_id, \
55
+ :workflow_definition_url, \
56
+ :workflow_definition_name, \
57
+ :workflow_definition_revision, \
58
+ :workflow_instance_id, \
59
+ :expression_name, \
60
+ :expression_id
61
+
62
+ #
63
+ # overrides the classical to_s()
64
+ #
65
+ def to_s ()
66
+ return "(fei #{@owfe_version} #{@engine_id}/#{@initial_engine_id} #{@workflow_definition_url} #{@workflow_definition_name} #{@workflow_definition_revision} #{@workflow_instance_id} #{@expression_name} #{@expression_id})"
67
+ end
68
+
69
+ def hash ()
70
+ return to_s().hash()
71
+ end
72
+
73
+ def == (other)
74
+ return false if not other.kind_of?(FlowExpressionId)
75
+
76
+ @owfe_version == other.owfe_version and
77
+ @engine_id == other.engine_id and
78
+ @initial_engine_id == other.initial_engine_id and
79
+ @workflow_definition_url == other.workflow_definition_url and
80
+ @workflow_definition_name == other.workflow_definition_name and
81
+ @workflow_definition_revision == other.workflow_definition_revision and
82
+ @workflow_instance_id == other.workflow_instance_id and
83
+ @expression_name == other.expression_name and
84
+ @expression_id == other.expression_id
85
+ end
86
+
87
+ def dup
88
+ n = FlowExpressionId.new
89
+ n.owfe_version = @owfe_version.dup
90
+ n.engine_id = @engine_id.dup
91
+ n.initial_engine_id = @initial_engine_id.dup
92
+ n.workflow_definition_url = @workflow_definition_url.dup
93
+ n.workflow_definition_name = @workflow_definition_name.dup
94
+ n.workflow_definition_revision = @workflow_definition_revision.dup
95
+ n.workflow_instance_id = @workflow_instance_id.dup
96
+ n.expression_name = @expression_name.dup
97
+ n.expression_id = @expression_id.dup
98
+ return n
99
+ end
100
+
101
+ alias eql? ==
102
+
103
+ alias to_debug_s to_s
104
+ #def to_debug_s
105
+ # "#{to_s} (h#{hash}) (i#{object_id})"
106
+ #end
107
+
108
+ #
109
+ # Returns the workflow instance id without any subflow indices.
110
+ # For example, if the wfid is "1234.0.1", this method will
111
+ # return "1234".
112
+ #
113
+ def parent_workflow_instance_id
114
+ i = workflow_instance_id.index(".")
115
+ return workflow_instance_id if not i
116
+ #return workflow_instance_id[0..i]
117
+ return workflow_instance_id[0..i-1]
118
+ end
119
+
120
+ #
121
+ # This class method parses a string into a FlowExpressionId instance
122
+ #
123
+ def FlowExpressionId.to_fei (string)
124
+
125
+ fei = FlowExpressionId.new()
126
+
127
+ ss = string.split(" ")
128
+ #puts "\n#{ss}"
129
+
130
+ fei.owfe_version = ss[1]
131
+
132
+ ssRawEngineId = ss[2].split("/")
133
+ fei.engine_id= ssRawEngineId[0]
134
+ fei.initial_engine_id= ssRawEngineId[1]
135
+
136
+ fei.workflow_definition_url = ss[3]
137
+ fei.workflow_definition_name = ss[4]
138
+ fei.workflow_definition_revision = ss[5]
139
+ fei.workflow_instance_id = ss[6]
140
+ fei.expression_name = ss[7]
141
+ fei.expression_id = ss[8][0..-2]
142
+
143
+ return fei
144
+ end
145
+ end
146
+
147
+ end
148
+
@@ -1,6 +1,6 @@
1
1
  #
2
- #<tt>
3
- # Copyright (c) 2006, John Mettraux, OpenWFE.org
2
+ #--
3
+ # Copyright (c) 2006-2007, John Mettraux, OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
28
28
  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
29
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
30
  # POSSIBILITY OF SUCH DAMAGE.
31
- #</tt>
31
+ #++
32
32
  #
33
33
  # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
34
  #
@@ -40,10 +40,14 @@
40
40
  #
41
41
 
42
42
  require 'logger'
43
- require 'ru/rudefinitions'
43
+ require 'openwfe/rudefinitions'
44
44
 
45
- module OpenWFEru
46
45
 
46
+ module OpenWFE
47
+
48
+ #
49
+ # A Mixin for adding logging method to any class
50
+ #
47
51
  module Logging
48
52
 
49
53
  def init_default_logging (filename)
@@ -74,7 +78,7 @@ module OpenWFEru
74
78
  end
75
79
 
76
80
  def who
77
- if respond_to?(:service_name)
81
+ if respond_to? :service_name
78
82
  "#{self.class} '#{self.service_name}'"
79
83
  else
80
84
  "#{self.class}"
@@ -1,6 +1,6 @@
1
1
  #
2
- #<tt>
3
- # Copyright (c) 2006, John Mettraux, OpenWFE.org
2
+ #--
3
+ # Copyright (c) 2006-2007, John Mettraux, OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -28,13 +28,14 @@
28
28
  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
29
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
30
  # POSSIBILITY OF SUCH DAMAGE.
31
- #</tt>
31
+ #++
32
32
  #
33
33
  # $Id: codec.rb 2515 2006-04-26 18:38:39Z jmettraux $
34
34
  #
35
35
 
36
36
  require 'socket'
37
- require 'codec'
37
+ require 'xmlcodec'
38
+
38
39
 
39
40
  module OpenWFE
40
41
 
@@ -82,11 +83,14 @@ module OpenWFE
82
83
  end
83
84
 
84
85
  #
85
- # dispatches a workitem over TCP
86
+ # Dispatches a workitem over TCP, the workitem will be
87
+ # encoded with XML
88
+ # The default encode_method is
86
89
  #
87
- def OpenWFE.dispatchWorkitem (host, port, workitem)
90
+ def OpenWFE.dispatch_workitem (host, port, workitem)
91
+
92
+ sXml = OpenWFE.xml_encode(workitem)
88
93
 
89
- sXml = OpenWFE.encode(workitem)
90
94
  socket = TCPSocket.new(host, port)
91
95
  socket.puts "xmlCoder #{sXml.length}"
92
96
  socket.puts
@@ -103,38 +107,35 @@ module OpenWFE
103
107
  #puts "dispatch() reply is >#{reply}<"
104
108
  end
105
109
 
106
- class OwfeHook
107
- end
108
-
109
110
  end
110
111
 
111
112
 
112
113
  #
113
114
  # some test code
114
115
 
115
- sl = OpenWFE::SocketListener.new('127.0.0.1', 7010)
116
-
117
- puts "..ready.."
118
-
119
- sl.listen do |workitem|
120
-
121
- #puts workitem
122
- #next
123
-
124
- puts workitem.flowExpressionId
125
- puts "...history length : #{workitem.history.length}"
126
-
127
- #puts workitem.history
128
- workitem.history.each do |hi|
129
- puts ".....hi = '#{hi.text}' #{hi.date}"
130
- end
131
-
132
- #hi = OpenWFE::HistoryItem.new
133
- #hi.author = 'osocket.rb'
134
- #workitem.history.push(hi)
135
-
136
- workitem.attributes['ruby?'] = 'yes'
137
-
138
- OpenWFE.dispatchWorkitem('127.0.0.1', 7007, workitem)
139
- end
116
+ #sl = OpenWFE::SocketListener.new('127.0.0.1', 7010)
117
+ #
118
+ #puts "..ready.."
119
+ #
120
+ #sl.listen do |workitem|
121
+ #
122
+ # #puts workitem
123
+ # #next
124
+ #
125
+ # puts workitem.flow_expression_id
126
+ # puts "...history length : #{workitem.history.length}"
127
+ #
128
+ # #puts workitem.history
129
+ # workitem.history.each do |hi|
130
+ # puts ".....hi = '#{hi.text}' #{hi.date}"
131
+ # end
132
+ #
133
+ # #hi = OpenWFE::HistoryItem.new
134
+ # #hi.author = 'osocket.rb'
135
+ # #workitem.history.push(hi)
136
+ #
137
+ # workitem.attributes['ruby?'] = 'yes'
138
+ #
139
+ # OpenWFE.dispatch_workitem('127.0.0.1', 7007, workitem)
140
+ #end
140
141
 
@@ -1,6 +1,6 @@
1
1
  #
2
- #<tt>
3
- # Copyright (c) 2005-2006, John Mettraux, OpenWFE.org
2
+ #--
3
+ # Copyright (c) 2005-2007, John Mettraux, OpenWFE.org
4
4
  # All rights reserved.
5
5
  #
6
6
  # Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
28
28
  # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
29
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
30
  # POSSIBILITY OF SUCH DAMAGE.
31
- #</tt>
31
+ #++
32
32
  #
33
33
  # $Id: otime.rb 3509 2006-10-21 12:00:52Z jmettraux $
34
34
  #
@@ -39,12 +39,13 @@
39
39
  # john.mettraux@openwfe.org
40
40
  #
41
41
 
42
- require 'parsedate'
42
+ require 'date'
43
+ #require 'parsedate'
43
44
 
44
45
 
45
46
  module OpenWFE
46
47
 
47
- TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
48
+ #TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
48
49
 
49
50
  #
50
51
  # Returns the current time as an ISO date string
@@ -53,35 +54,42 @@ module OpenWFE
53
54
  return to_iso_date(Time.new())
54
55
  end
55
56
 
56
- def OpenWFE.to_iso_date (date)
57
+ def OpenWFE.to_iso8601_date (date)
57
58
 
58
- if date.kind_of?(Float)
59
- date = Time.at(date)
59
+ if date.kind_of? Float
60
+ date = to_datetime(Time.at(date))
61
+ elsif date.kind_of? Time
62
+ date = to_datetime(date)
63
+ elsif not date.kind_of? Date
64
+ date = DateTime.parse(date)
60
65
  end
61
66
 
62
- s = date.getutc().strftime(TIME_FORMAT)
63
- o = date.utc_offset / 3600
64
- o = o.to_s() + "00"
65
- o = "0" + o if o.length < 4
66
- o = "+" + o unless o[0..1] == '-'
67
- return s + " " + o.to_s()
67
+ s = date.to_s
68
+ s[10] = " "
69
+
70
+ return s
68
71
  end
69
72
 
70
73
  #
71
- # Returns a Ruby time
74
+ # the old method we used to generate our ISO datetime strings
72
75
  #
73
- def OpenWFE.toRubyTime (isoDate)
76
+ def OpenWFE.time_to_iso8601_date (time)
77
+
78
+ s = time.getutc().strftime(TIME_FORMAT)
79
+ o = time.utc_offset / 3600
80
+ o = o.to_s + "00"
81
+ o = "0" + o if o.length < 4
82
+ o = "+" + o unless o[0..1] == '-'
74
83
 
75
- res = ParseDate.parsedate(isoDate)
76
- return Time.local(*res)
84
+ s + " " + o.to_s
77
85
  end
78
86
 
79
87
  #
80
- # An Ruby-friendly alias for toRubyTime()
88
+ # Returns a Ruby time
81
89
  #
82
90
  def OpenWFE.to_ruby_time (iso_date)
83
91
 
84
- return toRubyTime(iso_date)
92
+ return DateTime.parse(iso_date)
85
93
  end
86
94
 
87
95
  #def OpenWFE.parse_date (date)
@@ -91,6 +99,7 @@ module OpenWFE
91
99
  # equivalent to java.lang.System.currentTimeMillis()
92
100
  #
93
101
  def OpenWFE.current_time_millis ()
102
+
94
103
  t = Time.new()
95
104
  t = t.to_f * 1000
96
105
  return t.to_i
@@ -122,7 +131,7 @@ module OpenWFE
122
131
 
123
132
  if index >= string.length
124
133
  if number.length > 0
125
- result = result + (Integer(number) / 1000)
134
+ result = result + (Float(number) / 1000.0)
126
135
  end
127
136
  break
128
137
  end
@@ -157,6 +166,47 @@ module OpenWFE
157
166
  return (c >= "0" and c <= "9")
158
167
  end
159
168
 
169
+ #
170
+ # conversion methods between Date[Time] and Time
171
+
172
+ #
173
+ # Ruby Cookbook 1st edition p.111
174
+ # http://www.oreilly.com/catalog/rubyckbk/
175
+ # a must
176
+ #
177
+
178
+ #
179
+ # converts a Time instance to a DateTime one
180
+ #
181
+ def OpenWFE.to_datetime (time)
182
+
183
+ s = time.sec + Rational(time.usec, 10**6)
184
+ o = Rational(time.utc_offset, 3600 * 24)
185
+
186
+ begin
187
+ return DateTime.new(
188
+ time.year, time.month, time.day, time.hour, time.min, s, o)
189
+ rescue Exception => e
190
+ puts \
191
+ "\n Date.new() problem. Params :"+
192
+ "\n....y:#{time.year} M:#{time.month} d:#{time.day} "+
193
+ "h:#{time.hour} m:#{time.min} s:#{s} o:#{o}"
194
+ end
195
+ end
196
+
197
+ def OpenWFE.to_gm_time (dtime)
198
+ to_ttime(dtime.new_offset, :gm)
199
+ end
200
+
201
+ def OpenWFE.to_local_time (dtime)
202
+ to_ttime(dtime.new_offset(DateTime.now.offset-offset), :local)
203
+ end
204
+
205
+ def to_ttime (d, method)
206
+ usec = (d.sec_fraction * 3600 * 24 * (10**6)).to_i
207
+ Time.send(method, d.year, d.month, d.day, d.hour, d.min, d.sec, usec)
208
+ end
209
+
160
210
  protected
161
211
 
162
212
  DURATIONS = {