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

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

fixed #62
refs #49,#39

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