]>
git.saurik.com Git - apple/icu.git/blob - icuSources/i18n/datefmt.cpp
2 *******************************************************************************
3 * Copyright (C) 1997-2011, International Business Machines Corporation and *
4 * others. All Rights Reserved. *
5 *******************************************************************************
9 * Modification History:
11 * Date Name Description
12 * 02/19/97 aliu Converted from java.
13 * 03/31/97 aliu Modified extensively to work with 50 locales.
14 * 04/01/97 aliu Added support for centuries.
15 * 08/12/97 aliu Fixed operator== to use Calendar::equivalentTo.
16 * 07/20/98 stephen Changed ParsePosition initialization
17 ********************************************************************************
20 #include "unicode/utypes.h"
22 #if !UCONFIG_NO_FORMATTING
24 #include "unicode/ures.h"
25 #include "unicode/datefmt.h"
26 #include "unicode/smpdtfmt.h"
27 #include "unicode/dtptngen.h"
33 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
37 // *****************************************************************************
39 // *****************************************************************************
43 DateFormat::DateFormat()
49 //----------------------------------------------------------------------
51 DateFormat::DateFormat(const DateFormat
& other
)
59 //----------------------------------------------------------------------
61 DateFormat
& DateFormat::operator=(const DateFormat
& other
)
68 fCalendar
= other
.fCalendar
->clone();
72 if(other
.fNumberFormat
) {
73 fNumberFormat
= (NumberFormat
*)other
.fNumberFormat
->clone();
81 //----------------------------------------------------------------------
83 DateFormat::~DateFormat()
89 //----------------------------------------------------------------------
92 DateFormat::operator==(const Format
& other
) const
94 // This protected comparison operator should only be called by subclasses
95 // which have confirmed that the other object being compared against is
96 // an instance of a sublcass of DateFormat. THIS IS IMPORTANT.
98 // Format::operator== guarantees that this cast is safe
99 DateFormat
* fmt
= (DateFormat
*)&other
;
101 return (this == fmt
) ||
102 (Format::operator==(other
) &&
103 fCalendar
&&(fCalendar
->isEquivalentTo(*fmt
->fCalendar
)) &&
104 (fNumberFormat
&& *fNumberFormat
== *fmt
->fNumberFormat
));
107 //----------------------------------------------------------------------
110 DateFormat::format(const Formattable
& obj
,
111 UnicodeString
& appendTo
,
112 FieldPosition
& fieldPosition
,
113 UErrorCode
& status
) const
115 if (U_FAILURE(status
)) return appendTo
;
117 // if the type of the Formattable is double or long, treat it as if it were a Date
119 switch (obj
.getType())
121 case Formattable::kDate
:
122 date
= obj
.getDate();
124 case Formattable::kDouble
:
125 date
= (UDate
)obj
.getDouble();
127 case Formattable::kLong
:
128 date
= (UDate
)obj
.getLong();
131 status
= U_ILLEGAL_ARGUMENT_ERROR
;
136 //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
137 // status = U_ILLEGAL_ARGUMENT_ERROR;
139 return format(date
, appendTo
, fieldPosition
);
142 //----------------------------------------------------------------------
145 DateFormat::format(const Formattable
& obj
,
146 UnicodeString
& appendTo
,
147 FieldPositionIterator
* posIter
,
148 UErrorCode
& status
) const
150 if (U_FAILURE(status
)) return appendTo
;
152 // if the type of the Formattable is double or long, treat it as if it were a Date
154 switch (obj
.getType())
156 case Formattable::kDate
:
157 date
= obj
.getDate();
159 case Formattable::kDouble
:
160 date
= (UDate
)obj
.getDouble();
162 case Formattable::kLong
:
163 date
= (UDate
)obj
.getLong();
166 status
= U_ILLEGAL_ARGUMENT_ERROR
;
171 //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
172 // status = U_ILLEGAL_ARGUMENT_ERROR;
174 return format(date
, appendTo
, posIter
, status
);
177 //----------------------------------------------------------------------
179 // Default implementation for backwards compatibility, subclasses should implement.
181 DateFormat::format(Calendar
& /* unused cal */,
182 UnicodeString
& appendTo
,
183 FieldPositionIterator
* /* unused posIter */,
184 UErrorCode
& status
) const {
185 if (U_SUCCESS(status
)) {
186 status
= U_UNSUPPORTED_ERROR
;
191 //----------------------------------------------------------------------
194 DateFormat::format(UDate date
, UnicodeString
& appendTo
, FieldPosition
& fieldPosition
) const {
195 if (fCalendar
!= NULL
) {
196 // Use a clone of our calendar instance
197 Calendar
* calClone
= fCalendar
->clone();
198 if (calClone
!= NULL
) {
199 UErrorCode ec
= U_ZERO_ERROR
;
200 calClone
->setTime(date
, ec
);
202 format(*calClone
, appendTo
, fieldPosition
);
210 //----------------------------------------------------------------------
213 DateFormat::format(UDate date
, UnicodeString
& appendTo
, FieldPositionIterator
* posIter
,
214 UErrorCode
& status
) const {
215 if (fCalendar
!= NULL
) {
216 Calendar
* calClone
= fCalendar
->clone();
217 if (calClone
!= NULL
) {
218 calClone
->setTime(date
, status
);
219 if (U_SUCCESS(status
)) {
220 format(*calClone
, appendTo
, posIter
, status
);
228 //----------------------------------------------------------------------
231 DateFormat::format(UDate date
, UnicodeString
& appendTo
) const
233 // Note that any error information is just lost. That's okay
234 // for this convenience method.
235 FieldPosition
fpos(0);
236 return format(date
, appendTo
, fpos
);
239 //----------------------------------------------------------------------
242 DateFormat::parse(const UnicodeString
& text
,
243 ParsePosition
& pos
) const
245 UDate d
= 0; // Error return UDate is 0 (the epoch)
246 if (fCalendar
!= NULL
) {
247 Calendar
* calClone
= fCalendar
->clone();
248 if (calClone
!= NULL
) {
249 int32_t start
= pos
.getIndex();
251 parse(text
, *calClone
, pos
);
252 if (pos
.getIndex() != start
) {
253 UErrorCode ec
= U_ZERO_ERROR
;
254 d
= calClone
->getTime(ec
);
256 // We arrive here if fCalendar => calClone is non-lenient and
257 // there is an out-of-range field. We don't know which field
258 // was illegal so we set the error index to the start.
260 pos
.setErrorIndex(start
);
270 //----------------------------------------------------------------------
273 DateFormat::parse(const UnicodeString
& text
,
274 UErrorCode
& status
) const
276 if (U_FAILURE(status
)) return 0;
278 ParsePosition
pos(0);
279 UDate result
= parse(text
, pos
);
280 if (pos
.getIndex() == 0) {
281 #if defined (U_DEBUG_CAL)
282 fprintf(stderr
, "%s:%d - - failed to parse - err index %d\n"
283 , __FILE__
, __LINE__
, pos
.getErrorIndex() );
285 status
= U_ILLEGAL_ARGUMENT_ERROR
;
290 //----------------------------------------------------------------------
293 DateFormat::parseObject(const UnicodeString
& source
,
295 ParsePosition
& pos
) const
297 result
.setDate(parse(source
, pos
));
300 //----------------------------------------------------------------------
302 DateFormat
* U_EXPORT2
303 DateFormat::createTimeInstance(DateFormat::EStyle style
,
304 const Locale
& aLocale
)
306 return create(style
, kNone
, aLocale
);
309 //----------------------------------------------------------------------
311 DateFormat
* U_EXPORT2
312 DateFormat::createDateInstance(DateFormat::EStyle style
,
313 const Locale
& aLocale
)
315 // +4 to set the correct index for getting data out of
319 style
= (EStyle
) (style
+ kDateOffset
);
321 return create(kNone
, (EStyle
) (style
), aLocale
);
324 //----------------------------------------------------------------------
326 DateFormat
* U_EXPORT2
327 DateFormat::createDateTimeInstance(EStyle dateStyle
,
329 const Locale
& aLocale
)
331 if(dateStyle
!= kNone
)
333 dateStyle
= (EStyle
) (dateStyle
+ kDateOffset
);
335 return create(timeStyle
, dateStyle
, aLocale
);
338 //----------------------------------------------------------------------
340 DateFormat
* U_EXPORT2
341 DateFormat::createInstance()
343 return create(kShort
, (EStyle
) (kShort
+ kDateOffset
), Locale::getDefault());
346 //----------------------------------------------------------------------
348 DateFormat
* U_EXPORT2
349 DateFormat::create(EStyle timeStyle
, EStyle dateStyle
, const Locale
& locale
)
351 UErrorCode status
= U_ZERO_ERROR
;
352 #if U_PLATFORM_HAS_WIN32_API
354 int32_t count
= locale
.getKeywordValue("compat", buffer
, sizeof(buffer
), status
);
356 // if the locale has "@compat=host", create a host-specific DateFormat...
357 if (count
> 0 && uprv_strcmp(buffer
, "host") == 0) {
358 Win32DateFormat
*f
= new Win32DateFormat(timeStyle
, dateStyle
, locale
, status
);
360 if (U_SUCCESS(status
)) {
369 if(/*((timeStyle!=UDAT_NONE)&&(timeStyle & UDAT_RELATIVE)) || */((dateStyle
!=kNone
)&&((dateStyle
-kDateOffset
) & UDAT_RELATIVE
))) {
370 RelativeDateFormat
*r
= new RelativeDateFormat((UDateFormatStyle
)timeStyle
, (UDateFormatStyle
)(dateStyle
-kDateOffset
), locale
, status
);
371 if(U_SUCCESS(status
)) return r
;
373 status
= U_ZERO_ERROR
;
376 // Try to create a SimpleDateFormat of the desired style.
377 SimpleDateFormat
*f
= new SimpleDateFormat(timeStyle
, dateStyle
, locale
, status
);
378 if (U_SUCCESS(status
)) return f
;
381 // If that fails, try to create a format using the default pattern and
382 // the DateFormatSymbols for this locale.
383 status
= U_ZERO_ERROR
;
384 f
= new SimpleDateFormat(locale
, status
);
385 if (U_SUCCESS(status
)) return f
;
388 // This should never really happen, because the preceding constructor
389 // should always succeed. If the resource data is unavailable, a last
390 // resort object should be returned.
394 //----------------------------------------------------------------------
396 const Locale
* U_EXPORT2
397 DateFormat::getAvailableLocales(int32_t& count
)
399 // Get the list of installed locales.
400 // Even if root has the correct date format for this locale,
401 // it's still a valid locale (we don't worry about data fallbacks).
402 return Locale::getAvailableLocales(count
);
405 //----------------------------------------------------------------------
408 DateFormat::adoptCalendar(Calendar
* newCalendar
)
411 fCalendar
= newCalendar
;
414 //----------------------------------------------------------------------
416 DateFormat::setCalendar(const Calendar
& newCalendar
)
418 Calendar
* newCalClone
= newCalendar
.clone();
419 if (newCalClone
!= NULL
) {
420 adoptCalendar(newCalClone
);
424 //----------------------------------------------------------------------
427 DateFormat::getCalendar() const
432 //----------------------------------------------------------------------
435 DateFormat::adoptNumberFormat(NumberFormat
* newNumberFormat
)
437 delete fNumberFormat
;
438 fNumberFormat
= newNumberFormat
;
439 newNumberFormat
->setParseIntegerOnly(TRUE
);
441 //----------------------------------------------------------------------
444 DateFormat::setNumberFormat(const NumberFormat
& newNumberFormat
)
446 NumberFormat
* newNumFmtClone
= (NumberFormat
*)newNumberFormat
.clone();
447 if (newNumFmtClone
!= NULL
) {
448 adoptNumberFormat(newNumFmtClone
);
452 //----------------------------------------------------------------------
455 DateFormat::getNumberFormat() const
457 return fNumberFormat
;
460 //----------------------------------------------------------------------
463 DateFormat::adoptTimeZone(TimeZone
* zone
)
465 if (fCalendar
!= NULL
) {
466 fCalendar
->adoptTimeZone(zone
);
469 //----------------------------------------------------------------------
472 DateFormat::setTimeZone(const TimeZone
& zone
)
474 if (fCalendar
!= NULL
) {
475 fCalendar
->setTimeZone(zone
);
479 //----------------------------------------------------------------------
482 DateFormat::getTimeZone() const
484 if (fCalendar
!= NULL
) {
485 return fCalendar
->getTimeZone();
487 // If calendar doesn't exists, create default timezone.
488 // fCalendar is rarely null
489 return *(TimeZone::createDefault());
492 //----------------------------------------------------------------------
495 DateFormat::setLenient(UBool lenient
)
497 if (fCalendar
!= NULL
) {
498 fCalendar
->setLenient(lenient
);
502 //----------------------------------------------------------------------
505 DateFormat::isLenient() const
507 if (fCalendar
!= NULL
) {
508 return fCalendar
->isLenient();
510 // fCalendar is rarely null
516 #endif /* #if !UCONFIG_NO_FORMATTING */