File: duration.rb

package info (click to toggle)
mhc 1.2.4-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,424 kB
  • sloc: ruby: 12,718; lisp: 7,570; makefile: 70; sh: 68
file content (110 lines) | stat: -rw-r--r-- 3,310 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
module RiCal
  class PropertyValue
    #- ©2009 Rick DeNatale, All rights reserved. Refer to the file README.txt for the license
    #
    # RiCal::PropertyValue::CalAddress represents an icalendar Duration property value
    # which is defined in 
    # rfc 2445 section 4.3.6 p 37
    class Duration < PropertyValue

      def self.value_part(unit, diff) # :nodoc:
        (diff == 0) ? nil : "#{diff}#{unit}"
      end

      def self.from_datetimes(parent, start, finish, sign='+') # :nodoc:
        if start > finish
          from_datetimes(self, finish, start, '-')
        else
          diff = finish - start
          days_diff = diff.to_i
          hours = (diff - days_diff) * 24
          hour_diff = hours.to_i
          minutes = (hours - hour_diff) * 60
          min_diff = minutes.to_i
          seconds = (minutes - min_diff) * 60
          sec_diff = seconds.to_i

          day_part = value_part('D',days_diff)
          hour_part = value_part('H', hour_diff)
          min_part = value_part('M', min_diff)
          sec_part = value_part('S', sec_diff)
          t_part = (hour_diff.abs + min_diff.abs + sec_diff.abs) == 0 ? "" : "T"
          new(parent, :value => "#{sign}P#{day_part}#{t_part}#{hour_part}#{min_part}#{sec_part}")        
        end
      end

      def self.convert(parent, ruby_object) # :nodoc:
        ruby_object.to_ri_cal_duration_value
      end

      def value=(string) # :nodoc:
        super
        match = /([+-])?P(.*)$/.match(string)
        @days = @hours = @minutes = @seconds = @weeks = 0
        if match
          @sign = match[1] == '-' ? -1 : 1
          match[2].scan(/(\d+)([DHMSW])/) do |digits, unit|
            number = digits.to_i
            case unit
            when 'D'
              @days = number
            when 'H'
              @hours = number
            when 'M'
              @minutes = number
            when 'S'
              @seconds = number
            when 'W'
              @weeks = number
            end
          end
        end
      end
      
      def self.valid_string?(string) #:nodoc:
        string =~  /^[+-]?P((\d+D)(T((\d+)[HMS])+)?)|(T((\d+)[HMS])+)|(\d+W)$/
      end

      def days # :nodoc:
        @days * @sign
      end

      def weeks # :nodoc:
        @weeks * @sign
      end

      def hours # :nodoc:
        @hours * @sign
      end

      def minutes # :nodoc:
        @minutes * @sign
      end

      def seconds # :nodoc:
        @seconds * @sign
      end

      # Determine whether another object is an equivalent RiCal::PropertyValue::Duration
      def ==(other)
        other.kind_of?(PropertyValue::Duration) && value == other.value
      end

      # Returns the receiver
      def to_ri_cal_duration_value
        self
      end

      # Double-dispatch method to support RiCal::PropertyValue::DateTime.-
      def subtract_from_date_time_value(date_time_value)
        date_time_value.advance(:weeks => -weeks, :days => -days, :hours => -hours, :minutes => -minutes, :seconds => -seconds)
      end

      # Double-dispatch method to support RiCal::PropertyValue::DateTime.+
      def add_to_date_time_value(date_time_value)
        date_time_value.advance(:weeks => weeks, :days => days, :hours => hours, :minutes => minutes, :seconds => seconds)
      end

    end
  end
end