Line data Source code
1 : // © 2016 and later: Unicode, Inc. and others.
2 : // License & terms of use: http://www.unicode.org/copyright.html
3 : /*
4 : *******************************************************************************
5 : * Copyright (C) 2008-2016, International Business Machines Corporation and
6 : * others. All Rights Reserved.
7 : *******************************************************************************
8 : *
9 : * File DTITVINF.H
10 : *
11 : *******************************************************************************
12 : */
13 :
14 : #ifndef __DTITVINF_H__
15 : #define __DTITVINF_H__
16 :
17 : #include "unicode/utypes.h"
18 :
19 : /**
20 : * \file
21 : * \brief C++ API: Date/Time interval patterns for formatting date/time interval
22 : */
23 :
24 : #if !UCONFIG_NO_FORMATTING
25 :
26 : #include "unicode/udat.h"
27 : #include "unicode/locid.h"
28 : #include "unicode/ucal.h"
29 : #include "unicode/dtptngen.h"
30 :
31 : U_NAMESPACE_BEGIN
32 :
33 : /**
34 : * DateIntervalInfo is a public class for encapsulating localizable
35 : * date time interval patterns. It is used by DateIntervalFormat.
36 : *
37 : * <P>
38 : * For most users, ordinary use of DateIntervalFormat does not need to create
39 : * DateIntervalInfo object directly.
40 : * DateIntervalFormat will take care of it when creating a date interval
41 : * formatter when user pass in skeleton and locale.
42 : *
43 : * <P>
44 : * For power users, who want to create their own date interval patterns,
45 : * or want to re-set date interval patterns, they could do so by
46 : * directly creating DateIntervalInfo and manupulating it.
47 : *
48 : * <P>
49 : * Logically, the interval patterns are mappings
50 : * from (skeleton, the_largest_different_calendar_field)
51 : * to (date_interval_pattern).
52 : *
53 : * <P>
54 : * A skeleton
55 : * <ol>
56 : * <li>
57 : * only keeps the field pattern letter and ignores all other parts
58 : * in a pattern, such as space, punctuations, and string literals.
59 : * <li>
60 : * hides the order of fields.
61 : * <li>
62 : * might hide a field's pattern letter length.
63 : *
64 : * For those non-digit calendar fields, the pattern letter length is
65 : * important, such as MMM, MMMM, and MMMMM; EEE and EEEE,
66 : * and the field's pattern letter length is honored.
67 : *
68 : * For the digit calendar fields, such as M or MM, d or dd, yy or yyyy,
69 : * the field pattern length is ignored and the best match, which is defined
70 : * in date time patterns, will be returned without honor the field pattern
71 : * letter length in skeleton.
72 : * </ol>
73 : *
74 : * <P>
75 : * The calendar fields we support for interval formatting are:
76 : * year, month, date, day-of-week, am-pm, hour, hour-of-day, and minute.
77 : * Those calendar fields can be defined in the following order:
78 : * year > month > date > am-pm > hour > minute
79 : *
80 : * The largest different calendar fields between 2 calendars is the
81 : * first different calendar field in above order.
82 : *
83 : * For example: the largest different calendar fields between "Jan 10, 2007"
84 : * and "Feb 20, 2008" is year.
85 : *
86 : * <P>
87 : * There is a set of pre-defined static skeleton strings.
88 : * There are pre-defined interval patterns for those pre-defined skeletons
89 : * in locales' resource files.
90 : * For example, for a skeleton UDAT_YEAR_ABBR_MONTH_DAY, which is "yMMMd",
91 : * in en_US, if the largest different calendar field between date1 and date2
92 : * is "year", the date interval pattern is "MMM d, yyyy - MMM d, yyyy",
93 : * such as "Jan 10, 2007 - Jan 10, 2008".
94 : * If the largest different calendar field between date1 and date2 is "month",
95 : * the date interval pattern is "MMM d - MMM d, yyyy",
96 : * such as "Jan 10 - Feb 10, 2007".
97 : * If the largest different calendar field between date1 and date2 is "day",
98 : * the date interval pattern is "MMM d-d, yyyy", such as "Jan 10-20, 2007".
99 : *
100 : * For date skeleton, the interval patterns when year, or month, or date is
101 : * different are defined in resource files.
102 : * For time skeleton, the interval patterns when am/pm, or hour, or minute is
103 : * different are defined in resource files.
104 : *
105 : *
106 : * <P>
107 : * There are 2 dates in interval pattern. For most locales, the first date
108 : * in an interval pattern is the earlier date. There might be a locale in which
109 : * the first date in an interval pattern is the later date.
110 : * We use fallback format for the default order for the locale.
111 : * For example, if the fallback format is "{0} - {1}", it means
112 : * the first date in the interval pattern for this locale is earlier date.
113 : * If the fallback format is "{1} - {0}", it means the first date is the
114 : * later date.
115 : * For a particular interval pattern, the default order can be overriden
116 : * by prefixing "latestFirst:" or "earliestFirst:" to the interval pattern.
117 : * For example, if the fallback format is "{0}-{1}",
118 : * but for skeleton "yMMMd", the interval pattern when day is different is
119 : * "latestFirst:d-d MMM yy", it means by default, the first date in interval
120 : * pattern is the earlier date. But for skeleton "yMMMd", when day is different,
121 : * the first date in "d-d MMM yy" is the later date.
122 : *
123 : * <P>
124 : * The recommended way to create a DateIntervalFormat object is to pass in
125 : * the locale.
126 : * By using a Locale parameter, the DateIntervalFormat object is
127 : * initialized with the pre-defined interval patterns for a given or
128 : * default locale.
129 : * <P>
130 : * Users can also create DateIntervalFormat object
131 : * by supplying their own interval patterns.
132 : * It provides flexibility for power users.
133 : *
134 : * <P>
135 : * After a DateIntervalInfo object is created, clients may modify
136 : * the interval patterns using setIntervalPattern function as so desired.
137 : * Currently, users can only set interval patterns when the following
138 : * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH,
139 : * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE.
140 : * Interval patterns when other calendar fields are different is not supported.
141 : * <P>
142 : * DateIntervalInfo objects are cloneable.
143 : * When clients obtain a DateIntervalInfo object,
144 : * they can feel free to modify it as necessary.
145 : * <P>
146 : * DateIntervalInfo are not expected to be subclassed.
147 : * Data for a calendar is loaded out of resource bundles.
148 : * Through ICU 4.4, date interval patterns are only supported in the Gregorian
149 : * calendar; non-Gregorian calendars are supported from ICU 4.4.1.
150 : * @stable ICU 4.0
151 : **/
152 :
153 : class U_I18N_API DateIntervalInfo U_FINAL : public UObject {
154 : public:
155 : // Do not enclose the protected default constructor with #ifndef U_HIDE_INTERNAL_API
156 : // or else the compiler will create a public default constructor.
157 : /**
158 : * Default constructor.
159 : * It does not initialize any interval patterns except
160 : * that it initialize default fall-back pattern as "{0} - {1}",
161 : * which can be reset by setFallbackIntervalPattern().
162 : * It should be followed by setFallbackIntervalPattern() and
163 : * setIntervalPattern(),
164 : * and is recommended to be used only for power users who
165 : * wants to create their own interval patterns and use them to create
166 : * date interval formatter.
167 : * @param status output param set to success/failure code on exit
168 : * @internal ICU 4.0
169 : */
170 : DateIntervalInfo(UErrorCode& status);
171 :
172 :
173 : /**
174 : * Construct DateIntervalInfo for the given locale,
175 : * @param locale the interval patterns are loaded from the appropriate calendar
176 : * data (specified calendar or default calendar) in this locale.
177 : * @param status output param set to success/failure code on exit
178 : * @stable ICU 4.0
179 : */
180 : DateIntervalInfo(const Locale& locale, UErrorCode& status);
181 :
182 :
183 : /**
184 : * Copy constructor.
185 : * @stable ICU 4.0
186 : */
187 : DateIntervalInfo(const DateIntervalInfo&);
188 :
189 : /**
190 : * Assignment operator
191 : * @stable ICU 4.0
192 : */
193 : DateIntervalInfo& operator=(const DateIntervalInfo&);
194 :
195 : /**
196 : * Clone this object polymorphically.
197 : * The caller owns the result and should delete it when done.
198 : * @return a copy of the object
199 : * @stable ICU 4.0
200 : */
201 : virtual DateIntervalInfo* clone(void) const;
202 :
203 : /**
204 : * Destructor.
205 : * It is virtual to be safe, but it is not designed to be subclassed.
206 : * @stable ICU 4.0
207 : */
208 : virtual ~DateIntervalInfo();
209 :
210 :
211 : /**
212 : * Return true if another object is semantically equal to this one.
213 : *
214 : * @param other the DateIntervalInfo object to be compared with.
215 : * @return true if other is semantically equal to this.
216 : * @stable ICU 4.0
217 : */
218 : virtual UBool operator==(const DateIntervalInfo& other) const;
219 :
220 : /**
221 : * Return true if another object is semantically unequal to this one.
222 : *
223 : * @param other the DateIntervalInfo object to be compared with.
224 : * @return true if other is semantically unequal to this.
225 : * @stable ICU 4.0
226 : */
227 : UBool operator!=(const DateIntervalInfo& other) const;
228 :
229 :
230 :
231 : /**
232 : * Provides a way for client to build interval patterns.
233 : * User could construct DateIntervalInfo by providing a list of skeletons
234 : * and their patterns.
235 : * <P>
236 : * For example:
237 : * <pre>
238 : * UErrorCode status = U_ZERO_ERROR;
239 : * DateIntervalInfo dIntervalInfo = new DateIntervalInfo();
240 : * dIntervalInfo->setFallbackIntervalPattern("{0} ~ {1}");
241 : * dIntervalInfo->setIntervalPattern("yMd", UCAL_YEAR, "'from' yyyy-M-d 'to' yyyy-M-d", status);
242 : * dIntervalInfo->setIntervalPattern("yMMMd", UCAL_MONTH, "'from' yyyy MMM d 'to' MMM d", status);
243 : * dIntervalInfo->setIntervalPattern("yMMMd", UCAL_DAY, "yyyy MMM d-d", status, status);
244 : * </pre>
245 : *
246 : * Restriction:
247 : * Currently, users can only set interval patterns when the following
248 : * calendar fields are different: ERA, YEAR, MONTH, DATE, DAY_OF_MONTH,
249 : * DAY_OF_WEEK, AM_PM, HOUR, HOUR_OF_DAY, and MINUTE.
250 : * Interval patterns when other calendar fields are different are
251 : * not supported.
252 : *
253 : * @param skeleton the skeleton on which interval pattern based
254 : * @param lrgDiffCalUnit the largest different calendar unit.
255 : * @param intervalPattern the interval pattern on the largest different
256 : * calendar unit.
257 : * For example, if lrgDiffCalUnit is
258 : * "year", the interval pattern for en_US when year
259 : * is different could be "'from' yyyy 'to' yyyy".
260 : * @param status output param set to success/failure code on exit
261 : * @stable ICU 4.0
262 : */
263 : void setIntervalPattern(const UnicodeString& skeleton,
264 : UCalendarDateFields lrgDiffCalUnit,
265 : const UnicodeString& intervalPattern,
266 : UErrorCode& status);
267 :
268 : /**
269 : * Get the interval pattern given skeleton and
270 : * the largest different calendar field.
271 : * @param skeleton the skeleton
272 : * @param field the largest different calendar field
273 : * @param result output param to receive the pattern
274 : * @param status output param set to success/failure code on exit
275 : * @return a reference to 'result'
276 : * @stable ICU 4.0
277 : */
278 : UnicodeString& getIntervalPattern(const UnicodeString& skeleton,
279 : UCalendarDateFields field,
280 : UnicodeString& result,
281 : UErrorCode& status) const;
282 :
283 : /**
284 : * Get the fallback interval pattern.
285 : * @param result output param to receive the pattern
286 : * @return a reference to 'result'
287 : * @stable ICU 4.0
288 : */
289 : UnicodeString& getFallbackIntervalPattern(UnicodeString& result) const;
290 :
291 :
292 : /**
293 : * Re-set the fallback interval pattern.
294 : *
295 : * In construction, default fallback pattern is set as "{0} - {1}".
296 : * And constructor taking locale as parameter will set the
297 : * fallback pattern as what defined in the locale resource file.
298 : *
299 : * This method provides a way for user to replace the fallback pattern.
300 : *
301 : * @param fallbackPattern fall-back interval pattern.
302 : * @param status output param set to success/failure code on exit
303 : * @stable ICU 4.0
304 : */
305 : void setFallbackIntervalPattern(const UnicodeString& fallbackPattern,
306 : UErrorCode& status);
307 :
308 :
309 : /** Get default order -- whether the first date in pattern is later date
310 : or not.
311 : * return default date ordering in interval pattern. TRUE if the first date
312 : * in pattern is later date, FALSE otherwise.
313 : * @stable ICU 4.0
314 : */
315 : UBool getDefaultOrder() const;
316 :
317 :
318 : /**
319 : * ICU "poor man's RTTI", returns a UClassID for the actual class.
320 : *
321 : * @stable ICU 4.0
322 : */
323 : virtual UClassID getDynamicClassID() const;
324 :
325 : /**
326 : * ICU "poor man's RTTI", returns a UClassID for this class.
327 : *
328 : * @stable ICU 4.0
329 : */
330 : static UClassID U_EXPORT2 getStaticClassID();
331 :
332 :
333 : private:
334 : /**
335 : * DateIntervalFormat will need access to
336 : * getBestSkeleton(), parseSkeleton(), enum IntervalPatternIndex,
337 : * and calendarFieldToPatternIndex().
338 : *
339 : * Instead of making above public,
340 : * make DateIntervalFormat a friend of DateIntervalInfo.
341 : */
342 : friend class DateIntervalFormat;
343 :
344 : /**
345 : * Internal struct used to load resource bundle data.
346 : */
347 : struct DateIntervalSink;
348 :
349 : /**
350 : * Following is for saving the interval patterns.
351 : * We only support interval patterns on
352 : * ERA, YEAR, MONTH, DAY, AM_PM, HOUR, and MINUTE
353 : */
354 : enum IntervalPatternIndex
355 : {
356 : kIPI_ERA,
357 : kIPI_YEAR,
358 : kIPI_MONTH,
359 : kIPI_DATE,
360 : kIPI_AM_PM,
361 : kIPI_HOUR,
362 : kIPI_MINUTE,
363 : kIPI_SECOND,
364 : kIPI_MAX_INDEX
365 : };
366 : public:
367 : #ifndef U_HIDE_INTERNAL_API
368 : /**
369 : * Max index for stored interval patterns
370 : * @internal ICU 4.4
371 : */
372 : enum {
373 : kMaxIntervalPatternIndex = kIPI_MAX_INDEX
374 : };
375 : #endif /* U_HIDE_INTERNAL_API */
376 : private:
377 :
378 :
379 : /**
380 : * Initialize the DateIntervalInfo from locale
381 : * @param locale the given locale.
382 : * @param status output param set to success/failure code on exit
383 : */
384 : void initializeData(const Locale& locale, UErrorCode& status);
385 :
386 :
387 : /* Set Interval pattern.
388 : *
389 : * It sets interval pattern into the hash map.
390 : *
391 : * @param skeleton skeleton on which the interval pattern based
392 : * @param lrgDiffCalUnit the largest different calendar unit.
393 : * @param intervalPattern the interval pattern on the largest different
394 : * calendar unit.
395 : * @param status output param set to success/failure code on exit
396 : */
397 : void setIntervalPatternInternally(const UnicodeString& skeleton,
398 : UCalendarDateFields lrgDiffCalUnit,
399 : const UnicodeString& intervalPattern,
400 : UErrorCode& status);
401 :
402 :
403 : /**given an input skeleton, get the best match skeleton
404 : * which has pre-defined interval pattern in resource file.
405 : * Also return the difference between the input skeleton
406 : * and the best match skeleton.
407 : *
408 : * TODO (xji): set field weight or
409 : * isolate the funtionality in DateTimePatternGenerator
410 : * @param skeleton input skeleton
411 : * @param bestMatchDistanceInfo the difference between input skeleton
412 : * and best match skeleton.
413 : * 0, if there is exact match for input skeleton
414 : * 1, if there is only field width difference between
415 : * the best match and the input skeleton
416 : * 2, the only field difference is 'v' and 'z'
417 : * -1, if there is calendar field difference between
418 : * the best match and the input skeleton
419 : * @return best match skeleton
420 : */
421 : const UnicodeString* getBestSkeleton(const UnicodeString& skeleton,
422 : int8_t& bestMatchDistanceInfo) const;
423 :
424 :
425 : /**
426 : * Parse skeleton, save each field's width.
427 : * It is used for looking for best match skeleton,
428 : * and adjust pattern field width.
429 : * @param skeleton skeleton to be parsed
430 : * @param skeletonFieldWidth parsed skeleton field width
431 : */
432 : static void U_EXPORT2 parseSkeleton(const UnicodeString& skeleton,
433 : int32_t* skeletonFieldWidth);
434 :
435 :
436 : /**
437 : * Check whether one field width is numeric while the other is string.
438 : *
439 : * TODO (xji): make it general
440 : *
441 : * @param fieldWidth one field width
442 : * @param anotherFieldWidth another field width
443 : * @param patternLetter pattern letter char
444 : * @return true if one field width is numeric and the other is string,
445 : * false otherwise.
446 : */
447 : static UBool U_EXPORT2 stringNumeric(int32_t fieldWidth,
448 : int32_t anotherFieldWidth,
449 : char patternLetter);
450 :
451 :
452 : /**
453 : * Convert calendar field to the interval pattern index in
454 : * hash table.
455 : *
456 : * Since we only support the following calendar fields:
457 : * ERA, YEAR, MONTH, DATE, DAY_OF_MONTH, DAY_OF_WEEK,
458 : * AM_PM, HOUR, HOUR_OF_DAY, and MINUTE,
459 : * We reserve only 4 interval patterns for a skeleton.
460 : *
461 : * @param field calendar field
462 : * @param status output param set to success/failure code on exit
463 : * @return interval pattern index in hash table
464 : */
465 : static IntervalPatternIndex U_EXPORT2 calendarFieldToIntervalIndex(
466 : UCalendarDateFields field,
467 : UErrorCode& status);
468 :
469 :
470 : /**
471 : * delete hash table (of type fIntervalPatterns).
472 : *
473 : * @param hTable hash table to be deleted
474 : */
475 : void deleteHash(Hashtable* hTable);
476 :
477 :
478 : /**
479 : * initialize hash table (of type fIntervalPatterns).
480 : *
481 : * @param status output param set to success/failure code on exit
482 : * @return hash table initialized
483 : */
484 : Hashtable* initHash(UErrorCode& status);
485 :
486 :
487 :
488 : /**
489 : * copy hash table (of type fIntervalPatterns).
490 : *
491 : * @param source the source to copy from
492 : * @param target the target to copy to
493 : * @param status output param set to success/failure code on exit
494 : */
495 : void copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status);
496 :
497 :
498 : // data members
499 : // fallback interval pattern
500 : UnicodeString fFallbackIntervalPattern;
501 : // default order
502 : UBool fFirstDateInPtnIsLaterDate;
503 :
504 : // HashMap<UnicodeString, UnicodeString[kIPI_MAX_INDEX]>
505 : // HashMap( skeleton, pattern[largest_different_field] )
506 : Hashtable* fIntervalPatterns;
507 :
508 : };// end class DateIntervalInfo
509 :
510 :
511 : inline UBool
512 0 : DateIntervalInfo::operator!=(const DateIntervalInfo& other) const {
513 0 : return !operator==(other);
514 : }
515 :
516 :
517 : U_NAMESPACE_END
518 :
519 : #endif
520 :
521 : #endif
522 :
|