Class: ICU::TimeFormatting::DateTimeFormatter

Inherits:
BaseFormatter show all
Defined in:
lib/ffi-icu/time_formatting.rb

Instance Method Summary collapse

Methods inherited from BaseFormatter

#set_attributes

Constructor Details

#initialize(options = {}) ⇒ DateTimeFormatter

Returns a new instance of DateTimeFormatter.



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/ffi-icu/time_formatting.rb', line 119

def initialize(options = {})
  super()

  time_style  = options[:time]   || :short
  date_style  = options[:date]   || :short
  @locale     = options[:locale] || 'C'
  tz_style    = options[:tz_style]
  time_zone   = options[:zone]
  skeleton    = options[:skeleton]
  @hour_cycle = options[:hour_cycle]

  if @hour_cycle && !HOUR_CYCLE_SYMS.keys.include?(@hour_cycle)
    raise(ICU::Error, "Unknown hour cycle #{@hour_cycle}")
  end

  @f = make_formatter(time_style, date_style, @locale, time_zone, skeleton)
  if tz_style
    f0 = date_format(true)
    f1 = update_tz_format(f0, tz_style)
    set_date_format(true, f1) if f1 != f0
  end

  replace_hour_symbol!
end

Instance Method Details

#date_format(localized = true) ⇒ Object

rubocop:disable Style/OptionalBooleanParameter



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/ffi-icu/time_formatting.rb', line 201

def date_format(localized = true) # rubocop:disable Style/OptionalBooleanParameter
  needed_length = 0
  out_ptr = UCharPointer.new(needed_length)

  retried = false

  begin
    Lib.check_error do |error|
      needed_length = Lib.udat_toPattern(@f, localized, out_ptr, needed_length, error)
    end

    out_ptr.string
  rescue BufferOverflowError
    raise(BufferOverflowError, "needed: #{needed_length}") if retried

    out_ptr = out_ptr.resized_to(needed_length)
    retried = true
    retry
  end
end

#format(datetime) ⇒ Object



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
# File 'lib/ffi-icu/time_formatting.rb', line 153

def format(datetime)
  needed_length = 0
  out_ptr = UCharPointer.new(needed_length)

  retried = false

  begin
    Lib.check_error do |error|
      case datetime
      when Date
        needed_length = Lib.udat_format(
          @f,
          Time.mktime(datetime.year, datetime.month, datetime.day, 0, 0, 0, 0).to_f * 1000.0,
          out_ptr, needed_length, nil, error
        )
      when Time
        needed_length = Lib.udat_format(@f, datetime.to_f * 1000.0, out_ptr, needed_length, nil, error)
      end
    end

    out_ptr.string
  rescue BufferOverflowError
    raise(BufferOverflowError, "needed: #{needed_length}") if retried

    out_ptr = out_ptr.resized_to(needed_length)
    retried = true
    retry
  end
end

#parse(str) ⇒ Object



144
145
146
147
148
149
150
151
# File 'lib/ffi-icu/time_formatting.rb', line 144

def parse(str)
  str_u = UCharPointer.from_string(str)
  str_l = str.size
  Lib.check_error do |error|
    ret = Lib.udat_parse(@f, str_u, str_l, nil, error)
    Time.at(ret / 1000.0)
  end
end

#set_date_format(localized, pattern_str) ⇒ Object



222
223
224
225
226
227
228
# File 'lib/ffi-icu/time_formatting.rb', line 222

def set_date_format(localized, pattern_str)
  set_date_format_impl(localized, pattern_str)

  # After setting the date format string, we need to ensure that any hour
  # symbols were properly localised according to @hour_cycle.
  replace_hour_symbol!
end

#skeleton_format(skeleton_pattern_str, locale) ⇒ Object



230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/ffi-icu/time_formatting.rb', line 230

def skeleton_format(skeleton_pattern_str, locale)
  skeleton_pattern_ptr = UCharPointer.from_string(skeleton_pattern_str)
  skeleton_pattern_len = skeleton_pattern_str.size

  needed_length = 0
  pattern_ptr = UCharPointer.new(needed_length)

  udatpg_ptr = Lib.check_error { |error| Lib.udatpg_open(locale, error) }
  generator = FFI::AutoPointer.new(udatpg_ptr, Lib.method(:udatpg_close))

  retried = false

  begin
    Lib.check_error do |error|
      needed_length = Lib.udatpg_getBestPattern(generator, skeleton_pattern_ptr, skeleton_pattern_len,
                                                pattern_ptr, needed_length, error)
    end

    [needed_length, pattern_ptr]
  rescue BufferOverflowError
    raise(BufferOverflowError, "needed: #{needed_length}") if retried

    pattern_ptr = pattern_ptr.resized_to(needed_length)
    retried = true
    retry
  end
end

#update_tz_format(format, tz_style) ⇒ Object

time-zone formating



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/ffi-icu/time_formatting.rb', line 184

def update_tz_format(format, tz_style)
  return format if format !~ /(.*?)(\s*(?:[zZOV]+\s*))(.*?)/

  pre = ::Regexp.last_match(1)
  tz = ::Regexp.last_match(2)
  suff = ::Regexp.last_match(3)
  if tz_style == :none
    tz = (tz =~ /\s/) && !pre.empty? && !suff.empty? ? ' ' : ''
  else
    repl = TZ_MAP[tz_style]
    raise('no such tz_style') unless repl

    tz.gsub!(/^(\s*)(.*?)(\s*)$/, "\\1#{repl}\\3")
  end
  pre + tz + suff
end