source: ruby/trunk/lib/open_ehr/assumed_library_types.rb@ 398

Last change on this file since 398 was 398, checked in by KOBAYASHI, Shinji, 14 years ago

refs #71

File size: 16.2 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 TimeDefinitions < 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 return !year.nil? && year >= 0
98 end
99
100 def self.valid_day?(y, m, d)
101 unless y.nil? || m.nil? || d.nil?
102 return Date.valid_date?(y,m,d)
103 end
104 if (y.nil?) || (m.nil? && !d.nil?)
105 return false
106 end
107 return self.valid_year?(y) && self.valid_month?(m)
108 end
109
110 def self.valid_hour?(h,m = nil, s = nil)
111 if h.nil?
112 return false
113 end
114 if !m.nil? and !valid_minute?(m)
115 return false
116 end
117 if !s.nil? and (!m.nil? and !valid_second?(s))
118 return false
119 end
120 (h >= 0 and h < HOURS_IN_DAY) or (h == HOURS_IN_DAY and m == 0 and s == 0)
121 end
122
123 def self.valid_minute?(mi)
124 mi >= 0 and mi < MINUTES_IN_HOUR
125 end
126
127 def self.valid_second?(s)
128 s >= 0 and s < SECONDS_IN_MINUTE
129 end
130
131 def self.valid_month?(mo)
132 mo >= 1 and mo <= MONTH_IN_YEAR
133 end
134 end # end of TimeDefinitions
135
136 module ISO8601DateModule
137 attr_reader :year, :month, :day
138
139 def year=(year)
140 unless ISO8601Date.valid_year?(year)
141 raise ArgumentError, "Year is not valid"
142 end
143 @year = year
144 end
145
146 def month=(month)
147 raise ArgumentError, "Month is not valid" unless month.nil? or ISO8601Date.valid_month?(month)
148 @month = month
149 end
150
151 def day=(day)
152
153 raise ArgumentError, "Day is not valid" unless day.nil? or ISO8601Date.valid_day?(@year, @month, day)
154 @day = day
155 end
156
157 def as_string
158 if (!@year.nil? and !@month.nil? and !@day.nil?)
159 Date.new(@year, @month, @day).to_s
160 elsif (!@year.nil? and !@month.nil? and @day.nil?)
161 Date.new(@year, @month).to_s[0,7]
162 elsif (!@year.nil? and @month.nil? and @day.nil?)
163 Date.new(@year).to_s[0,4]
164 end
165 end
166
167 def month_unknown?
168 @month.nil?
169 end
170
171 def day_unknown?
172 @day.nil?
173 end
174
175 def is_extended?
176 true
177 end
178
179 def is_partial?
180 month_unknown? or day_unknown?
181 end
182
183 protected
184 def leapyear?(year)
185 case
186 when year % 400 == 0: true
187 when year % 100 == 0: false
188 else year % 4 == 0
189 end
190 end
191 end
192
193 def nilthenzero(value)
194 return value ? value : 0
195 end
196
197 class ISO8601Date < TimeDefinitions
198 include ISO8601DateModule, Comparable
199 def initialize(string)
200 /(\d{4})(?:-(\d{2})(?:-(\d{2})?)?)?/ =~ string
201 if $1.nil?
202 raise ArgumentError, 'data invalid'
203 else
204 self.year = $1.to_i
205 end
206 if $2.nil?
207 self.month = nil
208 else
209 self.month = $2.to_i
210 end
211 if $3.nil?
212 self.day = nil
213 else
214 self.day = $3.to_i
215 end
216 end
217
218 def <=>(other)
219 magnitude =
220 nilthenzero(@year)*TimeDefinitions::NOMINAL_DAYS_IN_YEAR +
221 nilthenzero(@month)*TimeDefinitions::NOMINAL_DAYS_IN_MONTH +
222 nilthenzero(@day)
223 other_magnitude =
224 nilthenzero(other.year)*TimeDefinitions::NOMINAL_DAYS_IN_YEAR +
225 nilthenzero(other.month)*TimeDefinitions::NOMINAL_DAYS_IN_MONTH +
226 nilthenzero(other.day)
227 magnitude <=> other_magnitude
228 end
229
230 def self.valid_iso8601_date?(string)
231 begin
232 Date.parse(string)
233 rescue
234 return false
235 end
236 true
237 end
238 end # end of ISO8601_DATE
239
240 module ISO8601TimeModule
241 attr_reader :hour, :minute, :second, :fractional_second, :timezone
242
243 def hour=(hour)
244 unless ISO8601Time.valid_hour?(hour, @minute, @second)
245 raise ArgumentError, "hour is not valid"
246 end
247 @hour = hour
248 end
249
250 def minute_unknown?
251 @minute.nil?
252 end
253
254 def minute=(minute)
255 raise ArgumentError, "minute is not valid" if !minute.nil? and !ISO8601Time.valid_minute?(minute)
256 @minute = minute
257 end
258
259 def second_unknown?
260 @second.nil?
261 end
262
263 def second=(second)
264 raise ArgumentError, "minute not defined" if @minute.nil? and !second.nil?
265 raise ArgumentError, "second is not valid" if !second.nil? and !ISO8601Time.valid_second?(second)
266 @second = second
267 end
268
269 def fractional_second=(fractional_second)
270 raise ArgumentError, "minute not defined" if minute_unknown? and !fractional_second.nil?
271 raise ArgumentError, "second not defined" if second_unknown? and !fractional_second.nil?
272 if !fractional_second.nil? &&
273 (fractional_second < 0.0 || fractional_second >= 1.0)
274 raise ArgumentError, 'fractional second should be between 0.0 - 1.0'
275 end
276 @fractional_second = fractional_second
277 end
278
279 def has_fractional_second?
280 return !@fractional_second.nil?
281 end
282
283 def timezone=(timezone)
284 unless timezone.nil? or timezone == 'Z'
285 if /[+-](\d{2}):?(\d{2})/ =~ timezone
286 @timezone = timezone
287 else
288 raise ArgumentError, "timezone invalid"
289 end
290 else
291 @timezone = nil
292 end
293 end
294
295 def is_decimal_sign_comma?
296 false
297 end
298
299 def is_extended?
300 true
301 end
302
303 def is_partial?
304 second_unknown? or minute_unknown?
305 end
306
307 def as_string
308 s = sprintf("%02d", @hour)
309 if !@minute.nil?
310 s += ":" + sprintf("%02d",@minute)
311 if !@second.nil?
312 s += ":" + sprintf("%02d", @second)
313 if !@fractional_second.nil?
314 s += "." + @fractional_second.to_s[2..-1]
315 if !@timezone.nil?
316 s += @timezone
317 end
318 end
319 end
320 end
321 return s
322 end
323
324
325 end
326
327 class ISO8601Time < TimeDefinitions
328 include ISO8601TimeModule, Comparable
329 def initialize(string)
330 /(\d{2}):?(\d{2})?(:?)(\d{2})?((\.|,)(\d+))?(Z|([+-](\d{2}):?(\d{2})))?/ =~ string
331 if $2.nil?
332 self.minute = nil
333 else
334 self.minute = $2.to_i
335 end
336 if $4.nil?
337 self.second = nil
338 else
339 self.second = $4.to_i
340 end
341 if $1.nil?
342 raise ArgumentError, 'data invalid'
343 else
344 self.hour = $1.to_i
345 end
346 if $7.nil?
347 self.fractional_second = nil
348 else
349 self.fractional_second = ("0." + $7).to_f
350 end
351 if $8.nil?
352 self.timezone = nil
353 else
354 self.timezone = $8
355 end
356 end
357
358 def <=>(other)
359 magnitude = (nilthenzero(@hour)*60 + nilthenzero(@minute))*60 +
360 nilthenzero(@second) +
361 nilthenzero(@fractional_second)
362 other_magnitude = (nilthenzero(other.hour) * 60 +
363 nilthenzero(other.minute)) * 60 +
364 nilthenzero(other.second) +
365 nilthenzero(other.fractional_second)
366 magnitude <=> other_magnitude
367 end
368
369 def self.valid_iso8601_time?(s)
370 if /^(\d{2}):?(\d{2})?(:?)(\d{2})?((\.|,)(\d+))?(Z|([+-](\d{2}):?(\d{2})))?$/ =~ s
371# ISO 8601 regular expression by H. Yuki
372# 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
373# (\d{4})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d))?)?(Z|([+-]\d{2}):(\d{2}))?)?)?)?
374 hh = $1; mm = $2; ss = $4; msec = $7; tz = $8
375 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)
376 return true
377 end
378 if hh.nil? or (hh.to_i < 0 or hh.to_i >= HOURS_IN_DAY)
379 return false
380 end
381 if !mm.nil?
382 if !self.valid_minute?(mm.to_i)
383 return false
384 end
385 end
386 if !ss.nil?
387 if !self.valid_second?(ss.to_i)
388 return false
389 end
390 end
391 if !tz.nil? and tz != "Z"
392 if /[+-](\d{2}):?(\d{2})/ =~ tz
393 h = $1; m = $2
394 if h.to_i < 0 or h.to_i >= HOURS_IN_DAY
395 return false
396 end
397 if m.to_i < 0 or m.to_i >= MINUTES_IN_HOUR
398 return false
399 end
400 end
401 end
402 return true
403 else
404 return false
405 end
406 end
407 end # end of ISO8601_TIME
408
409 module ISO8601DateTimeModule
410 include ISO8601DateModule, ISO8601TimeModule
411 def as_string
412 if (!@year.nil? and !@month.nil? and !@day.nil?)
413 s = Date.new(@year, @month, @day).to_s
414 elsif (!@year.nil? and !@month.nil? and @day.nil?)
415 return Date.new(@year, @month).to_s[0,7]
416 elsif (!@year.nil? and @month.nil? and @day.nil?)
417 return Date.new(@year).to_s[0,4]
418 end
419 unless hour.nil?
420 s += sprintf("T%02d", @hour)
421 unless @minute.nil?
422 s += ":" + sprintf("%02d",@minute)
423 unless @second.nil?
424 s += ":" + sprintf("%02d", @second)
425 unless @fractional_second.nil?
426 s += "." + @fractional_second.to_s[2..-1]
427 unless @timezone.nil?
428 s += @timezone
429 end
430 end
431 end
432 end
433 end
434 return s
435 end
436 end
437
438 class ISO8601DateTime < ISO8601Date
439 include ISO8601DateTimeModule
440 def initialize(string)
441 unless /(\d{4})(?:-(\d{2})(?:-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?(Z|([+-]\d{2}):?(\d{2}))?)?)?)?/ =~ string
442 raise ArgumentError, 'format invalid'
443 else
444 self.year = $1.to_i
445 end
446 if $2.nil?
447 self.month = nil
448 else
449 self.month = $2.to_i
450 end
451 if $3.nil?
452 self.day = nil
453 else
454 self.day = $3.to_i
455 end
456 if $5.nil?
457 self.minute = nil
458 else
459 self.minute = $5.to_i
460 end
461 if $6.nil?
462 self.second = nil
463 else
464 self.second = $6.to_i
465 end
466 if $4.nil?
467 self.hour = nil
468 else
469 self.hour = $4.to_i
470 end
471 if $7.nil? or $7.empty?
472 self.fractional_second = nil
473 else
474 self.fractional_second = ("0."+$7).to_f
475 end
476 if $8.nil?
477 self.timezone = nil
478 else
479 self.timezone = $9+$10
480 end
481 end
482 end
483
484 class ISO8601Timezone
485 attr_accessor :sign, :hour, :minute
486
487 def initialize(string)
488 unless /(Z|(([+-])(\d{2}):?(\d{2})))/ =~ string
489 raise ArgumentError, 'invaild format'
490 end
491 if $1 == 'Z'
492 @sign, @hour, @minute = +1, 0, 0
493 else
494 @sign, @hour, @minute = ($3+'1').to_i, $4.to_i , $5.to_i
495 end
496 end
497
498 def is_gmt?
499 @sign == +1 and @hour == 0 and @minute == 0
500 end
501
502 def as_string
503 if @sign == +1
504 s = "+"
505 elsif @sign == -1
506 s = "-"
507 end
508 sprintf("%s%02d%02d", s, @hour, @minute)
509 end
510 end # end of ISO8601Timezone
511
512 module ISO8601DurationModule
513 attr_reader :years, :months, :weeks, :days
514 attr_reader :hours, :minutes, :seconds, :fractional_second
515
516 def years=(years)
517 unless years.nil? || years >= 0
518 raise ArgumentError, 'years must be above zero'
519 end
520 @years = years
521 end
522
523 def months=(months)
524 unless months.nil? || months >= 0
525 raise ArgumentError, 'months must be above zero'
526 end
527 @months = months
528 end
529
530 def weeks=(weeks)
531 unless weeks.nil? || weeks >= 0
532 raise ArgumentError, 'weeks must be above zero'
533 end
534 @weeks = weeks
535 end
536
537 def days=(days)
538 unless days.nil? || days >= 0
539 raise ArgumentError, 'days must be above zero'
540 end
541 @days = days
542 end
543
544 def hours=(hours)
545 unless hours.nil? || hours >= 0
546 raise ArgumentError, 'hours must be above zero'
547 end
548 @hours = hours
549 end
550
551 def minutes=(minutes)
552 unless minutes.nil? || minutes >= 0
553 raise ArgumentError, 'minutes must be above zero'
554 end
555 @minutes = minutes
556 end
557
558 def seconds=(seconds)
559 unless seconds.nil? || seconds >= 0
560 raise ArgumentError, 'seconds must be above zero'
561 end
562 @seconds = seconds
563 end
564
565 def fractional_second=(fractional_second)
566 unless fractional_second.nil? || (fractional_second >= 0 && fractional_second < 1.0)
567 raise ArgumentError, 'fractional_second must be between 0.0 and 1.0'
568 end
569 @fractional_second = fractional_second
570 end
571
572 def as_string
573 str = 'P'
574 unless @years.nil?
575 str += @years.to_s + 'Y'
576 end
577 unless @months.nil?
578 str += @months.to_s + 'M'
579 end
580 unless @weeks.nil?
581 str += @weeks.to_s + 'W'
582 end
583 unless @days.nil?
584 str += @days.to_s + 'D'
585 end
586 unless @hours.nil?
587 str += 'T' + @hours.to_s + 'H'
588 unless @minutes.nil?
589 str += @minutes.to_s + 'M'
590 unless @seconds.nil?
591 str += @seconds.to_s
592 unless @fractional_second.nil?
593 str += @fractional_second.to_s[1 .. -1]
594 end
595 str += 'S'
596 end
597 end
598 end
599 return str
600 end
601 end
602
603 class ISO8601Duration < TimeDefinitions
604 include ISO8601DurationModule
605 def initialize(str)
606 /^P((\d+)Y)?((\d+)M)?((\d+)W)?((\d)D)?(T((\d+)H)?((\d+)M)?((\d+)(\.\d+)?S)?)?$/ =~ str
607 self.years = $2.to_i
608 self.months = $4.to_i
609 self.weeks = $6.to_i
610 self.days = $8.to_i
611 self.hours = $11.to_i
612 self.minutes = $13.to_i
613 self.seconds = $15.to_i
614 unless $16.nil?
615 self.fractional_second = $16.to_f
616 end
617 end
618 end # end of ISO8601Duration
619 end # end of Assumed_Types
620end # end of OpenEHR
Note: See TracBrowser for help on using the repository browser.