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

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

support/identification package moving from test/unit to rspec

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