source: ruby/trunk/lib/models/rm/data_types/quantity/date_time.rb@ 151

Last change on this file since 151 was 151, checked in by KOBAYASHI, Shinji, 15 years ago

fixed #49

File size: 8.7 KB
Line 
1# This module is implementation of the UML:
2# http://www.openehr.org/uml/release-1.0.1/Browsable/_9_0_76d0249_1109696321450_28117_5362Report.html
3# Ticket refs #49
4require 'assumed_library_types'
5require 'date'
6
7module OpenEHR
8 module RM
9 module Data_Types
10 module Quantity
11 module Date_Time
12 class DV_Temporal < OpenEHR::RM::Data_Types::Quantity::DV_Absolute_Quantity
13 attr_reader :value
14
15 def initialize(value, magnitude_status=nil, accuracy=nil,
16 normal_range=nil, normal_status=nil,
17 other_reference_ranges=nil)
18 self.value = value
19 self.magnitude_status = magnitude_status
20 self.accuracy = accuracy
21 self.normal_range = normal_range
22 self.normal_status = normal_status
23 self.other_reference_ranges = other_reference_ranges
24 end
25
26 def value=(value)
27 if value.nil? or value.empty?
28 raise ArgumentError, 'invalid value'
29 end
30 @value = value
31 end
32 end
33
34 class DV_Date < DV_Temporal
35 include OpenEHR::Assumed_Library_Types::ISO8601_DATE_MODULE
36
37 DAYS_IN_MONTH = [0,31,28,31,30,31,30,31,31,30,31,30,31]
38
39 def initialize(value, magnitude_status=nil, accuracy=nil,
40 normal_range=nil, normal_status=nil,
41 other_reference_range=nil)
42 super(value, magnitude_status, accuracy, normal_range,
43 normal_status, other_reference_range)
44 end
45
46 def value=(value)
47 super(value)
48 iso8601_date = Assumed_Library_Types::ISO8601_DATE.new(value)
49 @year = iso8601_date.year
50 @month = iso8601_date.month
51 @day = iso8601_date.day
52 end
53
54 undef magnitude=
55
56 def magnitude
57 return Date.new(@year, @month, @day)-Date.new(0000,1,1)
58 end
59
60 def diff(other)
61 if self.magnitude > other.magnitude
62 past, future = other, self
63 else
64 past, future = self, other
65 end
66 year, month, day = 0, 0, 0
67 if (future.day >= past.day)
68 day = future.day - past.day
69 else
70 month -= 1
71 previous_month = future.month - 1
72 if previous_month <= 0
73 previous_month = 12
74 end
75 day = DAYS_IN_MONTH[previous_month] + future.day - past.day
76 if leapyear?(future.year) && (previous_month == 2)
77 day += 1
78 end
79 end
80 week = day / 7
81 if (future.month >= past.month)
82 month += future.month - past.month
83 else
84 year -= 1
85 month += future.month + 12 - past.month
86 end
87 year += future.year - past.year
88 return DV_Duration.new(
89 'P' + year.to_s + 'Y' + month.to_s + 'M' +
90 week.to_s + 'W' + day.to_s + 'D')
91 end
92 end
93
94 class DV_Time < DV_Temporal
95 include OpenEHR::Assumed_Library_Types::ISO8601_TIME_MODULE
96 def initialize(value, magnitude_status=nil, accuracy=nil,
97 normal_range=nil, normal_status=nil,
98 other_reference_range=nil)
99 super(value, magnitude_status, accuracy, normal_range,
100 normal_status, other_reference_range)
101 end
102
103 def value=(value)
104 super(value)
105 iso8601_time = Assumed_Library_Types::ISO8601_TIME.new(value)
106 @hour = iso8601_time.hour
107 @minute = iso8601_time.minute
108 @second = iso8601_time.second
109 @fractional_second = iso8601_time.fractional_second
110 end
111
112 def magnitude
113 return @hour * 60 * 60 + @minute * 60 + @second + @fractional_second
114 end
115
116 def diff(other)
117 diff = (other.magnitude - self.magnitude).abs
118 hour = (diff / 60 / 60).to_i
119 minute = ((diff - hour*60*60)/60).to_i
120 second = (diff - hour * 60 *60 - minute * 60).to_i
121 fractional_second = ((diff - diff.to_i)*1000000.0).to_i/1000000.0
122 return DV_Duration.new('P0Y0M0W0DT' + hour.to_s + 'H' +
123 minute.to_s + 'M' +
124 second.to_s + fractional_second.to_s[1..-1] + 'S')
125 end
126 end
127
128 class DV_Date_Time < DV_Temporal
129 include OpenEHR::Assumed_Library_Types::ISO8601_DATE_TIME_MODULE
130 attr_reader :value
131
132 def initialize(value, magnitude_status=nil, accuracy=nil,
133 normal_range=nil, normal_status=nil,
134 other_reference_range=nil)
135 super(value, magnitude_status, accuracy, normal_range,
136 normal_status, other_reference_range)
137 end
138
139 def value=(value)
140 super(value)
141 iso8601date_time = Assumed_Library_Types::ISO8601_DATE_TIME.new(value)
142 self.year = iso8601date_time.year
143 self.month = iso8601date_time.month
144 self.day = iso8601date_time.day
145 self.minute = iso8601date_time.minute
146 self.second = iso8601date_time.second
147 self.hour = iso8601date_time.hour
148 self.fractional_second = iso8601date_time.fractional_second
149 self.timezone = iso8601date_time.timezone
150 end
151
152 def magnitude
153 return DateTime.new(@year,@month,@day,@hour,@minute,@second) -
154 DateTime.new(0000,1,1,0,0,0) + @fractional_second
155 end
156
157 undef magnitude=
158
159 def diff(other)
160 if self.magnitude >= other.magnitude
161 past, future = other, self
162 else
163 past, future = self, other
164 end
165 past_date, past_time = split_date_time(past)
166 future_date, future_time = split_date_time(future)
167 time_diff = future_time.magnitude - past_time.magnitude
168 if future_time.magnitude < past_time.magnitude
169 future_date.day = future_date.day - 1
170 time_diff += 24 * 60 * 60
171 end
172 date_duration = past_date.diff(future_date)
173 hour = (time_diff / 60 / 60).to_i
174 minute = ((time_diff - hour*60*60)/60).to_i
175 second = (time_diff - hour * 60 *60 - minute * 60).to_i
176 fractional_second = ((time_diff - time_diff.to_i)*1000000.0).to_i/1000000.0
177
178 return DV_Duration.new(date_duration.value + 'T' +
179 hour.to_s + 'H' +
180 minute.to_s + 'M' +
181 second.to_s + fractional_second.to_s[1..-1] + 'S')
182
183 end
184
185 private
186
187 def split_date_time(date_time)
188 /^(.*)T(.*)$/ =~ date_time.as_string
189 return DV_Date.new($1), DV_Time.new($2)
190 end
191 end
192
193 class DV_Duration < DV_Amount
194 include Assumed_Library_Types::ISO8601_DURATION_MODULE
195 attr_reader :value
196
197 def initialize(value, magnitude_status=nil, accuracy=nil,
198 accuracy_percent=nil, normal_range=nil,
199 normal_status = nil, other_reference_ranges=nil)
200 self.value = value
201 end
202
203 def value=(value)
204 raise ArgumentError, 'value must be not nil' if value.nil?
205 @value = value
206 iso8601_duration = Assumed_Library_Types::ISO8601_DURATION.new(value)
207 self.years = iso8601_duration.years
208 self.months = iso8601_duration.months
209 self.weeks = iso8601_duration.weeks
210 self.days = iso8601_duration.days
211 self.hours = iso8601_duration.hours
212 self.minutes = iso8601_duration.minutes
213 self.seconds = iso8601_duration.seconds
214 self.fractional_second = iso8601_duration.fractional_second
215 end
216
217 def magnitude
218 return ((((@year + @month/MONTH_IN_YEAR)*NOMINAL_DAYS_IN_MONTH) +
219 @week * DAYS_IN_WEEK + @days) * HOURS_IN_DAY * MINUTES_IN_HOUR*
220 SECONDS_IN_MINUTE) + @second + @fractional_second
221 end
222
223 undef magnitude=
224
225 end
226 end # of Date_Time
227 end # of Quantity
228 end # of Data_Types
229 end # of RM
230end # of OpenEHR
Note: See TracBrowser for help on using the repository browser.