Module: DateTimePrecision

Included in:
Date, DateTime, Time
Defined in:
lib/date_time_precision/lib.rb,
lib/date_time_precision/version.rb,
lib/date_time_precision/format/hash.rb,
lib/date_time_precision/format/json.rb,
lib/date_time_precision/format/iso8601.rb

Defined Under Namespace

Modules: ClassMethods

Constant Summary collapse

FRAC =
7
SEC =
6
MIN =
5
HOUR =
4
DAY =
3
MONTH =
2
YEAR =
1
NONE =
0
NEW_DEFAULTS =

Default values for y,m,d,h,m,s,frac

[-4712,1,1,0,0,0,0]
DATE_ATTRIBUTES =
[
  :year,
  :mon,
  :day,
  :hour,
  :min,
  :sec,
  :sec_frac
]
DATE_ATTRIBUTE_PRECISIONS =
{
  :year => YEAR,
  :mon => MONTH,
  :day => DAY,
  :hour => HOUR,
  :min => MIN,
  :sec => SEC,
  :sec_frac => FRAC
}
PATCH_VERSION =
begin
  if defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) and RUBY_ENGINE == 'rbx')
    #JRuby and Rubinius implement the Date/Time classes in pure Ruby, so they can use the 1.9.2 patch
    RUBY_VERSION >= '1.9' ? '1.9.2' : '1.8.7'
  elsif RUBY_VERSION > '2'
    # The 1.9.3 patch works in Ruby 2.0.0
    '1.9.3'
  else
    RUBY_VERSION
  end
end
VERSION =
"0.7.0"
ISO8601_DATE_FRAGMENTS =
%w(%0*d %02d %02d)
ISO8601_TIME_FRAGMENTS =
%w(%02d %02d %02d)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/date_time_precision/lib.rb', line 148

def self.included(base)
  # Redefine any conversion methods so precision is preserved
  [:to_date, :to_time, :to_datetime].each do |conversion_method|
    # If the conversion method is already defined, patch it
    orig = :"orig_#{conversion_method}"
    if base.method_defined?(conversion_method) && !base.instance_methods(false).map(&:to_sym).include?(orig)
      base.class_eval do
        alias_method orig, conversion_method
        define_method(conversion_method) do
          d = send(orig)
          d.precision = [self.precision, d.class::MAX_PRECISION].min
          DATE_ATTRIBUTES.each do |attribute|
            d.instance_variable_set(:"@#{attribute}_set", self.instance_variable_get(:"@#{attribute}_set"))
          end
          d
        end
      end
    else
      # Define our own conversion methods by converting to hash first
      require 'date_time_precision/format/hash'
      base.class_eval do
        define_method(conversion_method) do
          to_h.send(conversion_method)
        end
      end
    end

    base.send :public, conversion_method
  end
  
  # Extend with this module's class methods
  base.extend(ClassMethods)
  
  # Define attribute query methods, including:
  # year?, mon?, day?, hour?, min?, sec?, sec_frac?
  DATE_ATTRIBUTE_PRECISIONS.each do |attribute_name, precision|
    #next unless precision <= base::MAX_PRECISION
    
    base.class_eval <<-EOM, __FILE__, __LINE__
      def #{attribute_name}?
        return !@#{attribute_name}_set.nil? ? @#{attribute_name}_set : (self.precision >= #{precision})
      end

      def #{attribute_name}_set=(val)
        @#{attribute_name}_set = !!val
      end
      protected :#{attribute_name}_set=
    EOM
  end
  
  base.class_eval <<-EOM, __FILE__, __LINE__
    def attributes_set(*vals)
      #{DATE_ATTRIBUTES.map{|attribute| "@#{attribute}_set"}.join(', ')} = *(vals.flatten.map{|v| !!v})
    end
  EOM
  
  base.class_eval do
    if method_defined?(:usec)
      alias_method :usec?, :sec_frac?
      alias_method :sec_frac, :usec
    end
    
    if method_defined?(:subsec)
      alias_method :subsec?, :sec_frac?
    end

    alias_method :month?, :mon?

    alias_method :mday, :day
    alias_method :mday?, :day?
  end
end

.precision(val) ⇒ Object



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
# File 'lib/date_time_precision/lib.rb', line 72

def self.precision(val)
  case val
  when Date,Time,DateTime
    val.precision
  when Hash
    case
    when val[:sec_frac], val[:subsec]
      FRAC
    when val[:sec]
      SEC
    when val[:min]
      MIN
    when val[:hour]
      HOUR
    when val[:mday], val[:day], val[:d]
      DAY
    when val[:mon], val[:month], val[:m]
      MONTH
    when val[:year], val[:y]
      YEAR
    else
      NONE
    end
  when Array
    val.index{|v| v.nil?} || val.length
  else
    NONE
  end
end

Instance Method Details

#as_json(*args) ⇒ Object



20
21
22
# File 'lib/date_time_precision/format/json.rb', line 20

def as_json(*args)
  to_h
end

#fragmentsObject



102
103
104
105
106
107
108
109
110
111
# File 'lib/date_time_precision/lib.rb', line 102

def fragments
  frags = []
  frags << self.year if self.year?
  frags << self.month if self.month?
  frags << self.day if self.day?
  frags << self.hour if self.hour?
  frags << self.min if self.min?
  frags << self.sec if self.sec?
  frags
end

#partial_match?(date2) ⇒ Boolean

Returns true if dates partially match (i.e. one is a partial date of the other)

Returns:

  • (Boolean)


114
115
116
# File 'lib/date_time_precision/lib.rb', line 114

def partial_match?(date2)
  self.class::partial_match?(self, date2)
end

#precisionObject

Returns the precision for this Date/Time object, or the maximum precision if none was specified



63
64
65
66
# File 'lib/date_time_precision/lib.rb', line 63

def precision
  @precision = self.class::MAX_PRECISION unless @precision
  return @precision
end

#precision=(prec) ⇒ Object



68
69
70
# File 'lib/date_time_precision/lib.rb', line 68

def precision=(prec)
  @precision = [prec,self.class::MAX_PRECISION].min
end

#to_h(format = nil) ⇒ Object



36
37
38
39
40
41
42
43
# File 'lib/date_time_precision/format/hash.rb', line 36

def to_h(format = nil)
  keys = Hash::DATE_FORMATS[format || :default]
  
  Hash[keys.each_with_index.map do |key,i|
    attribute_name = Hash::DATE_FORMATS[:ruby][i]
    [key, self.send(attribute_name)] if self.send("#{attribute_name}?")
  end.compact]
end

#to_json(opts = {}) ⇒ Object



24
25
26
# File 'lib/date_time_precision/format/json.rb', line 24

def to_json(opts = {})
  to_h.to_json(opts)
end