icu4r 0.1.3.2006.01.26
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README +153 -0
- data/calendar.c +576 -0
- data/docs/FORMATTING +131 -0
- data/docs/UNICODE_REGEXPS +204 -0
- data/extconf.rb +15 -0
- data/fmt.cpp +150 -0
- data/icu4r.c +14 -0
- data/icu_common.h +45 -0
- data/samples/demo_each.rb +23 -0
- data/samples/demo_locales.rb +16 -0
- data/samples/demo_regexp.rb +11 -0
- data/samples/resbundle/appmsg/root.res +0 -0
- data/samples/resbundle/appmsg/ru.res +0 -0
- data/samples/resbundle/demo_bundle.rb +4 -0
- data/samples/resbundle/mkres.sh +4 -0
- data/samples/resbundle/root.txt +10 -0
- data/samples/resbundle/ru.txt +4 -0
- data/test/test_calendar.rb +109 -0
- data/test/test_ustring.rb +381 -0
- data/tools/doc.sh +2 -0
- data/tools/km.rb +425 -0
- data/ubundle.c +209 -0
- data/ucore_ext.c +168 -0
- data/uregex.c +673 -0
- data/uregex.h +27 -0
- data/ustring.c +3042 -0
- metadata +81 -0
data/calendar.c
ADDED
@@ -0,0 +1,576 @@
|
|
1
|
+
#include <unicode/ucal.h>
|
2
|
+
#include <unicode/uenum.h>
|
3
|
+
#include <unicode/udat.h>
|
4
|
+
#include "icu_common.h"
|
5
|
+
extern VALUE rb_cUString;
|
6
|
+
extern VALUE icu_ustr_new(UChar * ptr, long len);
|
7
|
+
extern VALUE icu_ustr_new_set(UChar * ptr, long len, long capa);
|
8
|
+
static VALUE s_calendar_fields;
|
9
|
+
extern VALUE rb_cUCalendar;
|
10
|
+
#define UCALENDAR(obj) ((UCalendar *)DATA_PTR(obj))
|
11
|
+
/**
|
12
|
+
* Document-class: UCalendar
|
13
|
+
*
|
14
|
+
* The UCalendar class provides methods for converting between a specific instant in
|
15
|
+
* time and a set of calendar fields such as YEAR, MONTH, DAY_OF_MONTH, HOUR, and so on,
|
16
|
+
* and for manipulating the calendar fields, such as getting the date of the next week.
|
17
|
+
* An instant in time can be represented by a millisecond value that is an offset from the
|
18
|
+
* Epoch, January 1, 1970 00:00:00.000 GMT (Gregorian).
|
19
|
+
*
|
20
|
+
* Also timezone info and methods are provided.
|
21
|
+
*
|
22
|
+
* NOTE: months are zero-based.
|
23
|
+
*/
|
24
|
+
|
25
|
+
/**
|
26
|
+
* call-seq:
|
27
|
+
* UCalendar.time_zones
|
28
|
+
*
|
29
|
+
* Returns array with all time zones (as UString values).
|
30
|
+
*/
|
31
|
+
VALUE icu4r_cal_all_tz (VALUE obj)
|
32
|
+
{
|
33
|
+
UErrorCode status = U_ZERO_ERROR;
|
34
|
+
UEnumeration * zones ;
|
35
|
+
VALUE ret ;
|
36
|
+
UChar * name;
|
37
|
+
int32_t len;
|
38
|
+
zones = ucal_openTimeZones (&status);
|
39
|
+
ICU_RAISE(status);
|
40
|
+
ret = rb_ary_new();
|
41
|
+
while( (name = (UChar*)uenum_unext(zones, &len, &status))) {
|
42
|
+
rb_ary_push(ret, icu_ustr_new(name, len));
|
43
|
+
}
|
44
|
+
uenum_close(zones);
|
45
|
+
return ret;
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
/**
|
50
|
+
* call-seq:
|
51
|
+
* UCalendar.tz_for_country(country)
|
52
|
+
*
|
53
|
+
* Returns array with all time zones associated with the given country.
|
54
|
+
* Note: <code>country</code> must be value of type String.
|
55
|
+
* Returned array content is UString's
|
56
|
+
*
|
57
|
+
* UCalendar.tz_for_country("GB") # => [ "Europe/Belfast", "Europe/London", "GB", "GB-Eire"]
|
58
|
+
*
|
59
|
+
*/
|
60
|
+
VALUE icu4r_cal_country_tz (VALUE obj, VALUE ctry)
|
61
|
+
{
|
62
|
+
UErrorCode status = U_ZERO_ERROR;
|
63
|
+
UEnumeration * zones ;
|
64
|
+
VALUE ret ;
|
65
|
+
UChar * name;
|
66
|
+
int32_t len;
|
67
|
+
Check_Type(ctry, T_STRING);
|
68
|
+
zones = ucal_openCountryTimeZones (RSTRING(ctry)->ptr, &status) ;
|
69
|
+
ICU_RAISE(status);
|
70
|
+
ret = rb_ary_new();
|
71
|
+
while( (name = (UChar*)uenum_unext(zones, &len, &status))) {
|
72
|
+
rb_ary_push(ret, icu_ustr_new(name, len));
|
73
|
+
}
|
74
|
+
uenum_close(zones);
|
75
|
+
return ret;
|
76
|
+
}
|
77
|
+
|
78
|
+
/**
|
79
|
+
* call-seq:
|
80
|
+
* UCalendar.default_tz => ustring
|
81
|
+
*
|
82
|
+
* Returns the default time zone (UString).
|
83
|
+
*
|
84
|
+
* UCalendar.default_tz # "EET"
|
85
|
+
*
|
86
|
+
*/
|
87
|
+
VALUE icu4r_cal_get_default_tz(VALUE obj)
|
88
|
+
{
|
89
|
+
UErrorCode status = U_ZERO_ERROR;
|
90
|
+
UChar * buf ;
|
91
|
+
long capa = 0;
|
92
|
+
capa = ucal_getDefaultTimeZone (buf, capa, &status);
|
93
|
+
if( U_BUFFER_OVERFLOW_ERROR == status) {
|
94
|
+
buf = ALLOC_N(UChar, capa+1);
|
95
|
+
status = U_ZERO_ERROR;
|
96
|
+
capa = ucal_getDefaultTimeZone (buf, capa, &status);
|
97
|
+
return icu_ustr_new_set(buf, capa, capa+1);
|
98
|
+
}
|
99
|
+
ICU_RAISE(status);
|
100
|
+
return Qnil;
|
101
|
+
}
|
102
|
+
|
103
|
+
/**
|
104
|
+
* call-seq:
|
105
|
+
* UCalendar.default_tz = ustring
|
106
|
+
*
|
107
|
+
* Set the default time zone.
|
108
|
+
*
|
109
|
+
* UCalendar.default_tz="GMT+00".u
|
110
|
+
* UCalendar.default_tz="Europe/Paris".u
|
111
|
+
*/
|
112
|
+
VALUE icu4r_cal_set_default_tz(VALUE obj, VALUE tz)
|
113
|
+
{
|
114
|
+
UErrorCode status = U_ZERO_ERROR;
|
115
|
+
Check_Class(tz, rb_cUString);
|
116
|
+
ucal_setDefaultTimeZone (ICU_PTR(tz), &status);
|
117
|
+
ICU_RAISE(status);
|
118
|
+
return tz;
|
119
|
+
}
|
120
|
+
/**
|
121
|
+
* call-seq:
|
122
|
+
* UCalendar.dst_savings(zone_id)
|
123
|
+
*
|
124
|
+
* Return the amount of time in milliseconds that the clock is advanced
|
125
|
+
* during daylight savings time for the given time zone, or zero if the time
|
126
|
+
* zone does not observe daylight savings time.
|
127
|
+
*
|
128
|
+
* UCalendar.dst_savings("GMT+00".u) # => 3600000
|
129
|
+
*
|
130
|
+
*/
|
131
|
+
VALUE icu4r_cal_dst_savings(VALUE obj, VALUE zone)
|
132
|
+
{
|
133
|
+
UErrorCode status = U_ZERO_ERROR;
|
134
|
+
int32_t dst;
|
135
|
+
Check_Class(zone, rb_cUString);
|
136
|
+
dst = ucal_getDSTSavings (ICU_PTR(zone), &status);
|
137
|
+
ICU_RAISE(status);
|
138
|
+
return INT2FIX(dst);
|
139
|
+
}
|
140
|
+
|
141
|
+
/**
|
142
|
+
* call-seq:
|
143
|
+
* UCalendar.now
|
144
|
+
*
|
145
|
+
* Get the current date and time. in millis
|
146
|
+
*
|
147
|
+
* UCalendar.now # => 1137934561000.0
|
148
|
+
*
|
149
|
+
*/
|
150
|
+
VALUE icu4r_cal_now(VALUE obj){
|
151
|
+
return rb_float_new(ucal_getNow());
|
152
|
+
}
|
153
|
+
//-----------------
|
154
|
+
|
155
|
+
void icu4r_cal_free(UCalendar * cal){
|
156
|
+
ucal_close(cal);
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* call-seq:
|
161
|
+
* UCalendar.new(zone_id = nil, locale = nil, traditional = false)
|
162
|
+
*
|
163
|
+
* Creates new instance of UCalendar, for given time zone id (UString),
|
164
|
+
* locale (Ruby String), and kind , by default gregorian.
|
165
|
+
* New instance has current time.
|
166
|
+
*
|
167
|
+
*/
|
168
|
+
VALUE icu4r_cal_init (int argc, VALUE * argv, VALUE self)
|
169
|
+
{
|
170
|
+
VALUE zone, loc, cal_type;
|
171
|
+
UChar * zone_id = NULL;
|
172
|
+
char * locale = NULL;
|
173
|
+
UCalendarType c_type = UCAL_GREGORIAN;
|
174
|
+
int32_t n, zone_len =0 , locale_len =0;
|
175
|
+
UCalendar * calendar;
|
176
|
+
VALUE ret;
|
177
|
+
UErrorCode status = U_ZERO_ERROR;
|
178
|
+
n = rb_scan_args(argc, argv, "03", &zone, &loc, &cal_type);
|
179
|
+
if( n >= 1) {
|
180
|
+
Check_Class(zone, rb_cUString);
|
181
|
+
zone_id = ICU_PTR(zone);
|
182
|
+
zone_len = ICU_LEN(zone);
|
183
|
+
}
|
184
|
+
if( n >= 2) {
|
185
|
+
Check_Type(loc, T_STRING);
|
186
|
+
locale = RSTRING(loc)->ptr;
|
187
|
+
locale_len = RSTRING(loc)->len;
|
188
|
+
}
|
189
|
+
if( n >= 3) {
|
190
|
+
if( Qtrue == cal_type ) {
|
191
|
+
c_type = UCAL_TRADITIONAL;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
calendar = ucal_open(zone_id, zone_len, locale, c_type, &status);
|
195
|
+
ICU_RAISE(status);
|
196
|
+
ret = Data_Wrap_Struct(self, 0, icu4r_cal_free, calendar);
|
197
|
+
return ret;
|
198
|
+
}
|
199
|
+
|
200
|
+
int icu4r_get_cal_field_int(VALUE field)
|
201
|
+
{
|
202
|
+
VALUE field_const;
|
203
|
+
field_const = rb_hash_aref(s_calendar_fields, field);
|
204
|
+
if(field_const == Qnil)
|
205
|
+
rb_raise(rb_eArgError, "no such field %s", rb_obj_as_string(field));
|
206
|
+
return NUM2INT(field_const);
|
207
|
+
}
|
208
|
+
|
209
|
+
/**
|
210
|
+
* call-seq:
|
211
|
+
* calendar.add(field, int_amount)
|
212
|
+
*
|
213
|
+
* Add a specified signed amount to a particular field in a UCalendar.
|
214
|
+
*
|
215
|
+
* c.add(:week_of_year, 2)
|
216
|
+
*/
|
217
|
+
VALUE icu4r_cal_add(VALUE obj, VALUE field, VALUE amount)
|
218
|
+
{
|
219
|
+
UErrorCode status = U_ZERO_ERROR;
|
220
|
+
int date_field;
|
221
|
+
Check_Type(field, T_SYMBOL);
|
222
|
+
Check_Type(amount, T_FIXNUM);
|
223
|
+
date_field = icu4r_get_cal_field_int(field);
|
224
|
+
ucal_add(UCALENDAR(obj), date_field, FIX2INT(amount) , &status);
|
225
|
+
ICU_RAISE(status);
|
226
|
+
return Qnil;
|
227
|
+
}
|
228
|
+
|
229
|
+
/**
|
230
|
+
* call-seq:
|
231
|
+
* calendar.roll(field, int_amount)
|
232
|
+
*
|
233
|
+
* Adds a signed amount to the specified calendar field without changing larger fields.
|
234
|
+
* A negative roll amount means to subtract from field without changing larger fields.
|
235
|
+
* If the specified amount is 0, this method performs nothing.
|
236
|
+
*
|
237
|
+
* Example: Consider a GregorianCalendar originally set to August 31, 1999. Calling roll(:month, 8)
|
238
|
+
* sets the calendar to April 30, 1999. Using a Gregorian Calendar, the :day_of_month field cannot
|
239
|
+
* be 31 in the month April. :day_of_month is set to the closest possible value, 30. The :year field
|
240
|
+
* maintains the value of 1999 because it is a larger field than :month.
|
241
|
+
*/
|
242
|
+
VALUE icu4r_cal_roll(VALUE obj, VALUE field, VALUE amount)
|
243
|
+
{
|
244
|
+
UErrorCode status = U_ZERO_ERROR;
|
245
|
+
int date_field;
|
246
|
+
Check_Type(field, T_SYMBOL);
|
247
|
+
Check_Type(amount, T_FIXNUM);
|
248
|
+
date_field = icu4r_get_cal_field_int(field);
|
249
|
+
ucal_roll(UCALENDAR(obj), date_field, FIX2INT(amount) , &status);
|
250
|
+
ICU_RAISE(status);
|
251
|
+
return Qnil;
|
252
|
+
}
|
253
|
+
/**
|
254
|
+
* call-seq:
|
255
|
+
* calendar[field]
|
256
|
+
*
|
257
|
+
* Get the current value of a field from a UCalendar.
|
258
|
+
*
|
259
|
+
*/
|
260
|
+
VALUE icu4r_cal_aref(VALUE obj, VALUE field)
|
261
|
+
{
|
262
|
+
UErrorCode status = U_ZERO_ERROR;
|
263
|
+
int date_field;
|
264
|
+
int32_t value;
|
265
|
+
Check_Type(field, T_SYMBOL);
|
266
|
+
date_field = icu4r_get_cal_field_int(field);
|
267
|
+
value = ucal_get(UCALENDAR(obj), date_field, &status);
|
268
|
+
ICU_RAISE(status);
|
269
|
+
return INT2FIX(value);
|
270
|
+
}
|
271
|
+
|
272
|
+
/**
|
273
|
+
* call-seq:
|
274
|
+
* calendar[field]=int_value
|
275
|
+
*
|
276
|
+
* Set the value of a field in a UCalendar.
|
277
|
+
*/
|
278
|
+
VALUE icu4r_cal_aset(VALUE obj, VALUE field, VALUE amount)
|
279
|
+
{
|
280
|
+
int date_field, ret;
|
281
|
+
UErrorCode status = U_ZERO_ERROR;
|
282
|
+
Check_Type(field, T_SYMBOL);
|
283
|
+
Check_Type(amount, T_FIXNUM);
|
284
|
+
date_field = icu4r_get_cal_field_int(field);
|
285
|
+
ucal_set(UCALENDAR(obj), date_field, FIX2INT(amount) );
|
286
|
+
ret = ucal_get(UCALENDAR(obj), date_field, &status);
|
287
|
+
|
288
|
+
return INT2FIX(ret);
|
289
|
+
}
|
290
|
+
/**
|
291
|
+
* call-seq:
|
292
|
+
* calendar.millis
|
293
|
+
*
|
294
|
+
* return this calendar value in milliseconds.
|
295
|
+
*/
|
296
|
+
VALUE icu4r_cal_millis(VALUE obj)
|
297
|
+
{
|
298
|
+
UErrorCode status = U_ZERO_ERROR;
|
299
|
+
double millis;
|
300
|
+
millis = ucal_getMillis(UCALENDAR(obj), &status);
|
301
|
+
ICU_RAISE(status);
|
302
|
+
return rb_float_new(millis);
|
303
|
+
}
|
304
|
+
/**
|
305
|
+
* call-seq:
|
306
|
+
* calendar.millis = new_value
|
307
|
+
*
|
308
|
+
* Sets calendar's value in milliseconds.
|
309
|
+
*/
|
310
|
+
VALUE icu4r_cal_set_millis(VALUE obj,VALUE milli)
|
311
|
+
{
|
312
|
+
UErrorCode status = U_ZERO_ERROR;
|
313
|
+
Check_Type(milli, T_FLOAT);
|
314
|
+
ucal_setMillis(UCALENDAR(obj), rb_num2dbl(milli), &status);
|
315
|
+
ICU_RAISE(status);
|
316
|
+
return Qnil;
|
317
|
+
}
|
318
|
+
|
319
|
+
/**
|
320
|
+
* call-seq:
|
321
|
+
* calendar.set_date(year, month, date)
|
322
|
+
*
|
323
|
+
* Set a UCalendar's current date.
|
324
|
+
*/
|
325
|
+
VALUE icu4r_cal_set_date(VALUE obj,VALUE year, VALUE mon, VALUE date)
|
326
|
+
{
|
327
|
+
UErrorCode status = U_ZERO_ERROR;
|
328
|
+
Check_Type(year, T_FIXNUM);
|
329
|
+
Check_Type(mon, T_FIXNUM);
|
330
|
+
Check_Type(date, T_FIXNUM);
|
331
|
+
ucal_setDate(UCALENDAR(obj), FIX2INT(year), FIX2INT(mon), FIX2INT(date), &status);
|
332
|
+
ICU_RAISE(status);
|
333
|
+
return Qnil;
|
334
|
+
}
|
335
|
+
/**
|
336
|
+
* call-seq:
|
337
|
+
* calendar.set_date_time(year, month, date, hour, minute, second)
|
338
|
+
*
|
339
|
+
* Set a UCalendar's current date and time.
|
340
|
+
*/
|
341
|
+
VALUE icu4r_cal_set_date_time(VALUE obj,VALUE year, VALUE mon, VALUE date, VALUE hour, VALUE min, VALUE sec)
|
342
|
+
{
|
343
|
+
UErrorCode status = U_ZERO_ERROR;
|
344
|
+
Check_Type(year, T_FIXNUM);
|
345
|
+
Check_Type(mon, T_FIXNUM);
|
346
|
+
Check_Type(date, T_FIXNUM);
|
347
|
+
Check_Type(hour, T_FIXNUM);
|
348
|
+
Check_Type(min, T_FIXNUM);
|
349
|
+
Check_Type(sec, T_FIXNUM);
|
350
|
+
|
351
|
+
ucal_setDateTime(UCALENDAR(obj),
|
352
|
+
FIX2INT(year), FIX2INT(mon), FIX2INT(date),
|
353
|
+
FIX2INT(hour), FIX2INT(min), FIX2INT(sec),
|
354
|
+
&status);
|
355
|
+
ICU_RAISE(status);
|
356
|
+
return Qnil;
|
357
|
+
}
|
358
|
+
|
359
|
+
/**
|
360
|
+
* call-seq:
|
361
|
+
* calendar.time_zone = zone_id
|
362
|
+
*
|
363
|
+
* Set the TimeZone used by a UCalendar.
|
364
|
+
*/
|
365
|
+
VALUE icu4r_cal_set_tz(VALUE obj, VALUE zone)
|
366
|
+
{
|
367
|
+
UErrorCode status = U_ZERO_ERROR;
|
368
|
+
Check_Class(zone, rb_cUString);
|
369
|
+
ucal_setTimeZone(UCALENDAR(obj), ICU_PTR(zone), ICU_LEN(zone), &status);
|
370
|
+
ICU_RAISE(status);
|
371
|
+
return Qnil;
|
372
|
+
|
373
|
+
}
|
374
|
+
|
375
|
+
/**
|
376
|
+
* call-seq:
|
377
|
+
* calendar.in_daylight_time?
|
378
|
+
*
|
379
|
+
* Determine if a UCalendar is currently in daylight savings time.
|
380
|
+
*
|
381
|
+
* Daylight savings time is not used in all parts of the world
|
382
|
+
*/
|
383
|
+
VALUE icu4r_cal_in_daylight(VALUE obj)
|
384
|
+
{
|
385
|
+
UErrorCode status = U_ZERO_ERROR;
|
386
|
+
int32_t answer;
|
387
|
+
answer = ucal_inDaylightTime(UCALENDAR(obj), &status);
|
388
|
+
ICU_RAISE(status);
|
389
|
+
return answer ? Qtrue : Qfalse;
|
390
|
+
}
|
391
|
+
|
392
|
+
/**
|
393
|
+
* call-seq:
|
394
|
+
* calendar.time_zone
|
395
|
+
*
|
396
|
+
* Returns the TimeZone used by a UCalendar.
|
397
|
+
*/
|
398
|
+
VALUE icu4r_cal_get_tz (int argc, VALUE * argv, VALUE obj)
|
399
|
+
{
|
400
|
+
UErrorCode status = U_ZERO_ERROR;
|
401
|
+
UChar * buf = NULL;
|
402
|
+
long capa = 0;
|
403
|
+
char *locale = NULL;
|
404
|
+
VALUE loc;
|
405
|
+
if( rb_scan_args(argc, argv, "01", &loc) == 1){
|
406
|
+
Check_Type(loc, T_STRING);
|
407
|
+
locale = RSTRING(loc)->ptr;
|
408
|
+
}
|
409
|
+
|
410
|
+
capa = ucal_getTimeZoneDisplayName(UCALENDAR(obj), UCAL_STANDARD, locale, buf, capa, &status);
|
411
|
+
if( U_BUFFER_OVERFLOW_ERROR == status) {
|
412
|
+
buf = ALLOC_N(UChar, capa+1);
|
413
|
+
status = U_ZERO_ERROR;
|
414
|
+
capa = ucal_getTimeZoneDisplayName(UCALENDAR(obj), UCAL_STANDARD, locale, buf, capa, &status);
|
415
|
+
return icu_ustr_new_set(buf, capa, capa+1);
|
416
|
+
}
|
417
|
+
ICU_RAISE(status);
|
418
|
+
return Qnil;
|
419
|
+
|
420
|
+
}
|
421
|
+
/** call-seq:
|
422
|
+
* calendar.format(pattern = nil , locale = nil)
|
423
|
+
*
|
424
|
+
* Formats this calendar time using given pattern and locale. Returns UString or nil on failure
|
425
|
+
*/
|
426
|
+
VALUE icu4r_cal_format(int argc, VALUE * argv, VALUE obj)
|
427
|
+
{
|
428
|
+
UErrorCode status = U_ZERO_ERROR;
|
429
|
+
UDateFormat * format;
|
430
|
+
UDate time_to_format;
|
431
|
+
UChar * buf = NULL, * pattern = NULL;
|
432
|
+
long capa = 0, pattern_len = 0;
|
433
|
+
char *locale = NULL;
|
434
|
+
VALUE loc, pat, ret = Qnil;
|
435
|
+
int n ;
|
436
|
+
|
437
|
+
|
438
|
+
|
439
|
+
n = rb_scan_args(argc, argv, "02", &pat, &loc);
|
440
|
+
if( n == 2) {
|
441
|
+
Check_Type(loc, T_STRING);
|
442
|
+
locale = RSTRING(loc)->ptr;
|
443
|
+
}
|
444
|
+
if (n >= 1 && pat != Qnil) {
|
445
|
+
Check_Class(pat, rb_cUString);
|
446
|
+
pattern = ICU_PTR(pat);
|
447
|
+
pattern_len = ICU_LEN(pat);
|
448
|
+
}
|
449
|
+
|
450
|
+
format = udat_open(UDAT_FULL, UDAT_FULL, locale, NULL, 0, NULL, 0, &status);
|
451
|
+
if( pattern ) {
|
452
|
+
udat_applyPattern(format, 0, pattern, pattern_len);
|
453
|
+
}
|
454
|
+
ICU_RAISE(status);
|
455
|
+
udat_setCalendar(format, UCALENDAR(obj));
|
456
|
+
time_to_format = ucal_getMillis(UCALENDAR(obj), &status);
|
457
|
+
|
458
|
+
capa = udat_format(format, time_to_format, buf, capa, NULL, &status);
|
459
|
+
if( U_BUFFER_OVERFLOW_ERROR == status) {
|
460
|
+
buf = ALLOC_N(UChar, capa+1);
|
461
|
+
status = U_ZERO_ERROR;
|
462
|
+
capa = udat_format(format, time_to_format, buf, capa, NULL, &status);
|
463
|
+
ret = icu_ustr_new_set(buf, capa, capa+1);
|
464
|
+
}
|
465
|
+
udat_close(format);
|
466
|
+
ICU_RAISE(status);
|
467
|
+
return ret;
|
468
|
+
}
|
469
|
+
|
470
|
+
/**
|
471
|
+
* Document-method: clone
|
472
|
+
*
|
473
|
+
* call-seq:
|
474
|
+
* cal.clone => UCalendar
|
475
|
+
*
|
476
|
+
* Create and return a copy of this calendar.
|
477
|
+
*/
|
478
|
+
extern VALUE icu4r_cal_clone(VALUE obj);
|
479
|
+
/**
|
480
|
+
* Document-method: eql?
|
481
|
+
*
|
482
|
+
* call-seq:
|
483
|
+
* cal.eql?(other)
|
484
|
+
*
|
485
|
+
* Compares the equality of two UCalendar objects.
|
486
|
+
*
|
487
|
+
* This comparison is very exacting; two UCalendar objects must be in exactly the
|
488
|
+
* same state to be considered equal.
|
489
|
+
*/
|
490
|
+
extern VALUE icu4r_cal_equal(VALUE obj, VALUE other);
|
491
|
+
|
492
|
+
/**
|
493
|
+
* Document-method: >
|
494
|
+
*
|
495
|
+
* call-seq:
|
496
|
+
* cal > when
|
497
|
+
*
|
498
|
+
* True if the current time of this UCalendar is after the time of UCalendar +when+; false otherwise.
|
499
|
+
*/
|
500
|
+
extern VALUE icu4r_cal_after(VALUE obj, VALUE other);
|
501
|
+
/**
|
502
|
+
* Document-method: <
|
503
|
+
*
|
504
|
+
* call-seq:
|
505
|
+
* cal < when
|
506
|
+
*
|
507
|
+
* True if the current time of this UCalendar is before the time of UCalendar +when+; false otherwise.
|
508
|
+
*/
|
509
|
+
extern VALUE icu4r_cal_before(VALUE obj, VALUE other);
|
510
|
+
/**
|
511
|
+
* Document-method: ==
|
512
|
+
*
|
513
|
+
* call-seq:
|
514
|
+
* cal == when
|
515
|
+
*
|
516
|
+
* True if the current time of this UCalendar is equal to the time of UCalendar +when+; false otherwise.
|
517
|
+
*/
|
518
|
+
extern VALUE icu4r_cal_time_equals(VALUE obj, VALUE other);
|
519
|
+
|
520
|
+
void initialize_calendar(void) {
|
521
|
+
|
522
|
+
rb_cUCalendar = rb_define_class("UCalendar", rb_cObject);
|
523
|
+
s_calendar_fields = rb_hash_new();
|
524
|
+
/* Valid symbols to use as field reference in UCalendar#[], UCalendar#[]=, UCalendar#add are:
|
525
|
+
:era , :year , :month , :week_of_year , :week_of_month , :date , :day_of_year , :day_of_week, :day_of_week_in_month,
|
526
|
+
:am_pm , :hour , :hour_of_day , :minute , :second , :millisecond , :zone_offset , :dst_offset:
|
527
|
+
*/
|
528
|
+
rb_define_const(rb_cUCalendar, "UCALENDAR_FIELDS", s_calendar_fields);
|
529
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("era")), INT2NUM(UCAL_ERA ));
|
530
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("year")), INT2NUM(UCAL_YEAR ));
|
531
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("month")), INT2NUM(UCAL_MONTH));
|
532
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("week_of_year")), INT2NUM(UCAL_WEEK_OF_YEAR ));
|
533
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("week_of_month")), INT2NUM(UCAL_WEEK_OF_MONTH));
|
534
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("date")), INT2NUM(UCAL_DATE));
|
535
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("day_of_year")), INT2NUM(UCAL_DAY_OF_YEAR));
|
536
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("day_of_week")), INT2NUM(UCAL_DAY_OF_WEEK));
|
537
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("day_of_week_in_month")), INT2NUM(UCAL_DAY_OF_WEEK_IN_MONTH));
|
538
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("am_pm")), INT2NUM(UCAL_AM_PM));
|
539
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("hour")), INT2NUM(UCAL_HOUR));
|
540
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("hour_of_day")), INT2NUM(UCAL_HOUR_OF_DAY));
|
541
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("minute")), INT2NUM(UCAL_MINUTE ));
|
542
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("second")), INT2NUM(UCAL_SECOND));
|
543
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("millisecond")), INT2NUM(UCAL_MILLISECOND ));
|
544
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("zone_offset")), INT2NUM(UCAL_ZONE_OFFSET));
|
545
|
+
rb_hash_aset(s_calendar_fields, ID2SYM(rb_intern("dst_offset")), INT2NUM(UCAL_DST_OFFSET));
|
546
|
+
|
547
|
+
|
548
|
+
rb_define_singleton_method(rb_cUCalendar, "now", icu4r_cal_now, 0);
|
549
|
+
|
550
|
+
rb_define_singleton_method(rb_cUCalendar, "default_tz=", icu4r_cal_set_default_tz, 1);
|
551
|
+
rb_define_singleton_method(rb_cUCalendar, "default_tz", icu4r_cal_get_default_tz, 0);
|
552
|
+
rb_define_singleton_method(rb_cUCalendar, "time_zones", icu4r_cal_all_tz, 0);
|
553
|
+
rb_define_singleton_method(rb_cUCalendar, "tz_for_country", icu4r_cal_country_tz, 1);
|
554
|
+
rb_define_singleton_method(rb_cUCalendar, "dst_savings", icu4r_cal_dst_savings, 1);
|
555
|
+
|
556
|
+
rb_define_singleton_method(rb_cUCalendar, "new", icu4r_cal_init, -1);
|
557
|
+
rb_define_method(rb_cUCalendar, "add", icu4r_cal_add, 2);
|
558
|
+
rb_define_method(rb_cUCalendar, "roll", icu4r_cal_roll, 2);
|
559
|
+
rb_define_method(rb_cUCalendar, "[]", icu4r_cal_aref, 1);
|
560
|
+
rb_define_method(rb_cUCalendar, "[]=", icu4r_cal_aset, 2);
|
561
|
+
rb_define_method(rb_cUCalendar, "millis=", icu4r_cal_set_millis, 1);
|
562
|
+
rb_define_method(rb_cUCalendar, "millis", icu4r_cal_millis,0);
|
563
|
+
rb_define_method(rb_cUCalendar, "set_date", icu4r_cal_set_date,3);
|
564
|
+
rb_define_method(rb_cUCalendar, "set_date_time", icu4r_cal_set_date_time,6);
|
565
|
+
rb_define_method(rb_cUCalendar, "time_zone=", icu4r_cal_set_tz,1);
|
566
|
+
rb_define_method(rb_cUCalendar, "time_zone", icu4r_cal_get_tz,-1);
|
567
|
+
rb_define_method(rb_cUCalendar, "in_daylight_time?", icu4r_cal_in_daylight,0);
|
568
|
+
rb_define_method(rb_cUCalendar, "format", icu4r_cal_format,-1);
|
569
|
+
|
570
|
+
rb_define_method(rb_cUCalendar, "clone", icu4r_cal_clone,0);
|
571
|
+
rb_define_method(rb_cUCalendar, "eql?", icu4r_cal_equal,1);
|
572
|
+
rb_define_method(rb_cUCalendar, "<", icu4r_cal_before,1);
|
573
|
+
rb_define_method(rb_cUCalendar, ">", icu4r_cal_after,1);
|
574
|
+
rb_define_method(rb_cUCalendar, "==", icu4r_cal_time_equals, 1);
|
575
|
+
|
576
|
+
}
|
data/docs/FORMATTING
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
=== Locale-sensitive Message Formatting
|
2
|
+
|
3
|
+
Basic pattern rules are:
|
4
|
+
|
5
|
+
messageFormatPattern := string ( "{" messageFormatElement "}" string )*
|
6
|
+
|
7
|
+
messageFormatElement := argument { "," elementFormat }
|
8
|
+
|
9
|
+
elementFormat := "time" { "," datetimeStyle }
|
10
|
+
| "date" { "," datetimeStyle }
|
11
|
+
| "number" { "," numberStyle }
|
12
|
+
| "spellout"
|
13
|
+
| "ordinal"
|
14
|
+
| "duration"
|
15
|
+
| "choice" "," choiceStyle
|
16
|
+
|
17
|
+
datetimeStyle := "short"
|
18
|
+
| "medium"
|
19
|
+
| "long"
|
20
|
+
| "full"
|
21
|
+
| dateFormatPattern
|
22
|
+
|
23
|
+
numberStyle := "currency"
|
24
|
+
| "percent"
|
25
|
+
| "integer"
|
26
|
+
| numberFormatPattern
|
27
|
+
|
28
|
+
choiceStyle := choiceFormatPattern
|
29
|
+
|
30
|
+
=== numberFormatPattern
|
31
|
+
|
32
|
+
pattern := subpattern{;subpattern}
|
33
|
+
subpattern := {prefix}integer{.fraction}{suffix}
|
34
|
+
|
35
|
+
prefix := '\\u0000'..'\\uFFFD' - specialCharacters
|
36
|
+
suffix := '\\u0000'..'\\uFFFD' - specialCharacters
|
37
|
+
integer := '#'* '0'* '0'
|
38
|
+
fraction := '0'* '#'*
|
39
|
+
|
40
|
+
Notation:
|
41
|
+
X* 0 or more instances of X
|
42
|
+
(X | Y) either X or Y.
|
43
|
+
X..Y any character from X up to Y, inclusive.
|
44
|
+
S - T characters in S, except those in T
|
45
|
+
|
46
|
+
The first subpattern is for positive numbers. The second (optional)
|
47
|
+
subpattern is used for negative numbers. (In both cases, ',' can
|
48
|
+
occur inside the integer portion--it is just too messy to indicate
|
49
|
+
in BNF.) For the second subpattern, only the PREFIX and SUFFIX are
|
50
|
+
noted; other attributes are taken only from the first subpattern.
|
51
|
+
|
52
|
+
Here are the special characters used in the parts of the
|
53
|
+
subpattern, with notes on their usage.
|
54
|
+
|
55
|
+
Symbol Meaning
|
56
|
+
0 a digit, showing up a zero if it is zero
|
57
|
+
# a digit, supressed if zero
|
58
|
+
. placeholder for decimal separator
|
59
|
+
, placeholder for grouping separator.
|
60
|
+
E separates mantissa and exponent for exponential formats.
|
61
|
+
; separates formats.
|
62
|
+
- default negative prefix.
|
63
|
+
% multiply by 100 and show as percentage
|
64
|
+
\u2030 multiply by 1000 and show as per mille
|
65
|
+
\u00A4 currency sign; replaced by currency symbol; if doubled, replaced by international currency symbol.
|
66
|
+
If present in a pattern, the monetary decimal separator
|
67
|
+
is used instead of the decimal separator.
|
68
|
+
X any other characters can be used in the prefix or suffix
|
69
|
+
' used to quote special characters in a prefix or suffix.
|
70
|
+
|
71
|
+
=== dateFormatPattern
|
72
|
+
|
73
|
+
Symbol Meaning Presentation Example
|
74
|
+
------ ------- ------------ -------
|
75
|
+
G era designator (Text) AD
|
76
|
+
y year (Number) 1996
|
77
|
+
Y year/week of year (Number) 1996
|
78
|
+
M month in year (Text & Number) July & 07
|
79
|
+
d day in month (Number) 10
|
80
|
+
h hour in am/pm (1~12) (Number) 12
|
81
|
+
H hour in day (0~23) (Number) 0
|
82
|
+
m minute in hour (Number) 30
|
83
|
+
s second in minute (Number) 55
|
84
|
+
S millisecond (Number) 978
|
85
|
+
E day of week (Text) Tuesday
|
86
|
+
e day of week/local (1~7) (Number) 2
|
87
|
+
D day of year (Number) 189
|
88
|
+
F day of week in month (Number) 2 (2nd Wed in July)
|
89
|
+
w week in year (Number) 27
|
90
|
+
W week in month (Number) 2
|
91
|
+
a am/pm marker (Text) PM
|
92
|
+
k hour in day (1~24) (Number) 24
|
93
|
+
K hour in am/pm (0~11) (Number) 0
|
94
|
+
z time zone (Text) Pacific Standard Time
|
95
|
+
' escape for text
|
96
|
+
'' single quote '
|
97
|
+
|
98
|
+
|
99
|
+
=== choiceFormatPattern
|
100
|
+
In most cases, the preferred way to define a ChoiceFormat is with a pattern. Here is an example of a ChoiceFormat pattern:
|
101
|
+
|
102
|
+
0≤are no files|1≤is one file|1<are many files
|
103
|
+
|
104
|
+
or equivalently,
|
105
|
+
|
106
|
+
0#are no files|1#is one file|1<are many files
|
107
|
+
|
108
|
+
The pattern consists of a number or range specifiers separated by vertical bars '|' (U+007C). There is no vertical bar after the last range. Each range specifier is of the form:
|
109
|
+
|
110
|
+
Number is a floating point number that can be parsed by a default
|
111
|
+
NumberFormat for the US locale. It gives the lower limit of this range.
|
112
|
+
The lower limit is either inclusive or exclusive, depending on the separator.
|
113
|
+
The upper limit is given by the lower limit of the next range. The Unicode infinity
|
114
|
+
sign ∞ (U+221E) is recognized for positive infinity. It may be preceded by '-' (U+002D)
|
115
|
+
to indicate negative infinity.
|
116
|
+
|
117
|
+
String is the format string for this range, with special characters enclosed in single
|
118
|
+
quotes ('The # sign'). Single quotes themselves are indicated by two single quotes in a
|
119
|
+
row ('o''clock').
|
120
|
+
|
121
|
+
Separator is one of the following single characters:
|
122
|
+
* '≤' (U+2264) or '#' (U+0023) indicates that the lower limit given by
|
123
|
+
Number is inclusive. (The two characters are equivalent to ChoiceFormat.)
|
124
|
+
This means that the limit value Number belongs to this range. Another way of
|
125
|
+
saying this is that the corresponding closure is FALSE.
|
126
|
+
|
127
|
+
* '<' (U+003C) indicates that the lower limit given by Number is exclusive.
|
128
|
+
This means that the value Number belongs to the prior range. Another way of saying
|
129
|
+
this is that the corresponding closure is TRUE.
|
130
|
+
|
131
|
+
See ICU docs for more info and examples.
|