source: ruby/branches/0.5/lib/open_ehr/assumed_library_types.rb@ 255

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

move interval test to rspec

File size: 14.7 KB
Line 
1# This module is related to the ticket #36
2require 'date'
3require 'time'
4
5module OpenEHR
6 module AssumedLibraryTypes
7 class Any < Object
8
9 end # of Any
10
11 class Interval < Any
12 attr_reader :lower, :upper
13
14 def initialize(args = {})
15 check_lower_upper(args[:lower], args[:upper])
16 self.lower_included = args[:lower_included]
17 self.upper_included = args[:upper_included]
18 end
19
20 def lower=(lower)
21 check_lower_upper(lower, @upper)
22 end
23
24 def upper=(upper)
25 check_lower_upper(@lower, upper)
26 end
27
28 def lower_included?
29 return @lower_included
30 end
31
32 def lower_included=(lower_included)
33 if (lower == nil) && (lower_included != nil)
34 raise ArgumentError, "lower is not set"
35 end
36 @lower_included = lower_included
37 end
38
39 def lower_unbounded?
40 return @lower.nil?
41 end
42
43 def upper_included?
44 return @upper_included
45 end
46
47 def upper_included=(upper_included)
48 if (@upper.nil?) && (upper_included != nil)
49 raise ArgumentError, "upper is not set"
50 end
51 @upper_included = upper_included
52 end
53
54 def upper_unbounded?
55 return @upper.nil?
56 end
57
58 def has?(value)
59 if ((@lower.nil?||@lower < value||((@lower_included == true) && (@lower == value)))&&
60 (@upper.nil?||value < @upper||((@upper_included == true) && (@upper == value))))
61 true
62 else
63 false
64 end
65 end
66
67 private
68
69 def check_lower_upper(lower, upper)
70 if lower.nil? && upper.nil?
71 raise ArgumentError, "Either lower or upper must be assigned"
72 end
73 unless (lower.nil? || upper.nil?)
74 if lower > upper
75 raise ArgumentError, "Upper must be larger than lower."
76 end
77 end
78 @lower = lower
79 @upper = upper
80 end
81 end # end of Interval
82
83 class TIME_DEFINITIONS < Any
84 DAYS_IN_LEAP_YEAR = 366
85 DAYS_IN_WEEK = 7
86 DAYS_IN_YEAR = 365
87 HOURS_IN_DAY = 24
88 MAX_DAYS_IN_MONTH = 31
89 MAX_DAYS_IN_YEAR = 366
90 MINUTES_IN_HOUR = 60
91 MONTH_IN_YEAR = 12
92 NOMINAL_DAYS_IN_MONTH = 30.42
93 NOMINAL_DAYS_IN_YEAR = 365.24
94 SECONDS_IN_MINUTE = 60
95
96 def self.valid_year?(year)
97 year >= 0
98 end
99
100 def self.valid_day?(y, m, d)
101 Date.valid_date?(y,m,d) and valid_year? y
102 end
103
104 def self.valid_hour?(h,m = nil, s = nil)
105 if !m.nil? and !valid_minute?(m)
106 return false
107 end
108 if !s.nil? and (!m.nil? and !valid_second?(s))
109 return false
110 end
111 (h >= 0 and h < HOURS_IN_DAY) or (h == HOURS_IN_DAY and m == 0 and s == 0)
112 end
113 def self.valid_minute?(mi)
114 mi >= 0 and mi < MINUTES_IN_HOUR
115 end
116 def self.valid_second?(s)
117 s >= 0 and s < SECONDS_IN_MINUTE
118 end
119 def self.valid_month?(mo)
120 mo >= 1 and mo <= MONTH_IN_YEAR
121 end
122 end # end of TIME_DEFINITIONS
123
124 module ISO8601_DATE_MODULE
125 attr_reader :year, :month, :day
126 def year=(year)
127 raise ArgumentError, "Year is not valid" unless ISO8601_DATE.valid_year?(year)
128 @year = year
129 end
130 def month=(month)
131 raise ArgumentError, "Month is not valid" unless month.nil? or ISO8601_DATE.valid_month?(month)
132 @month = month
133 end
134
135 def day=(day)
136 raise ArgumentError, "Day is not valid" unless day.nil? or ISO8601_DATE.valid_day?(@year, @month, day)
137 @day = day
138 end
139
140 def as_string
141 if (!@year.nil? and !@month.nil? and !@day.nil?)
142 Date.new(@year, @month, @day).to_s
143 elsif (!@year.nil? and !@month.nil? and @day.nil?)
144 Date.new(@year, @month).to_s[0,7]
145 elsif (!@year.nil? and @month.nil? and @day.nil?)
146 Date.new(@year).to_s[0,4]
147 end
148 end
149
150 def month_unknown?
151 @month.nil?
152 end
153
154 def day_unknown?
155 @day.nil?
156 end
157
158 def is_extended?
159 true
160 end
161
162 def is_partial?
163 month_unknown? or day_unknown?
164 end
165
166 protected
167 def leapyear?(year)
168 case
169 when year % 400 == 0: true
170 when year % 100 == 0: false
171 else year % 4 == 0
172 end
173 end
174 end
175
176 class ISO8601_DATE < TIME_DEFINITIONS
177 include ISO8601_DATE_MODULE
178 def initialize(string)
179 /(\d{4})(?:-(\d{2})(?:-(\d{2})?)?)?/ =~ string
180 if $1.nil?
181 raise ArgumentError, 'data invalid'
182 else
183 self.year = $1.to_i
184 end
185 if $2.nil?
186 self.month = nil
187 else
188 self.month = $2.to_i
189 end
190 if $3.nil?
191 self.day = nil
192 else
193 self.day = $3.to_i
194 end
195 end
196
197 def self.valid_iso8601_date?(string)
198 begin
199 Date.parse(string)
200 rescue
201 return false
202 end
203 true
204 end
205 end # end of ISO8601_DATE
206
207 module ISO8601_TIME_MODULE
208 attr_reader :hour, :minute, :second, :fractional_second, :timezone
209
210 def hour=(hour)
211 raise ArgumentError, "hour is not valid" if !ISO8601_TIME.valid_hour?(hour, @minute, @second)
212 @hour = hour
213 end
214
215 def minute_unknown?
216 @minute.nil?
217 end
218
219 def minute=(minute)
220 raise ArgumentError, "minute is not valid" if !minute.nil? and !ISO8601_TIME.valid_minute?(minute)
221 @minute = minute
222 end
223
224 def second_unknown?
225 @second.nil?
226 end
227
228 def second=(second)
229 raise ArgumentError, "minute not defined" if @minute.nil? and !second.nil?
230 raise ArgumentError, "second is not valid" if !second.nil? and !ISO8601_TIME.valid_second?(second)
231 @second = second
232 end
233
234 def fractional_second=(fractional_second)
235 raise ArgumentError, "minute not defined" if minute_unknown? and !fractional_second.nil?
236 raise ArgumentError, "second not defined" if second_unknown? and !fractional_second.nil?
237 raise ArgumentError, "fractional second should be lower than 1.0" if !fractional_second.nil? and fractional_second >= 1.0
238 @fractional_second = fractional_second
239 end
240
241 def has_fractional_second?
242 if @fractional_second.nil?
243 return false
244 else
245 return true
246 end
247 end
248
249 def timezone=(timezone)
250 unless timezone.nil? or timezone == 'Z'
251 if /[+-](\d{2}):?(\d{2})/ =~ timezone
252 @timezone = timezone
253 else
254 raise ArgumentError, "timezone invalid"
255 end
256 else
257 @timezone = nil
258 end
259 end
260
261 def is_decimal_sign_comma?
262 false
263 end
264
265 def is_extended?
266 true
267 end
268
269 def is_partial?
270 second_unknown? or minute_unknown?
271 end
272
273 def as_string
274 s = sprintf("%02d", @hour)
275 if !@minute.nil?
276 s += ":" + sprintf("%02d",@minute)
277 if !@second.nil?
278 s += ":" + sprintf("%02d", @second)
279 if !@fractional_second.nil?
280 s += "." + @fractional_second.to_s[2..-1]
281 if !@timezone.nil?
282 s += @timezone
283 end
284 end
285 end
286 end
287 return s
288 end
289 end
290
291 class ISO8601_TIME < TIME_DEFINITIONS
292 include ISO8601_TIME_MODULE
293 def initialize(string)
294 /(\d{2}):?(\d{2})?(:?)(\d{2})?((\.|,)(\d+))?(Z|([+-](\d{2}):?(\d{2})))?/ =~ string
295 if $2.nil?
296 self.minute = nil
297 else
298 self.minute = $2.to_i
299 end
300 if $4.nil?
301 self.second = nil
302 else
303 self.second = $4.to_i
304 end
305 if $1.nil?
306 raise ArgumentError, 'data invalid'
307 else
308 self.hour = $1.to_i
309 end
310 if $7.nil?
311 self.fractional_second = nil
312 else
313 self.fractional_second = ("0." + $7).to_f
314 end
315 if $8.nil?
316 self.timezone = nil
317 else
318 self.timezone = $8
319 end
320 end
321 def self.valid_iso8601_time?(s)
322 if /(\d{2}):?(\d{2})?(:?)(\d{2})?((\.|,)(\d+))?(Z|([+-](\d{2}):?(\d{2})))?/ =~ s
323# ISO 8601 regular expression by H. Yuki
324# http://digit.que.ne.jp/work/wiki.cgi?Perl%E3%83%A1%E3%83%A2%2FW3C%E5%BD%A2%E5%BC%8F%E3%81%AE%E6%97%A5%E6%99%82%E3%81%AE%E8%A7%A3%E6%9E%90
325# (\d{4})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d))?)?(Z|([+-]\d{2}):(\d{2}))?)?)?)?
326 hh = $1; mm = $2; ss = $4; msec = $7; tz = $8
327 if hh.to_i == HOURS_IN_DAY and (mm.nil? or mm.to_i == 0) and (ss.nil? or ss.to_i == 0) and (msec.nil? or msec.to_i==0)
328 return true
329 end
330 if hh.nil? or (hh.to_i < 0 or hh.to_i >= HOURS_IN_DAY)
331 return false
332 end
333 if !mm.nil?
334 if !self.valid_minute?(mm.to_i)
335 return false
336 end
337 end
338 if !ss.nil?
339 if !self.valid_second?(ss.to_i)
340 return false
341 end
342 end
343 if !tz.nil? and tz != "Z"
344 if /[+-](\d{2}):?(\d{2})/ =~ tz
345 h = $1; m = $2
346 if h.to_i < 0 or h.to_i >= HOURS_IN_DAY
347 return false
348 end
349 if m.to_i < 0 or m.to_i >= MINUTES_IN_HOUR
350 return false
351 end
352 else
353 return false
354 end
355 end
356 return true
357 else
358 return false
359 end
360 end
361 end # end of ISO8601_TIME
362
363 module ISO8601_DATE_TIME_MODULE
364 include ISO8601_DATE_MODULE, ISO8601_TIME_MODULE
365 def as_string
366 if (!@year.nil? and !@month.nil? and !@day.nil?)
367 s = Date.new(@year, @month, @day).to_s
368 elsif (!@year.nil? and !@month.nil? and @day.nil?)
369 return Date.new(@year, @month).to_s[0,7]
370 elsif (!@year.nil? and @month.nil? and @day.nil?)
371 return Date.new(@year).to_s[0,4]
372 end
373 unless hour.nil?
374 s += sprintf("T%02d", @hour)
375 unless @minute.nil?
376 s += ":" + sprintf("%02d",@minute)
377 unless @second.nil?
378 s += ":" + sprintf("%02d", @second)
379 unless @fractional_second.nil?
380 s += "." + @fractional_second.to_s[2..-1]
381 unless @timezone.nil?
382 s += @timezone
383 end
384 end
385 end
386 end
387 end
388 return s
389 end
390 end
391
392 class ISO8601_DATE_TIME < ISO8601_DATE
393 include ISO8601_DATE_TIME_MODULE
394 def initialize(string)
395 /(\d{4})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?(Z|([+-]\d{2}):?(\d{2}))?)?)?)?/ =~ string
396 if $1.empty?
397 raise ArgumentError, 'format invalid'
398 else
399 self.year = $1.to_i
400 end
401 if $2.nil?
402 self.month = nil
403 else
404 self.month = $2.to_i
405 end
406 if $3.nil?
407 self.day = nil
408 else
409 self.day = $3.to_i
410 end
411 if $5.nil?
412 self.minute = nil
413 else
414 self.minute = $5.to_i
415 end
416 if $6.nil?
417 self.second = nil
418 else
419 self.second = $6.to_i
420 end
421 if $4.nil?
422 self.hour = nil
423 else
424 self.hour = $4.to_i
425 end
426 if $7.nil? or $7.empty?
427 self.fractional_second = nil
428 else
429 self.fractional_second = ("0."+$7).to_f
430 end
431 if $8.nil?
432 self.timezone = nil
433 else
434 self.timezone = $9+$10
435 end
436 end
437 end
438
439 class ISO8601_TIMEZONE
440 attr_accessor :sign, :hour, :minute
441
442 def is_gmt?
443 @sign == "+1" and @hour == 0 and @minute == 0
444 end
445
446 def as_string
447 if @sign == "+1"
448 s = "+"
449 elsif @sign == "-1"
450 s = "-"
451 end
452 sprintf("Z%s%02d%02d", s, @hour, @minute)
453 end
454 end # end of ISO8601_TIMEZONE
455
456 module ISO8601_DURATION_MODULE
457 attr_reader :years, :months, :weeks, :days
458 attr_reader :hours, :minutes, :seconds, :fractional_second
459
460 def years=(years)
461 unless years.nil? || years >= 0
462 raise ArgumentError, 'years must be above zero'
463 end
464 @years = years
465 end
466
467 def months=(months)
468 unless months.nil? || months >= 0
469 raise ArgumentError, 'months must be above zero'
470 end
471 @months = months
472 end
473
474 def weeks=(weeks)
475 unless weeks.nil? || weeks >= 0
476 raise ArgumentError, 'weeks must be above zero'
477 end
478 @weeks = weeks
479 end
480
481 def days=(days)
482 unless days.nil? || days >= 0
483 raise ArgumentError, 'days must be above zero'
484 end
485 @days = days
486 end
487
488 def hours=(hours)
489 unless hours.nil? || hours >= 0
490 raise ArgumentError, 'hours must be above zero'
491 end
492 @hours = hours
493 end
494
495 def minutes=(minutes)
496 unless minutes.nil? || minutes >= 0
497 raise ArgumentError, 'minutes must be above zero'
498 end
499 @minutes = minutes
500 end
501
502 def seconds=(seconds)
503 unless seconds.nil? || seconds >= 0
504 raise ArgumentError, 'seconds must be above zero'
505 end
506 @seconds = seconds
507 end
508
509 def fractional_second=(fractional_second)
510 unless fractional_second.nil? || (fractional_second >= 0 && fractional_second < 1.0)
511 raise ArgumentError, 'fractional_second must be between 0.0 and 1.0'
512 end
513 @fractional_second = fractional_second
514 end
515
516 def as_string
517 str = 'P'
518 unless @years.nil?
519 str += @years.to_s + 'Y'
520 end
521 unless @months.nil?
522 str += @months.to_s + 'M'
523 end
524 unless @weeks.nil?
525 str += @weeks.to_s + 'W'
526 end
527 unless @days.nil?
528 str += @days.to_s + 'D'
529 end
530 unless @hours.nil?
531 str += 'T' + @hours.to_s + 'H'
532 unless @minutes.nil?
533 str += @minutes.to_s + 'M'
534 unless @seconds.nil?
535 str += @seconds.to_s
536 unless @fractional_second.nil?
537 str += @fractional_second.to_s[1 .. -1]
538 end
539 str += 'S'
540 end
541 end
542 end
543 return str
544 end
545 end
546 class ISO8601_DURATION < TIME_DEFINITIONS
547 include ISO8601_DURATION_MODULE
548 def initialize(str)
549 /^P((\d+)Y)?((\d+)M)?((\d+)W)?((\d)D)?(T((\d+)H)?((\d+)M)?((\d+)(\.\d+)?S)?)?$/ =~ str
550 self.years = $2.to_i
551 self.months = $4.to_i
552 self.weeks = $6.to_i
553 self.days = $8.to_i
554 self.hours = $11.to_i
555 self.minutes = $13.to_i
556 self.seconds = $15.to_i
557 self.fractional_second = $16.to_f
558 end
559 end # end of ISO8601_DURATION
560 end # end of Assumed_Types
561end # end of OpenEHR
Note: See TracBrowser for help on using the repository browser.