1/*
2*******************************************************************************
3* Copyright (C) 2007-2015, International Business Machines Corporation and
4* others. All Rights Reserved.
5*******************************************************************************
6*
7* File DTPTNGEN.H
8*
9*******************************************************************************
10*/
11
12#ifndef __DTPTNGEN_H__
13#define __DTPTNGEN_H__
14
15#include "unicode/datefmt.h"
16#include "unicode/locid.h"
17#include "unicode/udat.h"
18#include "unicode/udatpg.h"
19
20U_NAMESPACE_BEGIN
21
22/**
23 * \file
24 * \brief C++ API: Date/Time Pattern Generator
25 */
26
27
28class Hashtable;
29class FormatParser;
30class DateTimeMatcher;
31class DistanceInfo;
32class PatternMap;
33class PtnSkeleton;
34class SharedDateTimePatternGenerator;
35
36/**
37 * This class provides flexible generation of date format patterns, like "yy-MM-dd".
38 * The user can build up the generator by adding successive patterns. Once that
39 * is done, a query can be made using a "skeleton", which is a pattern which just
40 * includes the desired fields and lengths. The generator will return the "best fit"
41 * pattern corresponding to that skeleton.
42 * <p>The main method people will use is getBestPattern(String skeleton),
43 * since normally this class is pre-built with data from a particular locale.
44 * However, generators can be built directly from other data as well.
45 * <p><i>Issue: may be useful to also have a function that returns the list of
46 * fields in a pattern, in order, since we have that internally.
47 * That would be useful for getting the UI order of field elements.</i>
48 * @stable ICU 3.8
49**/
50class U_I18N_API DateTimePatternGenerator : public UObject {
51public:
52    /**
53     * Construct a flexible generator according to default locale.
54     * @param status  Output param set to success/failure code on exit,
55     *               which must not indicate a failure before the function call.
56     * @stable ICU 3.8
57     */
58    static DateTimePatternGenerator* U_EXPORT2 createInstance(UErrorCode& status);
59
60    /**
61     * Construct a flexible generator according to data for a given locale.
62     * @param uLocale
63     * @param status  Output param set to success/failure code on exit,
64     *               which must not indicate a failure before the function call.
65     * @stable ICU 3.8
66     */
67    static DateTimePatternGenerator* U_EXPORT2 createInstance(const Locale& uLocale, UErrorCode& status);
68
69#ifndef U_HIDE_INTERNAL_API
70
71    /**
72     * For ICU use only
73     *
74     * @internal
75     */
76    static DateTimePatternGenerator* U_EXPORT2 internalMakeInstance(const Locale& uLocale, UErrorCode& status);
77
78#endif /* U_HIDE_INTERNAL_API */
79
80    /**
81     * Create an empty generator, to be constructed with addPattern(...) etc.
82     * @param status  Output param set to success/failure code on exit,
83     *               which must not indicate a failure before the function call.
84     * @stable ICU 3.8
85     */
86     static DateTimePatternGenerator* U_EXPORT2 createEmptyInstance(UErrorCode& status);
87
88    /**
89     * Destructor.
90     * @stable ICU 3.8
91     */
92    virtual ~DateTimePatternGenerator();
93
94    /**
95     * Clone DateTimePatternGenerator object. Clients are responsible for
96     * deleting the DateTimePatternGenerator object cloned.
97     * @stable ICU 3.8
98     */
99    DateTimePatternGenerator* clone() const;
100
101     /**
102      * Return true if another object is semantically equal to this one.
103      *
104      * @param other    the DateTimePatternGenerator object to be compared with.
105      * @return         true if other is semantically equal to this.
106      * @stable ICU 3.8
107      */
108    UBool operator==(const DateTimePatternGenerator& other) const;
109
110    /**
111     * Return true if another object is semantically unequal to this one.
112     *
113     * @param other    the DateTimePatternGenerator object to be compared with.
114     * @return         true if other is semantically unequal to this.
115     * @stable ICU 3.8
116     */
117    UBool operator!=(const DateTimePatternGenerator& other) const;
118
119#ifndef U_HIDE_DRAFT_API
120    /**
121     * Utility to return a unique skeleton from a given pattern. For example,
122     * both "MMM-dd" and "dd/MMM" produce the skeleton "MMMdd".
123     *
124     * @param pattern   Input pattern, such as "dd/MMM"
125     * @param status  Output param set to success/failure code on exit,
126     *                  which must not indicate a failure before the function call.
127     * @return skeleton such as "MMMdd"
128     * @draft ICU 56
129     */
130    static UnicodeString staticGetSkeleton(const UnicodeString& pattern, UErrorCode& status);
131#endif  /* U_HIDE_DRAFT_API */
132
133    /**
134     * Utility to return a unique skeleton from a given pattern. For example,
135     * both "MMM-dd" and "dd/MMM" produce the skeleton "MMMdd".
136     * getSkeleton() works exactly like staticGetSkeleton().
137     * Use staticGetSkeleton() instead of getSkeleton().
138     *
139     * @param pattern   Input pattern, such as "dd/MMM"
140     * @param status  Output param set to success/failure code on exit,
141     *                  which must not indicate a failure before the function call.
142     * @return skeleton such as "MMMdd"
143     * @stable ICU 3.8
144     */
145    UnicodeString getSkeleton(const UnicodeString& pattern, UErrorCode& status) {
146        return staticGetSkeleton(pattern, status);
147    }
148
149#ifndef U_HIDE_DRAFT_API
150    /**
151     * Utility to return a unique base skeleton from a given pattern. This is
152     * the same as the skeleton, except that differences in length are minimized
153     * so as to only preserve the difference between string and numeric form. So
154     * for example, both "MMM-dd" and "d/MMM" produce the skeleton "MMMd"
155     * (notice the single d).
156     *
157     * @param pattern  Input pattern, such as "dd/MMM"
158     * @param status  Output param set to success/failure code on exit,
159     *               which must not indicate a failure before the function call.
160     * @return base skeleton, such as "MMMd"
161     * @draft ICU 56
162     */
163    static UnicodeString staticGetBaseSkeleton(const UnicodeString& pattern, UErrorCode& status);
164#endif  /* U_HIDE_DRAFT_API */
165
166    /**
167     * Utility to return a unique base skeleton from a given pattern. This is
168     * the same as the skeleton, except that differences in length are minimized
169     * so as to only preserve the difference between string and numeric form. So
170     * for example, both "MMM-dd" and "d/MMM" produce the skeleton "MMMd"
171     * (notice the single d).
172     * getBaseSkeleton() works exactly like staticGetBaseSkeleton().
173     * Use staticGetBaseSkeleton() instead of getBaseSkeleton().
174     *
175     * @param pattern  Input pattern, such as "dd/MMM"
176     * @param status  Output param set to success/failure code on exit,
177     *               which must not indicate a failure before the function call.
178     * @return base skeleton, such as "MMMd"
179     * @stable ICU 3.8
180     */
181    UnicodeString getBaseSkeleton(const UnicodeString& pattern, UErrorCode& status) {
182        return staticGetBaseSkeleton(pattern, status);
183    }
184
185    /**
186     * Adds a pattern to the generator. If the pattern has the same skeleton as
187     * an existing pattern, and the override parameter is set, then the previous
188     * value is overriden. Otherwise, the previous value is retained. In either
189     * case, the conflicting status is set and previous vale is stored in
190     * conflicting pattern.
191     * <p>
192     * Note that single-field patterns (like "MMM") are automatically added, and
193     * don't need to be added explicitly!
194     *
195     * @param pattern   Input pattern, such as "dd/MMM"
196     * @param override  When existing values are to be overridden use true,
197     *                   otherwise use false.
198     * @param conflictingPattern  Previous pattern with the same skeleton.
199     * @param status  Output param set to success/failure code on exit,
200     *               which must not indicate a failure before the function call.
201     * @return conflicting status.  The value could be UDATPG_NO_CONFLICT,
202     *                             UDATPG_BASE_CONFLICT or UDATPG_CONFLICT.
203     * @stable ICU 3.8
204	 * <p>
205	 * <h4>Sample code</h4>
206	 * \snippet samples/dtptngsample/dtptngsample.cpp getBestPatternExample1
207	 * \snippet samples/dtptngsample/dtptngsample.cpp addPatternExample
208	 * <p>
209     */
210    UDateTimePatternConflict addPattern(const UnicodeString& pattern,
211                                        UBool override,
212                                        UnicodeString& conflictingPattern,
213                                        UErrorCode& status);
214
215    /**
216     * An AppendItem format is a pattern used to append a field if there is no
217     * good match. For example, suppose that the input skeleton is "GyyyyMMMd",
218     * and there is no matching pattern internally, but there is a pattern
219     * matching "yyyyMMMd", say "d-MM-yyyy". Then that pattern is used, plus the
220     * G. The way these two are conjoined is by using the AppendItemFormat for G
221     * (era). So if that value is, say "{0}, {1}" then the final resulting
222     * pattern is "d-MM-yyyy, G".
223     * <p>
224     * There are actually three available variables: {0} is the pattern so far,
225     * {1} is the element we are adding, and {2} is the name of the element.
226     * <p>
227     * This reflects the way that the CLDR data is organized.
228     *
229     * @param field  such as UDATPG_ERA_FIELD.
230     * @param value  pattern, such as "{0}, {1}"
231     * @stable ICU 3.8
232     */
233    void setAppendItemFormat(UDateTimePatternField field, const UnicodeString& value);
234
235    /**
236     * Getter corresponding to setAppendItemFormat. Values below 0 or at or
237     * above UDATPG_FIELD_COUNT are illegal arguments.
238     *
239     * @param  field  such as UDATPG_ERA_FIELD.
240     * @return append pattern for field
241     * @stable ICU 3.8
242     */
243    const UnicodeString& getAppendItemFormat(UDateTimePatternField field) const;
244
245    /**
246     * Sets the names of field, eg "era" in English for ERA. These are only
247     * used if the corresponding AppendItemFormat is used, and if it contains a
248     * {2} variable.
249     * <p>
250     * This reflects the way that the CLDR data is organized.
251     *
252     * @param field   such as UDATPG_ERA_FIELD.
253     * @param value   name of the field
254     * @stable ICU 3.8
255     */
256    void setAppendItemName(UDateTimePatternField field, const UnicodeString& value);
257
258    /**
259     * Getter corresponding to setAppendItemNames. Values below 0 or at or above
260     * UDATPG_FIELD_COUNT are illegal arguments.
261     *
262     * @param field  such as UDATPG_ERA_FIELD.
263     * @return name for field
264     * @stable ICU 3.8
265     */
266    const UnicodeString& getAppendItemName(UDateTimePatternField field) const;
267
268    /**
269     * The DateTimeFormat is a message format pattern used to compose date and
270     * time patterns. The default pattern in the root locale is "{1} {0}", where
271     * {1} will be replaced by the date pattern and {0} will be replaced by the
272     * time pattern; however, other locales may specify patterns such as
273     * "{1}, {0}" or "{1} 'at' {0}", etc.
274     * <p>
275     * This is used when the input skeleton contains both date and time fields,
276     * but there is not a close match among the added patterns. For example,
277     * suppose that this object was created by adding "dd-MMM" and "hh:mm", and
278     * its datetimeFormat is the default "{1} {0}". Then if the input skeleton
279     * is "MMMdhmm", there is not an exact match, so the input skeleton is
280     * broken up into two components "MMMd" and "hmm". There are close matches
281     * for those two skeletons, so the result is put together with this pattern,
282     * resulting in "d-MMM h:mm".
283     *
284     * @param dateTimeFormat
285     *            message format pattern, here {1} will be replaced by the date
286     *            pattern and {0} will be replaced by the time pattern.
287     * @stable ICU 3.8
288     */
289    void setDateTimeFormat(const UnicodeString& dateTimeFormat);
290
291    /**
292     * Getter corresponding to setDateTimeFormat.
293     * @return DateTimeFormat.
294     * @stable ICU 3.8
295     */
296    const UnicodeString& getDateTimeFormat() const;
297
298    /**
299     * Return the best pattern matching the input skeleton. It is guaranteed to
300     * have all of the fields in the skeleton.
301     *
302     * @param skeleton
303     *            The skeleton is a pattern containing only the variable fields.
304     *            For example, "MMMdd" and "mmhh" are skeletons.
305     * @param status  Output param set to success/failure code on exit,
306     *               which must not indicate a failure before the function call.
307     * @return bestPattern
308     *            The best pattern found from the given skeleton.
309     * @stable ICU 3.8
310	 * <p>
311	 * <h4>Sample code</h4>
312	 * \snippet samples/dtptngsample/dtptngsample.cpp getBestPatternExample1
313	 * \snippet samples/dtptngsample/dtptngsample.cpp getBestPatternExample
314	 * <p>
315     */
316     UnicodeString getBestPattern(const UnicodeString& skeleton, UErrorCode& status);
317
318
319    /**
320     * Return the best pattern matching the input skeleton. It is guaranteed to
321     * have all of the fields in the skeleton.
322     *
323     * @param skeleton
324     *            The skeleton is a pattern containing only the variable fields.
325     *            For example, "MMMdd" and "mmhh" are skeletons.
326     * @param options
327     *            Options for forcing the length of specified fields in the
328     *            returned pattern to match those in the skeleton (when this
329     *            would not happen otherwise). For default behavior, use
330     *            UDATPG_MATCH_NO_OPTIONS.
331     * @param status
332     *            Output param set to success/failure code on exit,
333     *            which must not indicate a failure before the function call.
334     * @return bestPattern
335     *            The best pattern found from the given skeleton.
336     * @stable ICU 4.4
337     */
338     UnicodeString getBestPattern(const UnicodeString& skeleton,
339                                  UDateTimePatternMatchOptions options,
340                                  UErrorCode& status);
341
342
343    /**
344     * Adjusts the field types (width and subtype) of a pattern to match what is
345     * in a skeleton. That is, if you supply a pattern like "d-M H:m", and a
346     * skeleton of "MMMMddhhmm", then the input pattern is adjusted to be
347     * "dd-MMMM hh:mm". This is used internally to get the best match for the
348     * input skeleton, but can also be used externally.
349     *
350     * @param pattern Input pattern
351     * @param skeleton
352     *            The skeleton is a pattern containing only the variable fields.
353     *            For example, "MMMdd" and "mmhh" are skeletons.
354     * @param status  Output param set to success/failure code on exit,
355     *               which must not indicate a failure before the function call.
356     * @return pattern adjusted to match the skeleton fields widths and subtypes.
357     * @stable ICU 3.8
358	 * <p>
359	 * <h4>Sample code</h4>
360	 * \snippet samples/dtptngsample/dtptngsample.cpp getBestPatternExample1
361	 * \snippet samples/dtptngsample/dtptngsample.cpp replaceFieldTypesExample
362	 * <p>
363     */
364     UnicodeString replaceFieldTypes(const UnicodeString& pattern,
365                                     const UnicodeString& skeleton,
366                                     UErrorCode& status);
367
368    /**
369     * Adjusts the field types (width and subtype) of a pattern to match what is
370     * in a skeleton. That is, if you supply a pattern like "d-M H:m", and a
371     * skeleton of "MMMMddhhmm", then the input pattern is adjusted to be
372     * "dd-MMMM hh:mm". This is used internally to get the best match for the
373     * input skeleton, but can also be used externally.
374     *
375     * @param pattern Input pattern
376     * @param skeleton
377     *            The skeleton is a pattern containing only the variable fields.
378     *            For example, "MMMdd" and "mmhh" are skeletons.
379     * @param options
380     *            Options controlling whether the length of specified fields in the
381     *            pattern are adjusted to match those in the skeleton (when this
382     *            would not happen otherwise). For default behavior, use
383     *            UDATPG_MATCH_NO_OPTIONS.
384     * @param status
385     *            Output param set to success/failure code on exit,
386     *            which must not indicate a failure before the function call.
387     * @return pattern adjusted to match the skeleton fields widths and subtypes.
388     * @stable ICU 4.4
389     */
390     UnicodeString replaceFieldTypes(const UnicodeString& pattern,
391                                     const UnicodeString& skeleton,
392                                     UDateTimePatternMatchOptions options,
393                                     UErrorCode& status);
394
395    /**
396     * Return a list of all the skeletons (in canonical form) from this class.
397     *
398     * Call getPatternForSkeleton() to get the corresponding pattern.
399     *
400     * @param status  Output param set to success/failure code on exit,
401     *               which must not indicate a failure before the function call.
402     * @return StringEnumeration with the skeletons.
403     *         The caller must delete the object.
404     * @stable ICU 3.8
405     */
406     StringEnumeration* getSkeletons(UErrorCode& status) const;
407
408     /**
409      * Get the pattern corresponding to a given skeleton.
410      * @param skeleton
411      * @return pattern corresponding to a given skeleton.
412      * @stable ICU 3.8
413      */
414     const UnicodeString& getPatternForSkeleton(const UnicodeString& skeleton) const;
415
416    /**
417     * Return a list of all the base skeletons (in canonical form) from this class.
418     *
419     * @param status  Output param set to success/failure code on exit,
420     *               which must not indicate a failure before the function call.
421     * @return a StringEnumeration with the base skeletons.
422     *         The caller must delete the object.
423     * @stable ICU 3.8
424     */
425     StringEnumeration* getBaseSkeletons(UErrorCode& status) const;
426
427#ifndef U_HIDE_INTERNAL_API
428     /**
429      * Return a list of redundant patterns are those which if removed, make no
430      * difference in the resulting getBestPattern values. This method returns a
431      * list of them, to help check the consistency of the patterns used to build
432      * this generator.
433      *
434      * @param status  Output param set to success/failure code on exit,
435      *               which must not indicate a failure before the function call.
436      * @return a StringEnumeration with the redundant pattern.
437      *         The caller must delete the object.
438      * @internal ICU 3.8
439      */
440     StringEnumeration* getRedundants(UErrorCode& status);
441#endif  /* U_HIDE_INTERNAL_API */
442
443    /**
444     * The decimal value is used in formatting fractions of seconds. If the
445     * skeleton contains fractional seconds, then this is used with the
446     * fractional seconds. For example, suppose that the input pattern is
447     * "hhmmssSSSS", and the best matching pattern internally is "H:mm:ss", and
448     * the decimal string is ",". Then the resulting pattern is modified to be
449     * "H:mm:ss,SSSS"
450     *
451     * @param decimal
452     * @stable ICU 3.8
453     */
454    void setDecimal(const UnicodeString& decimal);
455
456    /**
457     * Getter corresponding to setDecimal.
458     * @return UnicodeString corresponding to the decimal point
459     * @stable ICU 3.8
460     */
461    const UnicodeString& getDecimal() const;
462
463    /**
464     * ICU "poor man's RTTI", returns a UClassID for the actual class.
465     *
466     * @stable ICU 3.8
467     */
468    virtual UClassID getDynamicClassID() const;
469
470    /**
471     * ICU "poor man's RTTI", returns a UClassID for this class.
472     *
473     * @stable ICU 3.8
474     */
475    static UClassID U_EXPORT2 getStaticClassID(void);
476
477private:
478    /**
479     * Constructor.
480     * @stable ICU 3.8
481     */
482    DateTimePatternGenerator(UErrorCode & status);
483
484    /**
485     * Constructor.
486     * @stable ICU 3.8
487     */
488    DateTimePatternGenerator(const Locale& locale, UErrorCode & status);
489
490    /**
491     * Copy constructor.
492     * @param other DateTimePatternGenerator to copy
493     * @stable ICU 3.8
494     */
495    DateTimePatternGenerator(const DateTimePatternGenerator& other);
496
497    /**
498     * Default assignment operator.
499     * @param other DateTimePatternGenerator to copy
500     * @stable ICU 3.8
501     */
502    DateTimePatternGenerator& operator=(const DateTimePatternGenerator& other);
503
504    Locale pLocale;  // pattern locale
505    FormatParser *fp;
506    DateTimeMatcher* dtMatcher;
507    DistanceInfo *distanceInfo;
508    PatternMap *patternMap;
509    UnicodeString appendItemFormats[UDATPG_FIELD_COUNT];
510    UnicodeString appendItemNames[UDATPG_FIELD_COUNT];
511    UnicodeString dateTimeFormat;
512    UnicodeString decimal;
513    DateTimeMatcher *skipMatcher;
514    Hashtable *fAvailableFormatKeyHash;
515    UnicodeString hackPattern;
516    UnicodeString emptyString;
517    UChar fDefaultHourFormatChar;
518
519    /* internal flags masks for adjustFieldTypes etc. */
520    enum {
521        kDTPGNoFlags = 0,
522        kDTPGFixFractionalSeconds = 1,
523        kDTPGSkeletonUsesCapJ = 2
524    };
525
526    void initData(const Locale &locale, UErrorCode &status);
527    void addCanonicalItems();
528    void addICUPatterns(const Locale& locale, UErrorCode& status);
529    void hackTimes(const UnicodeString& hackPattern, UErrorCode& status);
530    void addCLDRData(const Locale& locale, UErrorCode& status);
531    UDateTimePatternConflict addPatternWithSkeleton(const UnicodeString& pattern, const UnicodeString * skeletonToUse, UBool override, UnicodeString& conflictingPattern, UErrorCode& status);
532    void initHashtable(UErrorCode& status);
533    void setDateTimeFromCalendar(const Locale& locale, UErrorCode& status);
534    void setDecimalSymbols(const Locale& locale, UErrorCode& status);
535    UDateTimePatternField getAppendFormatNumber(const char* field) const;
536    UDateTimePatternField getAppendNameNumber(const char* field) const;
537    void getAppendName(UDateTimePatternField field, UnicodeString& value);
538    int32_t getCanonicalIndex(const UnicodeString& field);
539    const UnicodeString* getBestRaw(DateTimeMatcher& source, int32_t includeMask, DistanceInfo* missingFields, const PtnSkeleton** specifiedSkeletonPtr = 0);
540    UnicodeString adjustFieldTypes(const UnicodeString& pattern, const PtnSkeleton* specifiedSkeleton, int32_t flags, UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS);
541    UnicodeString getBestAppending(int32_t missingFields, int32_t flags, UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS);
542    int32_t getTopBitNumber(int32_t foundMask);
543    void setAvailableFormat(const UnicodeString &key, UErrorCode& status);
544    UBool isAvailableFormatSet(const UnicodeString &key) const;
545    void copyHashtable(Hashtable *other, UErrorCode &status);
546    UBool isCanonicalItem(const UnicodeString& item) const;
547} ;// end class DateTimePatternGenerator
548
549U_NAMESPACE_END
550
551#endif
552