File: column_type.rb

package info (click to toggle)
ruby-dbf 4.3.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,732 kB
  • sloc: ruby: 1,692; makefile: 9
file content (120 lines) | stat: -rw-r--r-- 2,648 bytes parent folder | download
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
111
112
113
114
115
116
117
118
119
120
module DBF
  module ColumnType
    class Base
      attr_reader :decimal, :encoding

      # @param decimal [Integer]
      # @param encoding [String, Encoding]
      def initialize(decimal, encoding)
        @decimal = decimal
        @encoding = encoding
      end
    end

    class Nil < Base
      # @param _value [String]
      def type_cast(_value)
        nil
      end
    end

    class Number < Base
      # @param value [String]
      def type_cast(value)
        return nil if value.strip.empty?

        @decimal.zero? ? value.to_i : value.to_f
      end
    end

    class Currency < Base
      # @param value [String]
      def type_cast(value)
        (value.unpack1('q<') / 10_000.0).to_f
      end
    end

    class SignedLong < Base
      # @param value [String]
      def type_cast(value)
        value.unpack1('l<')
      end
    end

    class SignedLong2 < Base
      # @param value [String]
      def type_cast(value)
        s = value.unpack1('B*')
        sign_multiplier = s[0] == '0' ? -1 : 1
        s[1, 31].to_i(2) * sign_multiplier
      end
    end

    class Float < Base
      # @param value [String]
      def type_cast(value)
        value.to_f
      end
    end

    class Double < Base
      # @param value [String]
      def type_cast(value)
        value.unpack1('E')
      end
    end

    class Boolean < Base
      # @param value [String]
      def type_cast(value)
        value.strip.match?(/^(y|t)$/i)
      end
    end

    class Date < Base
      # @param value [String]
      def type_cast(value)
        value.match?(/\d{8}/) && ::Date.strptime(value, '%Y%m%d')
      rescue StandardError
        nil
      end
    end

    class DateTime < Base
      # @param value [String]
      def type_cast(value)
        days, msecs = value.unpack('l2')
        secs = (msecs / 1000).to_i
        ::DateTime.jd(days, (secs / 3600).to_i, (secs / 60).to_i % 60, secs % 60).to_time
      rescue StandardError
        nil
      end
    end

    class Memo < Base
      # @param value [String]
      def type_cast(value)
        if encoding && !value.nil?
          value.force_encoding(@encoding).encode(Encoding.default_external, undef: :replace, invalid: :replace)
        else
          value
        end
      end
    end

    class General < Base
      # @param value [String]
      def type_cast(value)
        value
      end
    end

    class String < Base
      # @param value [String]
      def type_cast(value)
        value = value.strip
        @encoding ? value.force_encoding(@encoding).encode(Encoding.default_external, undef: :replace, invalid: :replace) : value
      end
    end
  end
end