icu-calendar 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b86febf5c2e4f2d55a1b67b9e308b20b75e728f
4
+ data.tar.gz: ceca6826de5dfbe5a4485e6cd7c31872904e5f6a
5
+ SHA512:
6
+ metadata.gz: 17221530b16d9f8da24c767b7d9a4b4d140c2edbcb4d9f2ffbb85b62f15e42dba1c26d668c84009e71a8f64dac4a5ea14f9f849bc790003a186d232212da8ca5
7
+ data.tar.gz: 29c51cbe355bb924f707c64d584896d399e3f6ed061c55ebfc4231f35a6e5ef56bae8fa15ebe82365e993f1961e924ca96c069a1c001fbb3e21d2dfd30aa3aef
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2014 Christopher Bandy
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,51 @@
1
+ # ICU::Calendar
2
+
3
+ [Ruby-FFI] bindings for the Calendar functionality of [ICU].
4
+
5
+ [![Build Status](https://travis-ci.org/cbandy/icu-calendar.svg?branch=master)](https://travis-ci.org/cbandy/icu-calendar)
6
+
7
+
8
+ ## Requirements
9
+
10
+ * [ICU4C] >= 4.2
11
+ * [Ruby-FFI]
12
+ * Ruby >= 1.9.3
13
+
14
+
15
+ ## Installation
16
+
17
+ ```sh
18
+ gem install icu-calendar
19
+ ```
20
+
21
+ ### Ubuntu
22
+
23
+ ```sh
24
+ sudo apt-get install ^libicu..$
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```ruby
30
+ require 'icu/calendar'
31
+
32
+ # Calendar for the default locale at the current time in the current timezone
33
+ ICU::Calendar.new
34
+
35
+ ICU::Calendar.new(locale: 'de_DE')
36
+ ICU::Calendar.new(time: Time.now - 300)
37
+ ICU::Calendar.new(timezone: 'America/New_York')
38
+
39
+ # Chinese calendar for the default locale
40
+ ICU::Calendar.new(locale: '@calendar=chinese')
41
+
42
+ calendar = ICU::Calendar.new
43
+ calendar[:year] # 2014
44
+ calendar.add(:month, 12)
45
+ calendar[:year] # 2015
46
+ ```
47
+
48
+
49
+ [ICU]: http://icu-project.org "International Components for Unicode"
50
+ [ICU4C]: http://icu-project.org/download
51
+ [Ruby-FFI]: https://github.com/ffi/ffi
@@ -0,0 +1,401 @@
1
+ require 'icu/calendar/library'
2
+
3
+ module ICU
4
+ class Calendar
5
+ RuntimeError = Class.new(::RuntimeError)
6
+
7
+ include Comparable
8
+
9
+ class << self
10
+ def available_locales
11
+ (0...Library.ucal_countAvailable).map(&Library.method(:ucal_getAvailable))
12
+ end
13
+
14
+ def canonical_timezone_identifier(timezone)
15
+ FFI::MemoryPointer.new(:bool) do |is_system_id|
16
+ return Library.wchar_buffer_from_string(timezone) do |w_timezone|
17
+ Library.read_into_wchar_buffer(32) do |buffer, status|
18
+ Library.ucal_getCanonicalTimeZoneID(
19
+ w_timezone, -1,
20
+ buffer, buffer.size / buffer.type_size,
21
+ is_system_id, status
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def country_timezones(country)
29
+ Library.read_wchar_enumeration(->(status) do
30
+ Library.ucal_openCountryTimeZones(country, status)
31
+ end).to_a
32
+ end
33
+
34
+ def default_timezone
35
+ Library.read_into_wchar_buffer(32) do |buffer, status|
36
+ Library.ucal_getDefaultTimeZone(buffer, buffer.size / buffer.type_size, status)
37
+ end
38
+ end
39
+
40
+ def default_timezone=(timezone)
41
+ Library.wchar_buffer_from_string(timezone) do |w_timezone|
42
+ Library.assert_success do |status|
43
+ Library.ucal_setDefaultTimeZone(w_timezone, status)
44
+ end
45
+ end
46
+ end
47
+
48
+ def dst_savings(timezone)
49
+ Library.wchar_buffer_from_string(timezone) do |w_timezone|
50
+ Library.assert_success do |status|
51
+ Library.ucal_getDSTSavings(w_timezone, status)
52
+ end
53
+ end
54
+ end
55
+
56
+ def timezone_data_version
57
+ Library.assert_success do |status|
58
+ Library.ucal_getTZDataVersion(status)
59
+ end
60
+ end
61
+
62
+ def timezone_identifiers(type, region = nil, offset = nil)
63
+ offset = FFI::MemoryPointer.new(:int32).write_int32(offset) unless offset.nil?
64
+
65
+ Library.read_wchar_enumeration(->(status) do
66
+ Library.ucal_openTimeZoneIDEnumeration(type, region, offset, status)
67
+ end).to_a
68
+ ensure
69
+ offset.free unless offset.nil?
70
+ end
71
+
72
+ def timezones
73
+ Library.read_wchar_enumeration(->(status) do
74
+ Library.ucal_openTimeZones(status)
75
+ end).to_a
76
+ end
77
+ end
78
+
79
+ def [](field)
80
+ field_value_to_symbol(field, Library.assert_success do |status|
81
+ Library.ucal_get(@calendar, field, status)
82
+ end)
83
+ end
84
+
85
+ def []=(field, value)
86
+ if value.nil?
87
+ Library.ucal_clearField(@calendar, field)
88
+ else
89
+ Library.ucal_set(@calendar, field, value)
90
+ end
91
+ end
92
+
93
+ def <=>(other)
94
+ time <=> coerce_to_milliseconds(other)
95
+ end
96
+
97
+ def actual_maximum(field)
98
+ field_value_to_symbol(field, Library.assert_success do |status|
99
+ Library.ucal_getLimit(@calendar, field, :actual_maximum, status)
100
+ end)
101
+ end
102
+
103
+ def actual_minimum(field)
104
+ field_value_to_symbol(field, Library.assert_success do |status|
105
+ Library.ucal_getLimit(@calendar, field, :actual_minimum, status)
106
+ end)
107
+ end
108
+
109
+ def add(field, amount)
110
+ Library.assert_success do |status|
111
+ Library.ucal_add(@calendar, field, amount, status)
112
+ end
113
+
114
+ self
115
+ end
116
+
117
+ def clear
118
+ Library.ucal_clear(@calendar)
119
+ end
120
+
121
+ def daylight_time?
122
+ Library.assert_success do |status|
123
+ Library.ucal_inDaylightTime(@calendar, status)
124
+ end
125
+ end
126
+
127
+ def difference(from, field)
128
+ from = coerce_to_milliseconds(from)
129
+ Library.assert_success do |status|
130
+ Library.ucal_getFieldDifference(@calendar, from, field, status)
131
+ end
132
+ end
133
+
134
+ def eql?(other)
135
+ equivalent?(other) && time == other.time
136
+ end
137
+
138
+ def equivalent?(other)
139
+ Calendar === other && Library.ucal_equivalentTo(@calendar, other.calendar)
140
+ end
141
+
142
+ def first_day_of_week
143
+ Library.enum_type(:day_of_week)[Library.ucal_getAttribute(@calendar, :first_day_of_week)]
144
+ end
145
+
146
+ def first_day_of_week=(day_of_week)
147
+ day_of_week = Library.enum_type(:day_of_week)[day_of_week] if Symbol === day_of_week
148
+ Library.ucal_setAttribute(@calendar, :first_day_of_week, day_of_week)
149
+ end
150
+
151
+ def greatest_minimum(field)
152
+ field_value_to_symbol(field, Library.assert_success do |status|
153
+ Library.ucal_getLimit(@calendar, field, :greatest_minimum, status)
154
+ end)
155
+ end
156
+
157
+ def gregorian_change
158
+ Library.assert_success do |status|
159
+ Library.ucal_getGregorianChange(@calendar, status)
160
+ end
161
+ end
162
+
163
+ def gregorian_change=(time)
164
+ time = coerce_to_milliseconds(time)
165
+
166
+ Library.assert_success do |status|
167
+ Library.ucal_setGregorianChange(@calendar, time, status)
168
+ end
169
+ end
170
+
171
+ def initialize(options = {})
172
+ calendar = wchar_buffer_from_string_or_nil(options[:timezone]) do |timezone|
173
+ Library.assert_success do |status|
174
+ Library.ucal_open(timezone, -1, options[:locale], :default, status)
175
+ end
176
+ end
177
+
178
+ @calendar = automatically_close(calendar)
179
+ self.time = options[:time] if options[:time]
180
+ end
181
+
182
+ def is_set?(field)
183
+ Library.ucal_isSet(@calendar, field)
184
+ end
185
+
186
+ def least_maximum(field)
187
+ field_value_to_symbol(field, Library.assert_success do |status|
188
+ Library.ucal_getLimit(@calendar, field, :least_maximum, status)
189
+ end)
190
+ end
191
+
192
+ def lenient?
193
+ Library.ucal_getAttribute(@calendar, :lenient).nonzero?
194
+ end
195
+
196
+ def lenient=(value)
197
+ Library.ucal_setAttribute(@calendar, :lenient, value ? 1 : 0)
198
+ end
199
+
200
+ def locale(type = :valid)
201
+ Library.assert_success do |status|
202
+ Library.ucal_getLocaleByType(@calendar, type, status)
203
+ end
204
+ end
205
+
206
+ def maximum(field)
207
+ field_value_to_symbol(field, Library.assert_success do |status|
208
+ Library.ucal_getLimit(@calendar, field, :maximum, status)
209
+ end)
210
+ end
211
+
212
+ def minimal_days_in_first_week
213
+ Library.ucal_getAttribute(@calendar, :minimal_days_in_first_week)
214
+ end
215
+
216
+ def minimal_days_in_first_week=(value)
217
+ Library.ucal_setAttribute(@calendar, :minimal_days_in_first_week, value)
218
+ end
219
+
220
+ def minimum(field)
221
+ field_value_to_symbol(field, Library.assert_success do |status|
222
+ Library.ucal_getLimit(@calendar, field, :minimum, status)
223
+ end)
224
+ end
225
+
226
+ def next_timezone_transition(inclusive = false)
227
+ timezone_transition(inclusive ? :next_inclusive : :next)
228
+ end
229
+
230
+ def previous_timezone_transition(inclusive = false)
231
+ timezone_transition(inclusive ? :previous_inclusive : :previous)
232
+ end
233
+
234
+ def repeated_wall_time
235
+ Library.enum_type(:walltime_option)[Library.ucal_getAttribute(@calendar, :repeated_wall_time)]
236
+ end
237
+
238
+ def repeated_wall_time=(option)
239
+ option = Library.enum_type(:walltime_option)[option] if Symbol === option
240
+ Library.ucal_setAttribute(@calendar, :repeated_wall_time, option)
241
+ end
242
+
243
+ def roll(field, amount)
244
+ Library.assert_success do |status|
245
+ Library.ucal_roll(@calendar, field, amount, status)
246
+ end
247
+
248
+ self
249
+ end
250
+
251
+ def set_date(year, month, day)
252
+ Library.assert_success do |status|
253
+ Library.ucal_setDate(@calendar, year, month, day, status)
254
+ end
255
+ end
256
+
257
+ def set_date_and_time(year, month, day, hour, minute, second)
258
+ Library.assert_success do |status|
259
+ Library.ucal_setDateTime(@calendar, year, month, day, hour, minute, second, status)
260
+ end
261
+ end
262
+
263
+ def skipped_wall_time
264
+ Library.enum_type(:walltime_option)[Library.ucal_getAttribute(@calendar, :skipped_wall_time)]
265
+ end
266
+
267
+ def skipped_wall_time=(option)
268
+ option = Library.enum_type(:walltime_option)[option] if Symbol === option
269
+ Library.ucal_setAttribute(@calendar, :skipped_wall_time, option)
270
+ end
271
+
272
+ def time
273
+ Library.assert_success do |status|
274
+ Library.ucal_getMillis(@calendar, status)
275
+ end
276
+ end
277
+
278
+ def time=(time)
279
+ time = coerce_to_milliseconds(time)
280
+
281
+ Library.assert_success do |status|
282
+ Library.ucal_setMillis(@calendar, time, status)
283
+ end
284
+ end
285
+
286
+ def timezone
287
+ Library.read_into_wchar_buffer(32) do |buffer, status|
288
+ Library.ucal_getTimeZoneID(@calendar, buffer, buffer.size / buffer.type_size, status)
289
+ end
290
+ end
291
+
292
+ def timezone=(timezone)
293
+ wchar_buffer_from_string_or_nil(timezone) do |w_timezone|
294
+ Library.assert_success do |status|
295
+ Library.ucal_setTimeZone(@calendar, w_timezone, -1, status)
296
+ end
297
+ end
298
+ end
299
+
300
+ def timezone_display_name(type = :standard, locale = nil)
301
+ Library.read_into_wchar_buffer(32) do |buffer, status|
302
+ Library.ucal_getTimeZoneDisplayName(@calendar, type, locale, buffer, buffer.size / buffer.type_size, status)
303
+ end
304
+ end
305
+
306
+ def to_time
307
+ Time.new(
308
+ self[:year],
309
+ self[Library.enum_type(:date_field)[:month]] + 1,
310
+ self[:day_of_month],
311
+ self[:hour_of_day],
312
+ self[:minute],
313
+ self[:second] + Rational(self[:millisecond], 1000),
314
+ (self[:zone_offset] + self[:dst_offset]) / 1000
315
+ )
316
+ end
317
+
318
+ def type
319
+ Library.assert_success do |status|
320
+ Library.ucal_getType(@calendar, status)
321
+ end.to_sym
322
+ end
323
+
324
+ def weekday_type(day_of_week)
325
+ Library.assert_success do |status|
326
+ Library.ucal_getDayOfWeekType(@calendar, day_of_week, status)
327
+ end
328
+ end
329
+
330
+ def weekend?
331
+ Library.assert_success do |status|
332
+ Library.ucal_isWeekend(@calendar, time, status)
333
+ end
334
+ end
335
+
336
+ def weekend_transition(day_of_week)
337
+ Library.assert_success do |status|
338
+ Library.ucal_getWeekendTransition(@calendar, day_of_week, status)
339
+ end
340
+ end
341
+
342
+ protected
343
+
344
+ attr_reader :calendar
345
+
346
+ private
347
+
348
+ def automatically_close(calendar_pointer)
349
+ FFI::AutoPointer.new(calendar_pointer, Library.method(:ucal_close))
350
+ end
351
+
352
+ def coerce_to_milliseconds(value)
353
+ if Calendar === value
354
+ value.time
355
+ else
356
+ value = value.to_time if value.respond_to? :to_time
357
+ value = value.getutc.to_f * 1000 if value.is_a? Time
358
+ value
359
+ end
360
+ end
361
+
362
+ def field_value_to_symbol(field, value)
363
+ case field
364
+ when :am_pm, :day_of_week, :month
365
+ Library.enum_type(field)[value]
366
+ else
367
+ value
368
+ end
369
+ end
370
+
371
+ def initialize_copy(other)
372
+ super
373
+
374
+ @calendar = automatically_close(
375
+ Library.assert_success do |status|
376
+ Library.ucal_clone(@calendar, status)
377
+ end
378
+ )
379
+ end
380
+
381
+ def timezone_transition(type)
382
+ FFI::MemoryPointer.new(:double) do |time|
383
+ valid = Library.assert_success do |status|
384
+ Library.ucal_getTimeZoneTransitionDate(@calendar, type, time, status)
385
+ end
386
+
387
+ return valid ? time.read_double : nil
388
+ end
389
+ end
390
+
391
+ def wchar_buffer_from_string_or_nil(string)
392
+ if string.nil?
393
+ yield string
394
+ else
395
+ Library.wchar_buffer_from_string(string) do |buffer|
396
+ yield buffer
397
+ end
398
+ end
399
+ end
400
+ end
401
+ end
@@ -0,0 +1,198 @@
1
+ require 'ffi'
2
+
3
+ module ICU
4
+ class Calendar
5
+ module Library
6
+ extend FFI::Library
7
+
8
+ %w( icutu ).tap do |libraries|
9
+ begin
10
+ ffi_lib(*libraries)
11
+ rescue LoadError
12
+ ffi_lib(*libraries.map do |lib|
13
+ if 'dll' == FFI::Platform::LIBSUFFIX
14
+ [42, 44, 46, *(48..100)].map { |i| "#{lib}#{i}.#{FFI::Platform::LIBSUFFIX}" }
15
+ else
16
+ [42, 44, 46, *(48..100)].map { |i| "#{lib}.#{FFI::Platform::LIBSUFFIX}.#{i}" }
17
+ end
18
+ end)
19
+ end.each do |library|
20
+ @suffix ||= ['', '_4_2', '_44', '_46', *(48..100).map { |i| "_#{i}" }].find do |suffix|
21
+ function_names("u_errorName#{suffix}", nil).any? { |name| library.find_function(name) }
22
+ end
23
+ end
24
+ end
25
+
26
+ require_relative 'library/constants'
27
+ require_relative 'library/error_code'
28
+ require_relative 'library/version_info'
29
+
30
+ U_BUFFER_OVERFLOW_ERROR = 15
31
+ U_MAX_VERSION_LENGTH = 4
32
+ U_MAX_VERSION_STRING_LENGTH = 20
33
+ U_ZERO_ERROR = 0
34
+
35
+ class << self
36
+ def assert_success
37
+ ErrorCode.new do |status|
38
+ result = yield status
39
+ raise RuntimeError, status.to_s unless status.success?
40
+ return result
41
+ end
42
+ end
43
+
44
+ def read_into_wchar_buffer(length)
45
+ ErrorCode.new do |status|
46
+ for _ in 1..2
47
+ FFI::Buffer.new(:uint16, length, false) do |buffer|
48
+ length = yield buffer, status
49
+ return buffer.read_array_of_uint16(length).pack('U*') if status.success?
50
+ raise RuntimeError, status.to_s unless status.buffer_overflow?
51
+ status.clear
52
+ end
53
+ end
54
+ raise RuntimeError, "#{status}: Needed #{length}"
55
+ end
56
+ end
57
+
58
+ def read_wchar_enumeration(open)
59
+ return enum_for(:read_wchar_enumeration, open) unless block_given?
60
+
61
+ Library::ErrorCode.new do |status|
62
+ enumeration = open.call(status)
63
+ raise RuntimeError, status.to_s unless status.success?
64
+
65
+ begin
66
+ FFI::MemoryPointer.new(:int32) do |length|
67
+ loop do
68
+ pointer = Library.uenum_unext(enumeration, length, status)
69
+ raise RuntimeError, status.to_s unless status.success?
70
+ break if pointer.null?
71
+ yield pointer.read_array_of_uint16(length.read_int32).pack('U*')
72
+ end
73
+ end
74
+ ensure
75
+ Library.uenum_close(enumeration)
76
+ end
77
+ end
78
+ end
79
+
80
+ def version
81
+ @version ||= VersionInfo.new.tap { |version| u_getVersion(version) }
82
+ end
83
+
84
+ def wchar_buffer_from_string(string, &block)
85
+ codepoints = string.encode('UTF-8').unpack('U*') << 0
86
+ FFI::Buffer.new(:uint16, codepoints.length, false) do |buffer|
87
+ buffer.write_array_of_uint16(codepoints)
88
+ return yield buffer
89
+ end
90
+ end
91
+
92
+ private
93
+
94
+ def attach_icu_function(name, type, *args)
95
+ attach_function name, "#{name}#{@suffix}", *args, type
96
+ end
97
+
98
+ def icu_version_at_least(version)
99
+ Gem::Version.new(version) <= Gem::Version.new(self.version)
100
+ end
101
+ end
102
+
103
+ enum :am_pm, am_pm_enum
104
+ enum :attribute, attribute_enum
105
+ enum :calendar_type, calendar_type_enum
106
+ enum :date_field, date_field_enum
107
+ enum :day_of_week, day_of_week_enum
108
+ enum :display_name_type, display_name_type_enum
109
+ enum :limit_type, limit_type_enum
110
+ enum :locale_type, locale_type_enum
111
+ enum :month, month_enum
112
+ enum :system_timezone_type, system_timezone_type_enum
113
+ enum :timezone_transition_type, timezone_transition_type_enum
114
+ enum :walltime_option, walltime_option_enum
115
+ enum :weekday_type, weekday_type_enum
116
+
117
+ typedef :pointer, :calendar
118
+ typedef :double, :date
119
+ typedef :pointer, :enumeration
120
+ typedef ErrorCode, :status
121
+ typedef VersionInfo, :version
122
+
123
+ attach_icu_function :u_errorName, :string, [:int]
124
+
125
+ attach_icu_function :u_getVersion, :void, [:version]
126
+ attach_icu_function :u_versionToString, :void, [:version, :buffer_out]
127
+
128
+ # Enumeration
129
+ attach_icu_function :uenum_close, :void, [:enumeration]
130
+ attach_icu_function :uenum_next, :string, [:enumeration, :buffer_out, :status]
131
+ attach_icu_function :uenum_unext, :pointer, [:enumeration, :buffer_out, :status]
132
+
133
+ # Locales
134
+ attach_icu_function :ucal_countAvailable, :int32, []
135
+ attach_icu_function :ucal_getAvailable, :string, [:int32]
136
+ attach_icu_function :uloc_getDefault, :string, []
137
+
138
+ # Time Zones
139
+ attach_icu_function :ucal_getCanonicalTimeZoneID, :int32, [:buffer_in, :int32, :buffer_out, :int32, :buffer_out, :status]
140
+ attach_icu_function :ucal_getDefaultTimeZone, :int32, [:buffer_out, :int32, :status]
141
+ attach_icu_function :ucal_getDSTSavings, :int32, [:buffer_in, :status]
142
+ attach_icu_function :ucal_getTZDataVersion, :string, [:status]
143
+ attach_icu_function :ucal_setDefaultTimeZone, :void, [:buffer_in, :status]
144
+
145
+ attach_icu_function :ucal_openTimeZones, :enumeration, [:status]
146
+ attach_icu_function :ucal_openCountryTimeZones, :enumeration, [:string, :status]
147
+
148
+ # Calendar
149
+ attach_icu_function :ucal_clone, :calendar, [:calendar, :status]
150
+ attach_icu_function :ucal_close, :void, [:calendar]
151
+ attach_icu_function :ucal_equivalentTo, :bool, [:calendar, :calendar]
152
+ attach_icu_function :ucal_open, :calendar, [:buffer_in, :int32, :string, :calendar_type, :status]
153
+
154
+ attach_icu_function :ucal_getAttribute, :int32, [:calendar, :attribute]
155
+ attach_icu_function :ucal_getGregorianChange, :date, [:calendar, :status]
156
+ attach_icu_function :ucal_getLocaleByType, :string, [:calendar, :locale_type, :status]
157
+ attach_icu_function :ucal_getMillis, :date, [:calendar, :status]
158
+ attach_icu_function :ucal_getTimeZoneDisplayName, :int32, [:calendar, :display_name_type, :string, :buffer_out, :int32, :status]
159
+ attach_icu_function :ucal_getType, :string, [:calendar, :status]
160
+ attach_icu_function :ucal_inDaylightTime, :bool, [:calendar, :status]
161
+ attach_icu_function :ucal_setAttribute, :void, [:calendar, :attribute, :int32]
162
+ attach_icu_function :ucal_setDate, :void, [:calendar, :int32, :month, :int32, :status]
163
+ attach_icu_function :ucal_setDateTime, :void, [:calendar, :int32, :month, :int32, :int32, :int32, :int32, :status]
164
+ attach_icu_function :ucal_setGregorianChange, :void, [:calendar, :date, :status]
165
+ attach_icu_function :ucal_setMillis, :void, [:calendar, :date, :status]
166
+ attach_icu_function :ucal_setTimeZone, :void, [:calendar, :buffer_in, :int32, :status]
167
+
168
+ # Calendar Fields
169
+ attach_icu_function :ucal_add, :void, [:calendar, :date_field, :int32, :status]
170
+ attach_icu_function :ucal_clear, :void, [:calendar]
171
+ attach_icu_function :ucal_clearField, :void, [:calendar, :date_field]
172
+ attach_icu_function :ucal_get, :int32, [:calendar, :date_field, :status]
173
+ attach_icu_function :ucal_getLimit, :int32, [:calendar, :date_field, :limit_type, :status]
174
+ attach_icu_function :ucal_isSet, :bool, [:calendar, :date_field]
175
+ attach_icu_function :ucal_roll, :void, [:calendar, :date_field, :int32, :status]
176
+ attach_icu_function :ucal_set, :void, [:calendar, :date_field, :int32]
177
+
178
+ if icu_version_at_least('4.4')
179
+ attach_icu_function :ucal_getDayOfWeekType, :weekday_type, [:calendar, :day_of_week, :status]
180
+ attach_icu_function :ucal_getWeekendTransition, :int32, [:calendar, :day_of_week, :status]
181
+ attach_icu_function :ucal_isWeekend, :bool, [:calendar, :date, :status]
182
+ end
183
+
184
+ if icu_version_at_least('4.8')
185
+ attach_icu_function :ucal_getFieldDifference, :int32, [:calendar, :date, :date_field, :status]
186
+ attach_icu_function :ucal_openTimeZoneIDEnumeration, :enumeration, [:system_timezone_type, :string, :buffer_in, :status]
187
+ end
188
+
189
+ if icu_version_at_least('50')
190
+ attach_icu_function :ucal_getTimeZoneTransitionDate, :bool, [:calendar, :timezone_transition_type, :buffer_out, :status]
191
+ end
192
+
193
+ if icu_version_at_least('51')
194
+ attach_icu_function :ucal_getTimeZoneID, :int32, [:calendar, :buffer_out, :int32, :status]
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,71 @@
1
+ class ICU::Calendar
2
+ module Library
3
+
4
+ class << self
5
+ private
6
+
7
+ def am_pm_enum
8
+ [:am, :pm]
9
+ end
10
+
11
+ def attribute_enum
12
+ [
13
+ :lenient, :first_day_of_week, :minimal_days_in_first_week,
14
+ # ICU >= 49
15
+ :repeated_wall_time, :skipped_wall_time,
16
+ ]
17
+ end
18
+
19
+ def calendar_type_enum
20
+ [:default, :gregorian]
21
+ end
22
+
23
+ def date_field_enum
24
+ [
25
+ :era, :year, :month, :week_of_year, :week_of_month,
26
+ :date, :day_of_year, :day_of_month, 5, :day_of_week, 7, :day_of_week_in_month,
27
+ :am_pm, :hour, :hour_of_day, :minute, :second, :millisecond, :zone_offset, :dst_offset,
28
+ :year_woy, :dow_local, :extended_year, :julian_day, :milliseconds_in_day, :is_leap_month,
29
+ :field_count
30
+ ]
31
+ end
32
+
33
+ def day_of_week_enum
34
+ [:sunday, 1, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday]
35
+ end
36
+
37
+ def display_name_type_enum
38
+ [:standard, :short_standard, :dst, :short_dst]
39
+ end
40
+
41
+ def limit_type_enum
42
+ [:minimum, :maximum, :greatest_minimum, :least_maximum, :actual_minimum, :actual_maximum]
43
+ end
44
+
45
+ def locale_type_enum
46
+ [:actual, :valid]
47
+ end
48
+
49
+ def month_enum
50
+ [:january, :february, :march, :april, :may, :june, :july, :august, :september, :october, :november, :december, :undecimber]
51
+ end
52
+
53
+ def system_timezone_type_enum
54
+ [:any, :canonical, :canonical_location]
55
+ end
56
+
57
+ def timezone_transition_type_enum
58
+ [:next, :next_inclusive, :previous, :previous_inclusive]
59
+ end
60
+
61
+ def walltime_option_enum
62
+ [:last, :first, :next_valid]
63
+ end
64
+
65
+ def weekday_type_enum
66
+ [:weekday, :weekend, :weekend_onset, :weekend_cease]
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,33 @@
1
+ class ICU::Calendar
2
+ module Library
3
+ class ErrorCode < FFI::MemoryPointer
4
+ extend FFI::DataConverter
5
+
6
+ def self.native_type
7
+ FFI::Type::POINTER
8
+ end
9
+
10
+ def initialize
11
+ super(:int)
12
+ end
13
+
14
+ def buffer_overflow?
15
+ to_i == U_BUFFER_OVERFLOW_ERROR
16
+ end
17
+
18
+ def failure?
19
+ to_i > U_ZERO_ERROR
20
+ end
21
+
22
+ def success?
23
+ to_i <= U_ZERO_ERROR
24
+ end
25
+
26
+ alias_method :to_i, :read_int
27
+
28
+ def to_s
29
+ Library.u_errorName(to_i)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,26 @@
1
+ class ICU::Calendar
2
+ module Library
3
+ class VersionInfo < FFI::MemoryPointer
4
+ extend FFI::DataConverter
5
+
6
+ def self.native_type
7
+ FFI::Type::POINTER
8
+ end
9
+
10
+ def initialize
11
+ super(:uint8, U_MAX_VERSION_LENGTH)
12
+ end
13
+
14
+ def to_a
15
+ read_array_of_uint8(U_MAX_VERSION_LENGTH)
16
+ end
17
+
18
+ def to_s
19
+ FFI::MemoryPointer.new(:char, U_MAX_VERSION_STRING_LENGTH) do |buffer|
20
+ Library.u_versionToString(self, buffer)
21
+ return buffer.read_string_to_null
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,5 @@
1
+ module ICU
2
+ class Calendar
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: icu-calendar
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Chris Bandy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: ffi
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email: bandy.chris@gmail.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - LICENSE
48
+ - README.md
49
+ - lib/icu/calendar.rb
50
+ - lib/icu/calendar/library.rb
51
+ - lib/icu/calendar/version.rb
52
+ - lib/icu/calendar/library/constants.rb
53
+ - lib/icu/calendar/library/version_info.rb
54
+ - lib/icu/calendar/library/error_code.rb
55
+ homepage: https://github.com/cbandy/icu-calendar
56
+ licenses:
57
+ - Apache License Version 2.0
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '>='
66
+ - !ruby/object:Gem::Version
67
+ version: 1.9.3
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements:
74
+ - ICU 4.2 or greater, http://www.icu-project.org/
75
+ rubyforge_project:
76
+ rubygems_version: 2.0.14
77
+ signing_key:
78
+ specification_version: 4
79
+ summary: Date arithmetic and calendar data from ICU
80
+ test_files: []