mirror of https://github.com/erickguan/ffi-icu.git
Add support for skeleton date formats
This commit is contained in:
parent
7fc5d65f6d
commit
f71e1fabeb
|
@ -425,11 +425,12 @@ module ICU
|
|||
attach_function :unum_set_attribute, "unum_setAttribute#{suffix}", [:pointer, :number_format_attribute, :int32_t], :void
|
||||
# date
|
||||
enum :date_format_style, [
|
||||
:none, -1,
|
||||
:full, 0,
|
||||
:long, 1,
|
||||
:medium, 2,
|
||||
:short, 3,
|
||||
:pattern, -2,
|
||||
:none, -1,
|
||||
:full, 0,
|
||||
:long, 1,
|
||||
:medium, 2,
|
||||
:short, 3,
|
||||
]
|
||||
attach_function :udat_open, "udat_open#{suffix}", [:date_format_style, :date_format_style, :string, :pointer, :int32_t, :pointer, :int32_t, :pointer ], :pointer
|
||||
attach_function :udat_close, "unum_close#{suffix}", [:pointer], :void
|
||||
|
@ -437,6 +438,9 @@ module ICU
|
|||
attach_function :udat_parse, "udat_parse#{suffix}", [:pointer, :pointer, :int32_t, :pointer, :pointer], :double
|
||||
attach_function :udat_toPattern, "udat_toPattern#{suffix}", [:pointer, :bool , :pointer, :int32_t , :pointer], :int32_t
|
||||
attach_function :udat_applyPattern, "udat_applyPattern#{suffix}", [:pointer, :bool , :pointer, :int32_t ], :void
|
||||
# skeleton pattern
|
||||
attach_function :udatpg_open, "udatpg_open#{suffix}", [:string, :pointer], :pointer
|
||||
attach_function :udatpg_getBestPattern, "udatpg_getBestPattern#{suffix}", [:pointer, :pointer, :int32_t, :pointer, :int32_t, :pointer], :int32_t
|
||||
# tz
|
||||
attach_function :ucal_setDefaultTimeZone, "ucal_setDefaultTimeZone#{suffix}", [:pointer, :pointer], :int32_t
|
||||
attach_function :ucal_getDefaultTimeZone, "ucal_getDefaultTimeZone#{suffix}", [:pointer, :int32_t, :pointer], :int32_t
|
||||
|
|
|
@ -65,21 +65,46 @@ module ICU
|
|||
|
||||
private
|
||||
|
||||
def make_formatter(time_style, date_style, locale, time_zone_str)
|
||||
def make_formatter(time_style, date_style, locale, time_zone_str, skeleton)
|
||||
time_zone = nil
|
||||
d_len = 0
|
||||
tz_len = 0
|
||||
if time_zone_str
|
||||
time_zone = UCharPointer.from_string(time_zone_str)
|
||||
d_len = time_zone_str.size
|
||||
tz_len = time_zone_str.size
|
||||
else
|
||||
Lib.check_error { | error|
|
||||
i_len = 150
|
||||
time_zone = UCharPointer.new(i_len)
|
||||
d_len = Lib.ucal_getDefaultTimeZone(time_zone, i_len, error)
|
||||
tz_len = Lib.ucal_getDefaultTimeZone(time_zone, i_len, error)
|
||||
}
|
||||
end
|
||||
|
||||
ptr = Lib.check_error { | error| Lib.udat_open(time_style, date_style, locale, time_zone, d_len, FFI::MemoryPointer.new(4), -1, error) }
|
||||
pattern_len = -1
|
||||
pattern_ptr = FFI::MemoryPointer.new(4)
|
||||
|
||||
if skeleton
|
||||
skeleton = UCharPointer.from_string(skeleton)
|
||||
|
||||
pattern_len = 0
|
||||
pattern_ptr = UCharPointer.new(pattern_len)
|
||||
|
||||
pg_ptr = Lib.check_error { |error| Lib.udatpg_open(locale, error) }
|
||||
generator = FFI::AutoPointer.new(pg_ptr, Lib.method(:udat_close))
|
||||
|
||||
retried = false
|
||||
begin
|
||||
Lib.check_error do |error|
|
||||
pattern_len = Lib.udatpg_getBestPattern(generator, skeleton, skeleton.size, pattern_ptr, pattern_len, error)
|
||||
end
|
||||
rescue BufferOverflowError
|
||||
raise BufferOverflowError, "needed: #{pattern_len}" if retried
|
||||
pattern_ptr = pattern_ptr.resized_to pattern_len
|
||||
retried = true
|
||||
retry
|
||||
end
|
||||
end
|
||||
|
||||
ptr = Lib.check_error { | error| Lib.udat_open(time_style, date_style, locale, time_zone, tz_len, pattern_ptr, pattern_len, error) }
|
||||
FFI::AutoPointer.new(ptr, Lib.method(:udat_close))
|
||||
end
|
||||
end
|
||||
|
@ -91,7 +116,9 @@ module ICU
|
|||
locale = options[:locale] || 'C'
|
||||
tz_style = options[:tz_style]
|
||||
time_zone = options[:zone]
|
||||
@f = make_formatter(time_style, date_style, locale, time_zone)
|
||||
skeleton = options[:skeleton]
|
||||
|
||||
@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)
|
||||
|
@ -177,6 +204,23 @@ module ICU
|
|||
needed_length = Lib.udat_applyPattern(@f, localized, pattern, pattern_len)
|
||||
end
|
||||
end
|
||||
|
||||
def with_retry(out_ptr)
|
||||
needed_length = 0
|
||||
out_ptr = UCharPointer.new(needed_length)
|
||||
retried = false
|
||||
|
||||
begin
|
||||
Lib.check_error do |error|
|
||||
yield(error)
|
||||
end
|
||||
rescue BufferOverflowError
|
||||
raise BufferOverflowError, "needed: #{needed_length}" if retried
|
||||
out_ptr = out_ptr.resized_to needed_length
|
||||
retried = true
|
||||
retry
|
||||
end
|
||||
end
|
||||
end # DateTimeFormatter
|
||||
end # Formatting
|
||||
end # ICU
|
||||
|
|
|
@ -59,7 +59,7 @@ module ICU
|
|||
expect(f2.format(t8)).to eq("3/29/08#{en_sep} 6:38:24 AM #{en_tz}")
|
||||
end
|
||||
|
||||
f3 = TimeFormatting.create(:locale => 'de_DE', :zone => 'Africa/Dakar ', :date => :short , :time => :long)
|
||||
f3 = TimeFormatting.create(:locale => 'de_DE', :zone => 'Africa/Dakar', :date => :short , :time => :long)
|
||||
ge_sep = ""
|
||||
if cldr_version >= "27.0.1"
|
||||
ge_sep = ","
|
||||
|
@ -82,6 +82,19 @@ module ICU
|
|||
expect(f3.format(t7)).to eq("29.03.08#{ge_sep} 02:37:23 GMT")
|
||||
expect(f3.format(t8)).to eq("29.03.08#{ge_sep} 03:38:24 GMT")
|
||||
end
|
||||
|
||||
context 'skeleton pattern' do
|
||||
f4 = TimeFormatting.create(:locale => 'fr_FR', :date => :pattern , :time => :pattern, :skeleton => 'MMMy')
|
||||
|
||||
it 'check format' do
|
||||
expect(f4.format(t0)).to eq("nov. 2008")
|
||||
expect(f4.format(t1)).to eq("oct. 2008")
|
||||
end
|
||||
|
||||
it 'check date_format' do
|
||||
expect(f4.date_format(true)).to eq("MMM y")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue