intl/icu/source/i18n/datefmt.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 *******************************************************************************
michael@0 3 * Copyright (C) 1997-2013, International Business Machines Corporation and *
michael@0 4 * others. All Rights Reserved. *
michael@0 5 *******************************************************************************
michael@0 6 *
michael@0 7 * File DATEFMT.CPP
michael@0 8 *
michael@0 9 * Modification History:
michael@0 10 *
michael@0 11 * Date Name Description
michael@0 12 * 02/19/97 aliu Converted from java.
michael@0 13 * 03/31/97 aliu Modified extensively to work with 50 locales.
michael@0 14 * 04/01/97 aliu Added support for centuries.
michael@0 15 * 08/12/97 aliu Fixed operator== to use Calendar::equivalentTo.
michael@0 16 * 07/20/98 stephen Changed ParsePosition initialization
michael@0 17 ********************************************************************************
michael@0 18 */
michael@0 19
michael@0 20 #include "unicode/utypes.h"
michael@0 21
michael@0 22 #if !UCONFIG_NO_FORMATTING
michael@0 23
michael@0 24 #include "unicode/ures.h"
michael@0 25 #include "unicode/datefmt.h"
michael@0 26 #include "unicode/smpdtfmt.h"
michael@0 27 #include "unicode/dtptngen.h"
michael@0 28 #include "reldtfmt.h"
michael@0 29
michael@0 30 #include "cstring.h"
michael@0 31 #include "windtfmt.h"
michael@0 32
michael@0 33 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
michael@0 34 #include <stdio.h>
michael@0 35 #endif
michael@0 36
michael@0 37 // *****************************************************************************
michael@0 38 // class DateFormat
michael@0 39 // *****************************************************************************
michael@0 40
michael@0 41 U_NAMESPACE_BEGIN
michael@0 42
michael@0 43 DateFormat::DateFormat()
michael@0 44 : fCalendar(0),
michael@0 45 fNumberFormat(0)
michael@0 46 {
michael@0 47 }
michael@0 48
michael@0 49 //----------------------------------------------------------------------
michael@0 50
michael@0 51 DateFormat::DateFormat(const DateFormat& other)
michael@0 52 : Format(other),
michael@0 53 fCalendar(0),
michael@0 54 fNumberFormat(0)
michael@0 55 {
michael@0 56 *this = other;
michael@0 57 }
michael@0 58
michael@0 59 //----------------------------------------------------------------------
michael@0 60
michael@0 61 DateFormat& DateFormat::operator=(const DateFormat& other)
michael@0 62 {
michael@0 63 if (this != &other)
michael@0 64 {
michael@0 65 delete fCalendar;
michael@0 66 delete fNumberFormat;
michael@0 67 if(other.fCalendar) {
michael@0 68 fCalendar = other.fCalendar->clone();
michael@0 69 } else {
michael@0 70 fCalendar = NULL;
michael@0 71 }
michael@0 72 if(other.fNumberFormat) {
michael@0 73 fNumberFormat = (NumberFormat*)other.fNumberFormat->clone();
michael@0 74 } else {
michael@0 75 fNumberFormat = NULL;
michael@0 76 }
michael@0 77 fBoolFlags = other.fBoolFlags;
michael@0 78 }
michael@0 79 return *this;
michael@0 80 }
michael@0 81
michael@0 82 //----------------------------------------------------------------------
michael@0 83
michael@0 84 DateFormat::~DateFormat()
michael@0 85 {
michael@0 86 delete fCalendar;
michael@0 87 delete fNumberFormat;
michael@0 88 }
michael@0 89
michael@0 90 //----------------------------------------------------------------------
michael@0 91
michael@0 92 UBool
michael@0 93 DateFormat::operator==(const Format& other) const
michael@0 94 {
michael@0 95 // This protected comparison operator should only be called by subclasses
michael@0 96 // which have confirmed that the other object being compared against is
michael@0 97 // an instance of a sublcass of DateFormat. THIS IS IMPORTANT.
michael@0 98
michael@0 99 // Format::operator== guarantees that this cast is safe
michael@0 100 DateFormat* fmt = (DateFormat*)&other;
michael@0 101
michael@0 102 return (this == fmt) ||
michael@0 103 (Format::operator==(other) &&
michael@0 104 fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) &&
michael@0 105 (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat));
michael@0 106 }
michael@0 107
michael@0 108 //----------------------------------------------------------------------
michael@0 109
michael@0 110 UnicodeString&
michael@0 111 DateFormat::format(const Formattable& obj,
michael@0 112 UnicodeString& appendTo,
michael@0 113 FieldPosition& fieldPosition,
michael@0 114 UErrorCode& status) const
michael@0 115 {
michael@0 116 if (U_FAILURE(status)) return appendTo;
michael@0 117
michael@0 118 // if the type of the Formattable is double or long, treat it as if it were a Date
michael@0 119 UDate date = 0;
michael@0 120 switch (obj.getType())
michael@0 121 {
michael@0 122 case Formattable::kDate:
michael@0 123 date = obj.getDate();
michael@0 124 break;
michael@0 125 case Formattable::kDouble:
michael@0 126 date = (UDate)obj.getDouble();
michael@0 127 break;
michael@0 128 case Formattable::kLong:
michael@0 129 date = (UDate)obj.getLong();
michael@0 130 break;
michael@0 131 default:
michael@0 132 status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 133 return appendTo;
michael@0 134 }
michael@0 135
michael@0 136 // Is this right?
michael@0 137 //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
michael@0 138 // status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 139
michael@0 140 return format(date, appendTo, fieldPosition);
michael@0 141 }
michael@0 142
michael@0 143 //----------------------------------------------------------------------
michael@0 144
michael@0 145 UnicodeString&
michael@0 146 DateFormat::format(const Formattable& obj,
michael@0 147 UnicodeString& appendTo,
michael@0 148 FieldPositionIterator* posIter,
michael@0 149 UErrorCode& status) const
michael@0 150 {
michael@0 151 if (U_FAILURE(status)) return appendTo;
michael@0 152
michael@0 153 // if the type of the Formattable is double or long, treat it as if it were a Date
michael@0 154 UDate date = 0;
michael@0 155 switch (obj.getType())
michael@0 156 {
michael@0 157 case Formattable::kDate:
michael@0 158 date = obj.getDate();
michael@0 159 break;
michael@0 160 case Formattable::kDouble:
michael@0 161 date = (UDate)obj.getDouble();
michael@0 162 break;
michael@0 163 case Formattable::kLong:
michael@0 164 date = (UDate)obj.getLong();
michael@0 165 break;
michael@0 166 default:
michael@0 167 status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 168 return appendTo;
michael@0 169 }
michael@0 170
michael@0 171 // Is this right?
michael@0 172 //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex())
michael@0 173 // status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 174
michael@0 175 return format(date, appendTo, posIter, status);
michael@0 176 }
michael@0 177
michael@0 178 //----------------------------------------------------------------------
michael@0 179
michael@0 180 // Default implementation for backwards compatibility, subclasses should implement.
michael@0 181 UnicodeString&
michael@0 182 DateFormat::format(Calendar& /* unused cal */,
michael@0 183 UnicodeString& appendTo,
michael@0 184 FieldPositionIterator* /* unused posIter */,
michael@0 185 UErrorCode& status) const {
michael@0 186 if (U_SUCCESS(status)) {
michael@0 187 status = U_UNSUPPORTED_ERROR;
michael@0 188 }
michael@0 189 return appendTo;
michael@0 190 }
michael@0 191
michael@0 192 //----------------------------------------------------------------------
michael@0 193
michael@0 194 UnicodeString&
michael@0 195 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const {
michael@0 196 if (fCalendar != NULL) {
michael@0 197 // Use a clone of our calendar instance
michael@0 198 Calendar* calClone = fCalendar->clone();
michael@0 199 if (calClone != NULL) {
michael@0 200 UErrorCode ec = U_ZERO_ERROR;
michael@0 201 calClone->setTime(date, ec);
michael@0 202 if (U_SUCCESS(ec)) {
michael@0 203 format(*calClone, appendTo, fieldPosition);
michael@0 204 }
michael@0 205 delete calClone;
michael@0 206 }
michael@0 207 }
michael@0 208 return appendTo;
michael@0 209 }
michael@0 210
michael@0 211 //----------------------------------------------------------------------
michael@0 212
michael@0 213 UnicodeString&
michael@0 214 DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator* posIter,
michael@0 215 UErrorCode& status) const {
michael@0 216 if (fCalendar != NULL) {
michael@0 217 Calendar* calClone = fCalendar->clone();
michael@0 218 if (calClone != NULL) {
michael@0 219 calClone->setTime(date, status);
michael@0 220 if (U_SUCCESS(status)) {
michael@0 221 format(*calClone, appendTo, posIter, status);
michael@0 222 }
michael@0 223 delete calClone;
michael@0 224 }
michael@0 225 }
michael@0 226 return appendTo;
michael@0 227 }
michael@0 228
michael@0 229 //----------------------------------------------------------------------
michael@0 230
michael@0 231 UnicodeString&
michael@0 232 DateFormat::format(UDate date, UnicodeString& appendTo) const
michael@0 233 {
michael@0 234 // Note that any error information is just lost. That's okay
michael@0 235 // for this convenience method.
michael@0 236 FieldPosition fpos(0);
michael@0 237 return format(date, appendTo, fpos);
michael@0 238 }
michael@0 239
michael@0 240 //----------------------------------------------------------------------
michael@0 241
michael@0 242 UDate
michael@0 243 DateFormat::parse(const UnicodeString& text,
michael@0 244 ParsePosition& pos) const
michael@0 245 {
michael@0 246 UDate d = 0; // Error return UDate is 0 (the epoch)
michael@0 247 if (fCalendar != NULL) {
michael@0 248 Calendar* calClone = fCalendar->clone();
michael@0 249 if (calClone != NULL) {
michael@0 250 int32_t start = pos.getIndex();
michael@0 251 calClone->clear();
michael@0 252 parse(text, *calClone, pos);
michael@0 253 if (pos.getIndex() != start) {
michael@0 254 UErrorCode ec = U_ZERO_ERROR;
michael@0 255 d = calClone->getTime(ec);
michael@0 256 if (U_FAILURE(ec)) {
michael@0 257 // We arrive here if fCalendar => calClone is non-lenient and
michael@0 258 // there is an out-of-range field. We don't know which field
michael@0 259 // was illegal so we set the error index to the start.
michael@0 260 pos.setIndex(start);
michael@0 261 pos.setErrorIndex(start);
michael@0 262 d = 0;
michael@0 263 }
michael@0 264 }
michael@0 265 delete calClone;
michael@0 266 }
michael@0 267 }
michael@0 268 return d;
michael@0 269 }
michael@0 270
michael@0 271 //----------------------------------------------------------------------
michael@0 272
michael@0 273 UDate
michael@0 274 DateFormat::parse(const UnicodeString& text,
michael@0 275 UErrorCode& status) const
michael@0 276 {
michael@0 277 if (U_FAILURE(status)) return 0;
michael@0 278
michael@0 279 ParsePosition pos(0);
michael@0 280 UDate result = parse(text, pos);
michael@0 281 if (pos.getIndex() == 0) {
michael@0 282 #if defined (U_DEBUG_CAL)
michael@0 283 fprintf(stderr, "%s:%d - - failed to parse - err index %d\n"
michael@0 284 , __FILE__, __LINE__, pos.getErrorIndex() );
michael@0 285 #endif
michael@0 286 status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 287 }
michael@0 288 return result;
michael@0 289 }
michael@0 290
michael@0 291 //----------------------------------------------------------------------
michael@0 292
michael@0 293 void
michael@0 294 DateFormat::parseObject(const UnicodeString& source,
michael@0 295 Formattable& result,
michael@0 296 ParsePosition& pos) const
michael@0 297 {
michael@0 298 result.setDate(parse(source, pos));
michael@0 299 }
michael@0 300
michael@0 301 //----------------------------------------------------------------------
michael@0 302
michael@0 303 DateFormat* U_EXPORT2
michael@0 304 DateFormat::createTimeInstance(DateFormat::EStyle style,
michael@0 305 const Locale& aLocale)
michael@0 306 {
michael@0 307 return create(style, kNone, aLocale);
michael@0 308 }
michael@0 309
michael@0 310 //----------------------------------------------------------------------
michael@0 311
michael@0 312 DateFormat* U_EXPORT2
michael@0 313 DateFormat::createDateInstance(DateFormat::EStyle style,
michael@0 314 const Locale& aLocale)
michael@0 315 {
michael@0 316 // +4 to set the correct index for getting data out of
michael@0 317 // LocaleElements.
michael@0 318 if(style != kNone)
michael@0 319 {
michael@0 320 style = (EStyle) (style + kDateOffset);
michael@0 321 }
michael@0 322 return create(kNone, (EStyle) (style), aLocale);
michael@0 323 }
michael@0 324
michael@0 325 //----------------------------------------------------------------------
michael@0 326
michael@0 327 DateFormat* U_EXPORT2
michael@0 328 DateFormat::createDateTimeInstance(EStyle dateStyle,
michael@0 329 EStyle timeStyle,
michael@0 330 const Locale& aLocale)
michael@0 331 {
michael@0 332 if(dateStyle != kNone)
michael@0 333 {
michael@0 334 dateStyle = (EStyle) (dateStyle + kDateOffset);
michael@0 335 }
michael@0 336 return create(timeStyle, dateStyle, aLocale);
michael@0 337 }
michael@0 338
michael@0 339 //----------------------------------------------------------------------
michael@0 340
michael@0 341 DateFormat* U_EXPORT2
michael@0 342 DateFormat::createInstance()
michael@0 343 {
michael@0 344 return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault());
michael@0 345 }
michael@0 346
michael@0 347 //----------------------------------------------------------------------
michael@0 348
michael@0 349 DateFormat* U_EXPORT2
michael@0 350 DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale)
michael@0 351 {
michael@0 352 UErrorCode status = U_ZERO_ERROR;
michael@0 353 #if U_PLATFORM_HAS_WIN32_API
michael@0 354 char buffer[8];
michael@0 355 int32_t count = locale.getKeywordValue("compat", buffer, sizeof(buffer), status);
michael@0 356
michael@0 357 // if the locale has "@compat=host", create a host-specific DateFormat...
michael@0 358 if (count > 0 && uprv_strcmp(buffer, "host") == 0) {
michael@0 359 Win32DateFormat *f = new Win32DateFormat(timeStyle, dateStyle, locale, status);
michael@0 360
michael@0 361 if (U_SUCCESS(status)) {
michael@0 362 return f;
michael@0 363 }
michael@0 364
michael@0 365 delete f;
michael@0 366 }
michael@0 367 #endif
michael@0 368
michael@0 369 // is it relative?
michael@0 370 if(/*((timeStyle!=UDAT_NONE)&&(timeStyle & UDAT_RELATIVE)) || */((dateStyle!=kNone)&&((dateStyle-kDateOffset) & UDAT_RELATIVE))) {
michael@0 371 RelativeDateFormat *r = new RelativeDateFormat((UDateFormatStyle)timeStyle, (UDateFormatStyle)(dateStyle-kDateOffset), locale, status);
michael@0 372 if(U_SUCCESS(status)) return r;
michael@0 373 delete r;
michael@0 374 status = U_ZERO_ERROR;
michael@0 375 }
michael@0 376
michael@0 377 // Try to create a SimpleDateFormat of the desired style.
michael@0 378 SimpleDateFormat *f = new SimpleDateFormat(timeStyle, dateStyle, locale, status);
michael@0 379 if (U_SUCCESS(status)) return f;
michael@0 380 delete f;
michael@0 381
michael@0 382 // If that fails, try to create a format using the default pattern and
michael@0 383 // the DateFormatSymbols for this locale.
michael@0 384 status = U_ZERO_ERROR;
michael@0 385 f = new SimpleDateFormat(locale, status);
michael@0 386 if (U_SUCCESS(status)) return f;
michael@0 387 delete f;
michael@0 388
michael@0 389 // This should never really happen, because the preceding constructor
michael@0 390 // should always succeed. If the resource data is unavailable, a last
michael@0 391 // resort object should be returned.
michael@0 392 return 0;
michael@0 393 }
michael@0 394
michael@0 395 //----------------------------------------------------------------------
michael@0 396
michael@0 397 const Locale* U_EXPORT2
michael@0 398 DateFormat::getAvailableLocales(int32_t& count)
michael@0 399 {
michael@0 400 // Get the list of installed locales.
michael@0 401 // Even if root has the correct date format for this locale,
michael@0 402 // it's still a valid locale (we don't worry about data fallbacks).
michael@0 403 return Locale::getAvailableLocales(count);
michael@0 404 }
michael@0 405
michael@0 406 //----------------------------------------------------------------------
michael@0 407
michael@0 408 void
michael@0 409 DateFormat::adoptCalendar(Calendar* newCalendar)
michael@0 410 {
michael@0 411 delete fCalendar;
michael@0 412 fCalendar = newCalendar;
michael@0 413 }
michael@0 414
michael@0 415 //----------------------------------------------------------------------
michael@0 416 void
michael@0 417 DateFormat::setCalendar(const Calendar& newCalendar)
michael@0 418 {
michael@0 419 Calendar* newCalClone = newCalendar.clone();
michael@0 420 if (newCalClone != NULL) {
michael@0 421 adoptCalendar(newCalClone);
michael@0 422 }
michael@0 423 }
michael@0 424
michael@0 425 //----------------------------------------------------------------------
michael@0 426
michael@0 427 const Calendar*
michael@0 428 DateFormat::getCalendar() const
michael@0 429 {
michael@0 430 return fCalendar;
michael@0 431 }
michael@0 432
michael@0 433 //----------------------------------------------------------------------
michael@0 434
michael@0 435 void
michael@0 436 DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat)
michael@0 437 {
michael@0 438 delete fNumberFormat;
michael@0 439 fNumberFormat = newNumberFormat;
michael@0 440 newNumberFormat->setParseIntegerOnly(TRUE);
michael@0 441 }
michael@0 442 //----------------------------------------------------------------------
michael@0 443
michael@0 444 void
michael@0 445 DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)
michael@0 446 {
michael@0 447 NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone();
michael@0 448 if (newNumFmtClone != NULL) {
michael@0 449 adoptNumberFormat(newNumFmtClone);
michael@0 450 }
michael@0 451 }
michael@0 452
michael@0 453 //----------------------------------------------------------------------
michael@0 454
michael@0 455 const NumberFormat*
michael@0 456 DateFormat::getNumberFormat() const
michael@0 457 {
michael@0 458 return fNumberFormat;
michael@0 459 }
michael@0 460
michael@0 461 //----------------------------------------------------------------------
michael@0 462
michael@0 463 void
michael@0 464 DateFormat::adoptTimeZone(TimeZone* zone)
michael@0 465 {
michael@0 466 if (fCalendar != NULL) {
michael@0 467 fCalendar->adoptTimeZone(zone);
michael@0 468 }
michael@0 469 }
michael@0 470 //----------------------------------------------------------------------
michael@0 471
michael@0 472 void
michael@0 473 DateFormat::setTimeZone(const TimeZone& zone)
michael@0 474 {
michael@0 475 if (fCalendar != NULL) {
michael@0 476 fCalendar->setTimeZone(zone);
michael@0 477 }
michael@0 478 }
michael@0 479
michael@0 480 //----------------------------------------------------------------------
michael@0 481
michael@0 482 const TimeZone&
michael@0 483 DateFormat::getTimeZone() const
michael@0 484 {
michael@0 485 if (fCalendar != NULL) {
michael@0 486 return fCalendar->getTimeZone();
michael@0 487 }
michael@0 488 // If calendar doesn't exists, create default timezone.
michael@0 489 // fCalendar is rarely null
michael@0 490 return *(TimeZone::createDefault());
michael@0 491 }
michael@0 492
michael@0 493 //----------------------------------------------------------------------
michael@0 494
michael@0 495 void
michael@0 496 DateFormat::setLenient(UBool lenient)
michael@0 497 {
michael@0 498 if (fCalendar != NULL) {
michael@0 499 fCalendar->setLenient(lenient);
michael@0 500 }
michael@0 501 }
michael@0 502
michael@0 503 //----------------------------------------------------------------------
michael@0 504
michael@0 505 UBool
michael@0 506 DateFormat::isLenient() const
michael@0 507 {
michael@0 508 if (fCalendar != NULL) {
michael@0 509 return fCalendar->isLenient();
michael@0 510 }
michael@0 511 // fCalendar is rarely null
michael@0 512 return FALSE;
michael@0 513 }
michael@0 514
michael@0 515 //----------------------------------------------------------------------
michael@0 516
michael@0 517 DateFormat&
michael@0 518 DateFormat::setBooleanAttribute(UDateFormatBooleanAttribute attr,
michael@0 519 UBool newValue,
michael@0 520 UErrorCode &status) {
michael@0 521 if(!fBoolFlags.isValidValue(newValue)) {
michael@0 522 status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 523 } else {
michael@0 524 fBoolFlags.set(attr, newValue);
michael@0 525 }
michael@0 526
michael@0 527 return *this;
michael@0 528 }
michael@0 529
michael@0 530 //----------------------------------------------------------------------
michael@0 531
michael@0 532 UBool
michael@0 533 DateFormat::getBooleanAttribute(UDateFormatBooleanAttribute attr, UErrorCode &/*status*/) const {
michael@0 534
michael@0 535 return fBoolFlags.get(attr);
michael@0 536 }
michael@0 537
michael@0 538 U_NAMESPACE_END
michael@0 539
michael@0 540 #endif /* #if !UCONFIG_NO_FORMATTING */
michael@0 541
michael@0 542 //eof

mercurial