icu 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,82 @@
1
+ #include "icu.h"
2
+
3
+ VALUE cCountry;
4
+
5
+ /******************* ICU::Locale::Country */
6
+
7
+ /**
8
+ * call-seq:
9
+ * ICU::Locale.get => locale
10
+ */
11
+ VALUE rb_Country_class_get(VALUE self, VALUE code)
12
+ {
13
+ VALUE countries, country;
14
+
15
+ code = StringValue(code);
16
+ countries = rb_cv_get(self, "@@countries");
17
+ country = rb_hash_aref(countries, code);
18
+ if (country == Qnil) {
19
+ VALUE args[1];
20
+
21
+ args[0] = code;
22
+ country = rb_class_new_instance(1, args, self);
23
+ rb_hash_aset(countries, code, country);
24
+ return country;
25
+ } else {
26
+ return country;
27
+ }
28
+ }
29
+
30
+ VALUE rb_Country_initialize(VALUE self, VALUE code)
31
+ {
32
+ code = StringValue(code);
33
+ CheckCountryCode(RSTRING(code)->ptr);
34
+ rb_iv_set(self, "@code", code);
35
+
36
+ return self;
37
+ }
38
+
39
+ VALUE rb_Country_name(int argc, VALUE *argv, VALUE self)
40
+ {
41
+ char fakeLocale[4] = "_";
42
+ VALUE code = rb_iv_get(self, "@code");
43
+
44
+ VALUE rb_locale;
45
+ char * locale = NULL;
46
+
47
+ UChar * country = ALLOC_N(UChar, 32);
48
+ int32_t countryLen = 32;
49
+ UErrorCode status = U_ZERO_ERROR;
50
+
51
+ strcat(fakeLocale, RSTRING(code)->ptr);
52
+
53
+ rb_scan_args(argc, argv, "01", &rb_locale);
54
+ if (rb_locale != Qnil) {
55
+ locale = StringValuePtr(rb_locale);
56
+ }
57
+
58
+ countryLen = uloc_getDisplayCountry(fakeLocale, locale, country, countryLen, &status);
59
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
60
+ status = U_ZERO_ERROR;
61
+ REALLOC_N(country, UChar, countryLen);
62
+ uloc_getDisplayCountry(fakeLocale, locale, country, countryLen, &status);
63
+ }
64
+ RAISE_ON_ERROR(status);
65
+
66
+ return u_strToRString(country, countryLen);
67
+ }
68
+
69
+ void Init_ICU_Locale_Country()
70
+ {
71
+ extern VALUE cLocale;
72
+
73
+ cCountry = rb_define_class_under(cLocale, "Country", rb_cObject);
74
+ rb_funcall(cCountry, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
75
+ rb_cv_set(cCountry, "@@countries", rb_hash_new());
76
+ rb_define_singleton_method(cCountry, "get", rb_Country_class_get, 1);
77
+ rb_define_private_method(cCountry, "initialize", rb_Country_initialize, 1);
78
+ rb_define_attr(cCountry, "code", 1, 0);
79
+ rb_define_alias(cCountry, "to_str", "code");
80
+ rb_define_alias(cCountry, "to_s", "code");
81
+ rb_define_method(cCountry, "name", rb_Country_name, -1);
82
+ }
@@ -0,0 +1,82 @@
1
+ #include "icu.h"
2
+
3
+ VALUE cLanguage;
4
+
5
+ /******************* ICU::Locale::Language */
6
+
7
+ /**
8
+ * call-seq:
9
+ * ICU::Locale.get => locale
10
+ */
11
+ VALUE rb_Language_class_get(VALUE self, VALUE code)
12
+ {
13
+ VALUE languages, language;
14
+
15
+ code = StringValue(code);
16
+ languages = rb_cv_get(self, "@@languages");
17
+ language = rb_hash_aref(languages, code);
18
+ if (language == Qnil) {
19
+ VALUE args[1];
20
+
21
+ args[0] = code;
22
+ language = rb_class_new_instance(1, args, self);
23
+ rb_hash_aset(languages, code, language);
24
+ return language;
25
+ } else {
26
+ return language;
27
+ }
28
+ }
29
+
30
+ VALUE rb_Language_initialize(VALUE self, VALUE code)
31
+ {
32
+ code = StringValue(code);
33
+ CheckLanguageCode(RSTRING(code)->ptr);
34
+ rb_iv_set(self, "@code", code);
35
+
36
+ return self;
37
+ }
38
+
39
+ VALUE rb_Language_name(int argc, VALUE *argv, VALUE self)
40
+ {
41
+ char *fakeLocale;
42
+ VALUE code = rb_iv_get(self, "@code");
43
+
44
+ VALUE rb_locale;
45
+ char *locale = NULL;
46
+
47
+ UChar *language = ALLOC_N(UChar, 32);
48
+ int32_t languageLen = 32;
49
+ UErrorCode status = U_ZERO_ERROR;
50
+
51
+ fakeLocale = RSTRING(code)->ptr;
52
+
53
+ rb_scan_args(argc, argv, "01", &rb_locale);
54
+ if (rb_locale != Qnil) {
55
+ locale = StringValuePtr(rb_locale);
56
+ }
57
+
58
+ languageLen = uloc_getDisplayLanguage(fakeLocale, locale, language, languageLen, &status);
59
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
60
+ status = U_ZERO_ERROR;
61
+ REALLOC_N(language, UChar, languageLen);
62
+ uloc_getDisplayLanguage(fakeLocale, locale, language, languageLen, &status);
63
+ }
64
+ RAISE_ON_ERROR(status);
65
+
66
+ return u_strToRString(language, languageLen);
67
+ }
68
+
69
+ void Init_ICU_Locale_Language()
70
+ {
71
+ extern VALUE cLocale;
72
+
73
+ cLanguage = rb_define_class_under(cLocale, "Language", rb_cObject);
74
+ rb_funcall(cLanguage, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
75
+ rb_cv_set(cLanguage, "@@languages", rb_hash_new());
76
+ rb_define_singleton_method(cLanguage, "get", rb_Language_class_get, 1);
77
+ rb_define_private_method(cLanguage, "initialize", rb_Language_initialize, 1);
78
+ rb_define_attr(cLanguage, "code", 1, 0);
79
+ rb_define_alias(cLanguage, "to_str", "code");
80
+ rb_define_alias(cLanguage, "to_s", "code");
81
+ rb_define_method(cLanguage, "name", rb_Language_name, -1);
82
+ }
@@ -0,0 +1,175 @@
1
+ #include "icu.h"
2
+
3
+ #include "unicode/unum.h"
4
+
5
+ //UNumberFormatRoundingMode parseRoundingModeOption(VALUE rb_options)
6
+ //{
7
+ // VALUE rounding_mode;
8
+ //
9
+ // rounding_mode = rb_hash_aref(rb_options, ID2SYM(rb_intern("round_mode")));
10
+ // if (rounding_mode != Qnil) {
11
+ // ID rounding_mode_ID;
12
+ //
13
+ // Check_Type(rounding_mode, T_SYMBOL);
14
+ // rounding_mode_ID = SYM2ID(rounding_mode);
15
+ // if (rounding_mode_ID == rb_intern("ceil")) {
16
+ // return UNUM_ROUND_CEILING;
17
+ // } else if (rounding_mode_ID == rb_intern("floor")) {
18
+ // return UNUM_ROUND_FLOOR;
19
+ // } else if (rounding_mode_ID == rb_intern("down")) {
20
+ // return UNUM_ROUND_DOWN;
21
+ // } else if (rounding_mode_ID == rb_intern("up")) {
22
+ // return UNUM_ROUND_UP;
23
+ // } else if (rounding_mode_ID == rb_intern("halfeven")) {
24
+ // return UNUM_FOUND_HALFEVEN;
25
+ // } else if (rounding_mode_ID == rb_intern("halfdown")) {
26
+ // return UNUM_ROUND_HALFDOWN;
27
+ // } else if (rounding_mode_ID == rb_intern("halfup")) {
28
+ // return UNUM_ROUND_HALFUP;
29
+ // } else {
30
+ // rb_raise(rb_eArgError, "unsupported rounding mode '%s'", rb_id2name(rounding_mode_ID));
31
+ // }
32
+ // }
33
+ // return -1;
34
+ //}
35
+
36
+ /******************* Numeric */
37
+
38
+ /**
39
+ * call-seq:
40
+ * 23874.localize(:decimal, 'es_ES') => 23.874
41
+ */
42
+ VALUE rb_numeric_localize(int argc, VALUE *argv, VALUE self)
43
+ {
44
+ VALUE style, options;
45
+ UNumberFormatStyle formatStyle;
46
+ char *locale = NULL;
47
+
48
+ UNumberFormat *format;
49
+ UErrorCode status;
50
+
51
+ UChar result[256];
52
+ /* arguments */
53
+ rb_scan_args(argc, argv, "02", &style, &options);
54
+ if (style == Qnil) {
55
+ formatStyle = UNUM_DECIMAL;
56
+ } else {
57
+ ID style_ID;
58
+
59
+ Check_Type(style, T_SYMBOL);
60
+ style_ID = SYM2ID(style);
61
+ if (style_ID == rb_intern("decimal")) {
62
+ formatStyle = UNUM_DECIMAL;
63
+ } else if (style_ID == rb_intern("currency")) {
64
+ formatStyle = UNUM_CURRENCY;
65
+ } else if (style_ID == rb_intern("percent")) {
66
+ formatStyle = UNUM_PERCENT;
67
+ } else if (style_ID == rb_intern("scientific")) {
68
+ formatStyle = UNUM_SCIENTIFIC;
69
+ } else if (style_ID == rb_intern("spellout")) {
70
+ formatStyle = UNUM_SPELLOUT;
71
+ } else {
72
+ rb_raise(rb_eArgError, "unsupported format style %s", rb_id2name(style_ID));
73
+ }
74
+ }
75
+ if (options != Qnil) {
76
+ VALUE rb_locale;
77
+
78
+ Check_Type(options, T_HASH);
79
+ rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
80
+ if (rb_locale != Qnil) {
81
+ locale = StringValuePtr(rb_locale);
82
+ }
83
+ }
84
+ /* formatter */
85
+ status = U_ZERO_ERROR;
86
+ format = unum_open(formatStyle, NULL, 0, locale, NULL, &status);
87
+ RAISE_ON_ERROR(status);
88
+ /* set format attributes */
89
+ if (options != Qnil) {
90
+ VALUE currency, precision, round_mode, round_increment;
91
+
92
+ switch (formatStyle) {
93
+ case UNUM_CURRENCY:
94
+ currency = rb_hash_aref(options, ID2SYM(rb_intern("currency")));
95
+ if (currency != Qnil) {
96
+ UChar *uStr;
97
+ int32_t uStrLen;
98
+
99
+ uStr = u_strFromRString(currency, &uStrLen);
100
+ status = U_ZERO_ERROR;
101
+ unum_setTextAttribute(format, UNUM_CURRENCY_CODE, uStr, uStrLen, &status);
102
+ RAISE_ON_ERROR(status);
103
+ }
104
+ case UNUM_DECIMAL:
105
+ /* precision */
106
+ precision = rb_hash_aref(options, ID2SYM(rb_intern("precision")));
107
+ if (precision != Qnil) {
108
+ Check_Type(precision, T_FIXNUM);
109
+ status = U_ZERO_ERROR;
110
+ unum_setAttribute(format, UNUM_FRACTION_DIGITS, NUM2INT(precision));
111
+ RAISE_ON_ERROR(status);
112
+ }
113
+
114
+ round_mode = rb_hash_aref(options, ID2SYM(rb_intern("round_mode")));
115
+ if (round_mode != Qnil) {
116
+ ID round_mode_ID;
117
+ UNumberFormatRoundingMode rounding_mode;
118
+
119
+ Check_Type(round_mode, T_SYMBOL);
120
+ round_mode_ID = SYM2ID(round_mode);
121
+ if (round_mode_ID == rb_intern("ceil")) {
122
+ rounding_mode = UNUM_ROUND_CEILING;
123
+ } else if (round_mode_ID == rb_intern("floor")) {
124
+ rounding_mode = UNUM_ROUND_FLOOR;
125
+ } else if (round_mode_ID == rb_intern("down")) {
126
+ rounding_mode = UNUM_ROUND_DOWN;
127
+ } else if (round_mode_ID == rb_intern("up")) {
128
+ rounding_mode = UNUM_ROUND_UP;
129
+ } else if (round_mode_ID == rb_intern("halfeven")) {
130
+ rounding_mode = UNUM_FOUND_HALFEVEN;
131
+ } else if (round_mode_ID == rb_intern("halfdown")) {
132
+ rounding_mode = UNUM_ROUND_HALFDOWN;
133
+ } else if (round_mode_ID == rb_intern("halfup")) {
134
+ rounding_mode = UNUM_ROUND_HALFUP;
135
+ } else {
136
+ rb_raise(rb_eArgError, "unsupported rounding mode '%s'", rb_id2name(round_mode_ID));
137
+ }
138
+ status = U_ZERO_ERROR;
139
+ unum_setAttribute(format, UNUM_ROUNDING_MODE, rounding_mode);
140
+ RAISE_ON_ERROR(status);
141
+ }
142
+ round_increment = rb_hash_aref(options, ID2SYM(rb_intern("round_increment")));
143
+ if (round_increment != Qnil) {
144
+ Check_Type(round_increment, T_FLOAT);
145
+ status = U_ZERO_ERROR;
146
+ unum_setDoubleAttribute(format, UNUM_ROUNDING_INCREMENT, NUM2DBL(round_increment));
147
+ RAISE_ON_ERROR(status);
148
+ }
149
+ }
150
+ }
151
+ /* format */
152
+ status = U_ZERO_ERROR;
153
+ switch (TYPE(self)) {
154
+ case T_FIXNUM:
155
+ unum_format(format, NUM2INT(self), result, 256, NULL, &status);
156
+ break;
157
+ case T_FLOAT:
158
+ unum_formatDouble(format, NUM2DBL(self), result, 256, NULL, &status);
159
+ break;
160
+ case T_BIGNUM:
161
+ unum_formatInt64(format, rb_big2ll(self), result, 256, NULL, &status);
162
+ break;
163
+
164
+ }
165
+ RAISE_ON_ERROR(status);
166
+ /* free resources */
167
+ unum_close(format);
168
+
169
+ return u_strToRString(result, -1);
170
+ }
171
+
172
+ void Init_ICU_Numeric(void)
173
+ {
174
+ rb_define_method(rb_cNumeric, "localize", rb_numeric_localize, -1);
175
+ }
@@ -0,0 +1,374 @@
1
+ #include "icu.h"
2
+
3
+ #include "unicode/ucal.h"
4
+ #include "unicode/udat.h"
5
+
6
+ /******************* Time */
7
+
8
+ /**
9
+ * call-seq:
10
+ * 23874.localize(:date => :short) => 23.874
11
+ */
12
+ VALUE rb_Time_localize(int argc, VALUE *argv, VALUE self)
13
+ {
14
+ VALUE options;
15
+ UDateFormatStyle dateStyle = UDAT_DEFAULT, timeStyle = UDAT_DEFAULT;
16
+ char *locale = NULL;
17
+ const UChar *timeZone = 0;
18
+ int32_t timeZoneLen = -1;
19
+
20
+ UDateFormat *format;
21
+ UErrorCode status;
22
+ UChar result[256];
23
+ /* arguments */
24
+ rb_scan_args(argc, argv, "01", &options);
25
+ if (options != Qnil) {
26
+ VALUE rb_locale, rb_timeZone;
27
+
28
+ Check_Type(options, T_HASH);
29
+ /* date and time style */
30
+ dateStyle = getStyle(options, "date");
31
+ timeStyle = getStyle(options, "time");
32
+ /* locale */
33
+ rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
34
+ if (rb_locale != Qnil) {
35
+ locale = StringValuePtr(rb_locale);
36
+ }
37
+ /* time zone */
38
+ rb_timeZone = rb_hash_aref(options, ID2SYM(rb_intern("zone")));
39
+ if (rb_timeZone != Qnil) {
40
+ Check_Type(rb_timeZone, T_STRING);
41
+ timeZone = u_strFromRString(rb_timeZone, &timeZoneLen);
42
+ }
43
+ }
44
+
45
+ /* formatter */
46
+ status = U_ZERO_ERROR;
47
+ format = udat_open(timeStyle, dateStyle, locale, timeZone, timeZoneLen, NULL, -1, &status);
48
+ RAISE_ON_ERROR(status);
49
+ /* format */
50
+ status = U_ZERO_ERROR;
51
+ {
52
+ extern struct timeval rb_time_timeval(VALUE time);
53
+ struct timeval tv;
54
+ UDate dateToFormat;
55
+ UChar result[256];
56
+
57
+ tv = rb_time_timeval(self);
58
+ dateToFormat = ((double)tv.tv_sec + (double)tv.tv_usec / 1e6) * 1e3;
59
+ udat_format(format, dateToFormat, result, 256, NULL, &status);
60
+ RAISE_ON_ERROR(status);
61
+ /* free resources */
62
+ unum_close(format);
63
+
64
+ return u_strToRString(result, -1);
65
+ }
66
+ }
67
+
68
+ UDateFormatStyle getStyle(VALUE options, const char * key)
69
+ {
70
+ UDateFormatStyle formatStyle = UDAT_DEFAULT;
71
+ VALUE style;
72
+
73
+ style = rb_hash_aref(options, ID2SYM(rb_intern(key)));
74
+ if (style != Qnil) {
75
+ if (style == Qfalse) {
76
+ formatStyle = UDAT_NONE;
77
+ } else {
78
+ ID style_ID;
79
+
80
+ Check_Type(style, T_SYMBOL);
81
+ style_ID = SYM2ID(style);
82
+ if (style_ID == rb_intern("full")) {
83
+ formatStyle = UDAT_FULL;
84
+ } else if (style_ID == rb_intern("long")) {
85
+ formatStyle = UDAT_LONG;
86
+ } else if (style_ID == rb_intern("medium")) {
87
+ formatStyle = UDAT_MEDIUM;
88
+ } else if (style_ID == rb_intern("short")) {
89
+ formatStyle = UDAT_SHORT;
90
+ } else {
91
+ rb_raise(rb_eArgError, "unsupported format style %s", rb_id2name(style_ID));
92
+ }
93
+ }
94
+ }
95
+
96
+ return formatStyle;
97
+ }
98
+
99
+ VALUE enumToOptions(UEnumeration *enumeration, VALUE options, UCalendar *calendar, UCalendarDisplayNameType type, char *locale)
100
+ {
101
+ const UChar *zoneID;
102
+ int32_t zoneIDLen;
103
+ UErrorCode status = U_ZERO_ERROR;
104
+
105
+ while (zoneID = uenum_unext(enumeration, &zoneIDLen, &status)) {
106
+ RAISE_ON_ERROR(status);
107
+ if (type == -1) {
108
+ rb_ary_push(options, u_strToRString(zoneID, zoneIDLen));
109
+ } else {
110
+ VALUE option = rb_ary_new2(2);
111
+ UChar *zoneName = ALLOC_N(UChar, 64);
112
+ int32_t zoneNameLen = 64;
113
+
114
+ ucal_setTimeZone(calendar, zoneID, zoneIDLen, &status);
115
+ RAISE_ON_ERROR(status);
116
+ zoneNameLen = ucal_getTimeZoneDisplayName(calendar, UCAL_STANDARD, locale, zoneName, zoneNameLen, &status);
117
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
118
+ status = U_ZERO_ERROR;
119
+ REALLOC_N(zoneName, UChar, zoneNameLen);
120
+ ucal_getTimeZoneDisplayName(calendar, UCAL_STANDARD, locale, zoneName, zoneNameLen, &status);
121
+ }
122
+ RAISE_ON_ERROR(status);
123
+ rb_ary_push(option, u_strToRString(zoneName, zoneNameLen));
124
+ rb_ary_push(option, u_strToRString(zoneID, zoneIDLen));
125
+ rb_ary_push(options, option);
126
+ }
127
+ }
128
+
129
+ return options;
130
+ }
131
+
132
+ /**
133
+ * call-seq:
134
+ * Time.zones(:countries => ['US'], :locale => 'es_ES', :type => :short) => 23.874
135
+ * Time.zones(:countries => :all, :group => true) => 23.874
136
+ */
137
+ VALUE rb_Time_singleton_zones(int argc, VALUE *argv, VALUE self)
138
+ {
139
+ VALUE options, countries = Qfalse, group = Qfalse;
140
+ char *locale = NULL;
141
+ UCalendarDisplayNameType type = -1;
142
+
143
+ UCalendar *calendar;
144
+ UErrorCode status = U_ZERO_ERROR;
145
+ UEnumeration *enumeration;
146
+ VALUE select = rb_ary_new();
147
+ UCollator *collator;
148
+
149
+ //arguments
150
+ rb_scan_args(argc, argv, "01", &options);
151
+ if (options != Qnil) {
152
+ VALUE rb_locale, rb_type;
153
+
154
+ Check_Type(options, T_HASH);
155
+ //locale
156
+ rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
157
+ if (rb_locale != Qnil) {
158
+ locale = StringValuePtr(rb_locale);
159
+ }
160
+ //countries
161
+ countries = rb_hash_aref(options, ID2SYM(rb_intern("countries")));
162
+ if (countries == Qnil) {
163
+ countries = Qfalse;
164
+ } else {
165
+
166
+ }
167
+ //group
168
+ group = rb_hash_aref(options, ID2SYM(rb_intern("group")));
169
+ group = group && group != Qnil ? Qtrue : Qfalse;
170
+ //type
171
+ rb_type = rb_hash_aref(options, ID2SYM(rb_intern("type")));
172
+ if (rb_type != Qnil) {
173
+ ID rb_type_ID;
174
+
175
+ Check_Type(rb_type, T_SYMBOL);
176
+ rb_type_ID = SYM2ID(rb_type);
177
+ if (rb_type_ID == rb_intern("standard")) {
178
+ type = UCAL_STANDARD;
179
+ } else if (rb_type_ID == rb_intern("short_standard")) {
180
+ type = UCAL_SHORT_STANDARD;
181
+ } else if (rb_type_ID == rb_intern("dst")) {
182
+ type = UCAL_DST;
183
+ } else if (rb_type_ID == rb_intern("short_dst")) {
184
+ type = UCAL_SHORT_DST;
185
+ } else {
186
+ rb_raise(rb_eArgError, "unsupported time zone type %s", rb_id2name(rb_type_ID));
187
+ }
188
+ }
189
+ }
190
+ //calendar
191
+ calendar = ucal_open(NULL, -1, locale, UCAL_GREGORIAN, &status);
192
+ RAISE_ON_ERROR(status);
193
+
194
+ collator = ucol_open(locale, &status);
195
+ RAISE_ON_ERROR(status);
196
+
197
+ if (countries) {
198
+ const char* const* isoCountries = uloc_getISOCountries();
199
+
200
+ while (*isoCountries != NULL) {
201
+ if (TYPE(countries) == T_SYMBOL || (TYPE(countries) == T_ARRAY && rb_ary_includes(countries, rb_str_new2(*isoCountries)))) {
202
+ if (group) {
203
+ char fakeLocale[4] = "_";
204
+ UChar *country = ALLOC_N(UChar, 32);
205
+ int32_t countryLen = 32;
206
+ VALUE optgroup = rb_ary_new2(2);
207
+
208
+ strcat(fakeLocale, *isoCountries);
209
+ countryLen = uloc_getDisplayCountry(fakeLocale, locale, country, countryLen, &status);
210
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
211
+ status = U_ZERO_ERROR;
212
+ REALLOC_N(country, UChar, countryLen);
213
+ uloc_getDisplayCountry(fakeLocale, locale, country, countryLen, &status);
214
+ }
215
+ rb_ary_push(optgroup, u_strToRString(country, countryLen));
216
+ enumeration = ucal_openCountryTimeZones(*isoCountries, &status);
217
+ RAISE_ON_ERROR(status);
218
+ rb_ary_push(optgroup, enumToOptions(enumeration, rb_ary_new(), calendar, type, locale));
219
+ uenum_close(enumeration);
220
+ if (RARRAY(RARRAY(optgroup)->ptr[1])->len) {
221
+ ruby_qsort(RARRAY(RARRAY(optgroup)->ptr[1])->ptr, RARRAY(RARRAY(optgroup)->ptr[1])->len, sizeof(VALUE), collateByDisplayName, collator);
222
+ rb_ary_push(select, optgroup);
223
+ }
224
+ } else {
225
+ enumeration = ucal_openCountryTimeZones(*isoCountries, &status);
226
+ RAISE_ON_ERROR(status);
227
+ enumToOptions(enumeration, select, calendar, type, locale);
228
+ uenum_close(enumeration);
229
+ }
230
+ }
231
+ *isoCountries++;
232
+ }
233
+ } else {
234
+ enumeration = ucal_openTimeZones(&status);
235
+ RAISE_ON_ERROR(status);
236
+ enumToOptions(enumeration, select, calendar, type, locale);
237
+ uenum_close(enumeration);
238
+ }
239
+ //sort
240
+ ruby_qsort(RARRAY(select)->ptr, RARRAY(select)->len, sizeof(VALUE), collateByDisplayName, collator);
241
+ //free
242
+ ucal_close(calendar);
243
+ ucol_close(collator);
244
+
245
+ return select;
246
+ }
247
+
248
+ /**
249
+ * call-seq:
250
+ * Time.default_zone = 'GMT'
251
+ */
252
+ VALUE rb_Time_singleton_set_default_zone(VALUE self, VALUE zone)
253
+ {
254
+ UErrorCode status = U_ZERO_ERROR;
255
+
256
+ ucal_setDefaultTimeZone((const UChar *)u_strFromRString(zone, NULL), &status);
257
+ RAISE_ON_ERROR(status);
258
+
259
+ return zone;
260
+ }
261
+
262
+ /**
263
+ * call-seq:
264
+ * Time.default_zone -> 'GMT'
265
+ */
266
+ VALUE rb_Time_singleton_get_default_zone(VALUE self)
267
+ {
268
+ UChar * timeZone = ALLOC_N(UChar, 64);
269
+ int32_t timeZoneLen;
270
+ UErrorCode status = U_ZERO_ERROR;
271
+
272
+ timeZoneLen = ucal_getDefaultTimeZone(timeZone, 2, &status);
273
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
274
+ status = U_ZERO_ERROR;
275
+ REALLOC_N(timeZone, UChar, timeZoneLen);
276
+ ucal_getDefaultTimeZone(timeZone, timeZoneLen, &status);
277
+ }
278
+ RAISE_ON_ERROR(status);
279
+
280
+ return u_strToRString(timeZone, timeZoneLen);
281
+ }
282
+
283
+ /**
284
+ * call-seq:
285
+ * 23874.localize(:date => :short) => 23.874
286
+ */
287
+ VALUE rb_Time_singleton_pattern(int argc, VALUE *argv, VALUE self)
288
+ {
289
+ VALUE options;
290
+ UDateFormatStyle dateStyle = UDAT_DEFAULT, timeStyle = UDAT_DEFAULT;
291
+ char *locale = NULL;
292
+
293
+ UDateFormat *format;
294
+ UErrorCode status = U_ZERO_ERROR;
295
+
296
+ UChar * pattern = ALLOC_N(UChar, 64);
297
+ int32_t patternLen;
298
+
299
+ /* arguments */
300
+ rb_scan_args(argc, argv, "01", &options);
301
+ if (options != Qnil) {
302
+ VALUE rb_locale;
303
+
304
+ Check_Type(options, T_HASH);
305
+ /* date and time style */
306
+ dateStyle = getStyle(options, "date");
307
+ timeStyle = getStyle(options, "time");
308
+ /* locale */
309
+ rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
310
+ if (rb_locale != Qnil) {
311
+ locale = StringValuePtr(rb_locale);
312
+ }
313
+ }
314
+ /* formatter */
315
+ status = U_ZERO_ERROR;
316
+ format = udat_open(timeStyle, dateStyle, locale, NULL, 0, NULL, 0, &status);
317
+ RAISE_ON_ERROR(status);
318
+ /* pattern */
319
+ patternLen = udat_toPattern(format, 0, pattern, 64, &status);
320
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
321
+ status = U_ZERO_ERROR;
322
+ REALLOC_N(pattern, UChar, patternLen);
323
+ udat_toPattern(format, 0, pattern, 64, &status);
324
+ }
325
+ RAISE_ON_ERROR(status);
326
+ /* free */
327
+ udat_close(format);
328
+
329
+ return u_strToRString(pattern, patternLen);
330
+ }
331
+
332
+ /**
333
+ * call-seq:
334
+ * 23874.localize(:date => :short) => 23.874
335
+ */
336
+ VALUE rb_Time_singleton_week_start(int argc, VALUE *argv, VALUE self)
337
+ {
338
+ VALUE options;
339
+ char * locale = NULL;
340
+ UErrorCode status = U_ZERO_ERROR;
341
+ UCalendar * calendar;
342
+ int32_t result;
343
+
344
+ /* arguments */
345
+ rb_scan_args(argc, argv, "01", &options);
346
+ if (options != Qnil) {
347
+ VALUE rb_locale;
348
+
349
+ Check_Type(options, T_HASH);
350
+ /* locale */
351
+ rb_locale = rb_hash_aref(options, ID2SYM(rb_intern("locale")));
352
+ if (rb_locale != Qnil) {
353
+ locale = StringValuePtr(rb_locale);
354
+ }
355
+ }
356
+ /* calendar */
357
+ calendar = ucal_open(NULL, 0, locale, UCAL_GREGORIAN, &status);
358
+ RAISE_ON_ERROR(status);
359
+ /* attribute */
360
+ result = ucal_getAttribute(calendar, UCAL_FIRST_DAY_OF_WEEK);
361
+ ucal_close(calendar);
362
+
363
+ return INT2NUM(result);
364
+ }
365
+
366
+ void Init_ICU_Time(void)
367
+ {
368
+ rb_define_method(rb_cTime, "localize", rb_Time_localize, -1);
369
+ rb_define_singleton_method(rb_cTime, "zones", rb_Time_singleton_zones, -1);
370
+ rb_define_singleton_method(rb_cTime, "default_zone=", rb_Time_singleton_set_default_zone, 1);
371
+ rb_define_singleton_method(rb_cTime, "default_zone", rb_Time_singleton_get_default_zone, 0);
372
+ rb_define_singleton_method(rb_cTime, "pattern", rb_Time_singleton_pattern, -1);
373
+ rb_define_singleton_method(rb_cTime, "week_start", rb_Time_singleton_week_start, -1);
374
+ }