icu-calendar 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []