intl/icu/source/i18n/reldtfmt.cpp

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /*
michael@0 2 *******************************************************************************
michael@0 3 * Copyright (C) 2007-2013, International Business Machines Corporation and
michael@0 4 * others. All Rights Reserved.
michael@0 5 *******************************************************************************
michael@0 6 */
michael@0 7
michael@0 8 #include "unicode/utypes.h"
michael@0 9
michael@0 10 #if !UCONFIG_NO_FORMATTING
michael@0 11
michael@0 12 #include <stdlib.h>
michael@0 13
michael@0 14 #include "reldtfmt.h"
michael@0 15 #include "unicode/datefmt.h"
michael@0 16 #include "unicode/smpdtfmt.h"
michael@0 17 #include "unicode/msgfmt.h"
michael@0 18
michael@0 19 #include "gregoimp.h" // for CalendarData
michael@0 20 #include "cmemory.h"
michael@0 21 #include "uresimp.h"
michael@0 22
michael@0 23 U_NAMESPACE_BEGIN
michael@0 24
michael@0 25
michael@0 26 /**
michael@0 27 * An array of URelativeString structs is used to store the resource data loaded out of the bundle.
michael@0 28 */
michael@0 29 struct URelativeString {
michael@0 30 int32_t offset; /** offset of this item, such as, the relative date **/
michael@0 31 int32_t len; /** length of the string **/
michael@0 32 const UChar* string; /** string, or NULL if not set **/
michael@0 33 };
michael@0 34
michael@0 35 static const char DT_DateTimePatternsTag[]="DateTimePatterns";
michael@0 36
michael@0 37
michael@0 38 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RelativeDateFormat)
michael@0 39
michael@0 40 RelativeDateFormat::RelativeDateFormat(const RelativeDateFormat& other) :
michael@0 41 DateFormat(other), fDateTimeFormatter(NULL), fDatePattern(other.fDatePattern),
michael@0 42 fTimePattern(other.fTimePattern), fCombinedFormat(NULL),
michael@0 43 fDateStyle(other.fDateStyle), fLocale(other.fLocale),
michael@0 44 fDayMin(other.fDayMin), fDayMax(other.fDayMax),
michael@0 45 fDatesLen(other.fDatesLen), fDates(NULL)
michael@0 46 {
michael@0 47 if(other.fDateTimeFormatter != NULL) {
michael@0 48 fDateTimeFormatter = (SimpleDateFormat*)other.fDateTimeFormatter->clone();
michael@0 49 }
michael@0 50 if(other.fCombinedFormat != NULL) {
michael@0 51 fCombinedFormat = (MessageFormat*)other.fCombinedFormat->clone();
michael@0 52 }
michael@0 53 if (fDatesLen > 0) {
michael@0 54 fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
michael@0 55 uprv_memcpy(fDates, other.fDates, sizeof(fDates[0])*fDatesLen);
michael@0 56 }
michael@0 57 }
michael@0 58
michael@0 59 RelativeDateFormat::RelativeDateFormat( UDateFormatStyle timeStyle, UDateFormatStyle dateStyle,
michael@0 60 const Locale& locale, UErrorCode& status) :
michael@0 61 DateFormat(), fDateTimeFormatter(NULL), fDatePattern(), fTimePattern(), fCombinedFormat(NULL),
michael@0 62 fDateStyle(dateStyle), fLocale(locale), fDatesLen(0), fDates(NULL)
michael@0 63 {
michael@0 64 if(U_FAILURE(status) ) {
michael@0 65 return;
michael@0 66 }
michael@0 67
michael@0 68 if (timeStyle < UDAT_NONE || timeStyle > UDAT_SHORT) {
michael@0 69 // don't support other time styles (e.g. relative styles), for now
michael@0 70 status = U_ILLEGAL_ARGUMENT_ERROR;
michael@0 71 return;
michael@0 72 }
michael@0 73 UDateFormatStyle baseDateStyle = (dateStyle > UDAT_SHORT)? (UDateFormatStyle)(dateStyle & ~UDAT_RELATIVE): dateStyle;
michael@0 74 DateFormat * df;
michael@0 75 // Get fDateTimeFormatter from either date or time style (does not matter, we will override the pattern).
michael@0 76 // We do need to get separate patterns for the date & time styles.
michael@0 77 if (baseDateStyle != UDAT_NONE) {
michael@0 78 df = createDateInstance((EStyle)baseDateStyle, locale);
michael@0 79 fDateTimeFormatter=dynamic_cast<SimpleDateFormat *>(df);
michael@0 80 if (fDateTimeFormatter == NULL) {
michael@0 81 status = U_UNSUPPORTED_ERROR;
michael@0 82 return;
michael@0 83 }
michael@0 84 fDateTimeFormatter->toPattern(fDatePattern);
michael@0 85 if (timeStyle != UDAT_NONE) {
michael@0 86 df = createTimeInstance((EStyle)timeStyle, locale);
michael@0 87 SimpleDateFormat *sdf = dynamic_cast<SimpleDateFormat *>(df);
michael@0 88 if (sdf != NULL) {
michael@0 89 sdf->toPattern(fTimePattern);
michael@0 90 delete sdf;
michael@0 91 }
michael@0 92 }
michael@0 93 } else {
michael@0 94 // does not matter whether timeStyle is UDAT_NONE, we need something for fDateTimeFormatter
michael@0 95 df = createTimeInstance((EStyle)timeStyle, locale);
michael@0 96 fDateTimeFormatter=dynamic_cast<SimpleDateFormat *>(df);
michael@0 97 if (fDateTimeFormatter == NULL) {
michael@0 98 status = U_UNSUPPORTED_ERROR;
michael@0 99 return;
michael@0 100 }
michael@0 101 fDateTimeFormatter->toPattern(fTimePattern);
michael@0 102 }
michael@0 103
michael@0 104 // Initialize the parent fCalendar, so that parse() works correctly.
michael@0 105 initializeCalendar(NULL, locale, status);
michael@0 106 loadDates(status);
michael@0 107 }
michael@0 108
michael@0 109 RelativeDateFormat::~RelativeDateFormat() {
michael@0 110 delete fDateTimeFormatter;
michael@0 111 delete fCombinedFormat;
michael@0 112 uprv_free(fDates);
michael@0 113 }
michael@0 114
michael@0 115
michael@0 116 Format* RelativeDateFormat::clone(void) const {
michael@0 117 return new RelativeDateFormat(*this);
michael@0 118 }
michael@0 119
michael@0 120 UBool RelativeDateFormat::operator==(const Format& other) const {
michael@0 121 if(DateFormat::operator==(other)) {
michael@0 122 // DateFormat::operator== guarantees following cast is safe
michael@0 123 RelativeDateFormat* that = (RelativeDateFormat*)&other;
michael@0 124 return (fDateStyle==that->fDateStyle &&
michael@0 125 fDatePattern==that->fDatePattern &&
michael@0 126 fTimePattern==that->fTimePattern &&
michael@0 127 fLocale==that->fLocale);
michael@0 128 }
michael@0 129 return FALSE;
michael@0 130 }
michael@0 131
michael@0 132 static const UChar APOSTROPHE = (UChar)0x0027;
michael@0 133
michael@0 134 UnicodeString& RelativeDateFormat::format( Calendar& cal,
michael@0 135 UnicodeString& appendTo,
michael@0 136 FieldPosition& pos) const {
michael@0 137
michael@0 138 UErrorCode status = U_ZERO_ERROR;
michael@0 139 UnicodeString relativeDayString;
michael@0 140
michael@0 141 // calculate the difference, in days, between 'cal' and now.
michael@0 142 int dayDiff = dayDifference(cal, status);
michael@0 143
michael@0 144 // look up string
michael@0 145 int32_t len = 0;
michael@0 146 const UChar *theString = getStringForDay(dayDiff, len, status);
michael@0 147 if(U_SUCCESS(status) && (theString!=NULL)) {
michael@0 148 // found a relative string
michael@0 149 relativeDayString.setTo(theString, len);
michael@0 150 }
michael@0 151
michael@0 152 if (fDatePattern.isEmpty()) {
michael@0 153 fDateTimeFormatter->applyPattern(fTimePattern);
michael@0 154 fDateTimeFormatter->format(cal,appendTo,pos);
michael@0 155 } else if (fTimePattern.isEmpty() || fCombinedFormat == NULL) {
michael@0 156 if (relativeDayString.length() > 0) {
michael@0 157 appendTo.append(relativeDayString);
michael@0 158 } else {
michael@0 159 fDateTimeFormatter->applyPattern(fDatePattern);
michael@0 160 fDateTimeFormatter->format(cal,appendTo,pos);
michael@0 161 }
michael@0 162 } else {
michael@0 163 UnicodeString datePattern;
michael@0 164 if (relativeDayString.length() > 0) {
michael@0 165 // Need to quote the relativeDayString to make it a legal date pattern
michael@0 166 relativeDayString.findAndReplace(UNICODE_STRING("'", 1), UNICODE_STRING("''", 2)); // double any existing APOSTROPHE
michael@0 167 relativeDayString.insert(0, APOSTROPHE); // add APOSTROPHE at beginning...
michael@0 168 relativeDayString.append(APOSTROPHE); // and at end
michael@0 169 datePattern.setTo(relativeDayString);
michael@0 170 } else {
michael@0 171 datePattern.setTo(fDatePattern);
michael@0 172 }
michael@0 173 UnicodeString combinedPattern;
michael@0 174 Formattable timeDatePatterns[] = { fTimePattern, datePattern };
michael@0 175 fCombinedFormat->format(timeDatePatterns, 2, combinedPattern, pos, status); // pos is ignored by this
michael@0 176 fDateTimeFormatter->applyPattern(combinedPattern);
michael@0 177 fDateTimeFormatter->format(cal,appendTo,pos);
michael@0 178 }
michael@0 179
michael@0 180 return appendTo;
michael@0 181 }
michael@0 182
michael@0 183
michael@0 184
michael@0 185 UnicodeString&
michael@0 186 RelativeDateFormat::format(const Formattable& obj,
michael@0 187 UnicodeString& appendTo,
michael@0 188 FieldPosition& pos,
michael@0 189 UErrorCode& status) const
michael@0 190 {
michael@0 191 // this is just here to get around the hiding problem
michael@0 192 // (the previous format() override would hide the version of
michael@0 193 // format() on DateFormat that this function correspond to, so we
michael@0 194 // have to redefine it here)
michael@0 195 return DateFormat::format(obj, appendTo, pos, status);
michael@0 196 }
michael@0 197
michael@0 198
michael@0 199 void RelativeDateFormat::parse( const UnicodeString& text,
michael@0 200 Calendar& cal,
michael@0 201 ParsePosition& pos) const {
michael@0 202
michael@0 203 int32_t startIndex = pos.getIndex();
michael@0 204 if (fDatePattern.isEmpty()) {
michael@0 205 // no date pattern, try parsing as time
michael@0 206 fDateTimeFormatter->applyPattern(fTimePattern);
michael@0 207 fDateTimeFormatter->parse(text,cal,pos);
michael@0 208 } else if (fTimePattern.isEmpty() || fCombinedFormat == NULL) {
michael@0 209 // no time pattern or way to combine, try parsing as date
michael@0 210 // first check whether text matches a relativeDayString
michael@0 211 UBool matchedRelative = FALSE;
michael@0 212 for (int n=0; n < fDatesLen && !matchedRelative; n++) {
michael@0 213 if (fDates[n].string != NULL &&
michael@0 214 text.compare(startIndex, fDates[n].len, fDates[n].string) == 0) {
michael@0 215 // it matched, handle the relative day string
michael@0 216 UErrorCode status = U_ZERO_ERROR;
michael@0 217 matchedRelative = TRUE;
michael@0 218
michael@0 219 // Set the calendar to now+offset
michael@0 220 cal.setTime(Calendar::getNow(),status);
michael@0 221 cal.add(UCAL_DATE,fDates[n].offset, status);
michael@0 222
michael@0 223 if(U_FAILURE(status)) {
michael@0 224 // failure in setting calendar field, set offset to beginning of rel day string
michael@0 225 pos.setErrorIndex(startIndex);
michael@0 226 } else {
michael@0 227 pos.setIndex(startIndex + fDates[n].len);
michael@0 228 }
michael@0 229 }
michael@0 230 }
michael@0 231 if (!matchedRelative) {
michael@0 232 // just parse as normal date
michael@0 233 fDateTimeFormatter->applyPattern(fDatePattern);
michael@0 234 fDateTimeFormatter->parse(text,cal,pos);
michael@0 235 }
michael@0 236 } else {
michael@0 237 // Here we replace any relativeDayString in text with the equivalent date
michael@0 238 // formatted per fDatePattern, then parse text normally using the combined pattern.
michael@0 239 UnicodeString modifiedText(text);
michael@0 240 FieldPosition fPos;
michael@0 241 int32_t dateStart = 0, origDateLen = 0, modDateLen = 0;
michael@0 242 UErrorCode status = U_ZERO_ERROR;
michael@0 243 for (int n=0; n < fDatesLen; n++) {
michael@0 244 int32_t relativeStringOffset;
michael@0 245 if (fDates[n].string != NULL &&
michael@0 246 (relativeStringOffset = modifiedText.indexOf(fDates[n].string, fDates[n].len, startIndex)) >= startIndex) {
michael@0 247 // it matched, replace the relative date with a real one for parsing
michael@0 248 UnicodeString dateString;
michael@0 249 Calendar * tempCal = cal.clone();
michael@0 250
michael@0 251 // Set the calendar to now+offset
michael@0 252 tempCal->setTime(Calendar::getNow(),status);
michael@0 253 tempCal->add(UCAL_DATE,fDates[n].offset, status);
michael@0 254 if(U_FAILURE(status)) {
michael@0 255 pos.setErrorIndex(startIndex);
michael@0 256 delete tempCal;
michael@0 257 return;
michael@0 258 }
michael@0 259
michael@0 260 fDateTimeFormatter->applyPattern(fDatePattern);
michael@0 261 fDateTimeFormatter->format(*tempCal, dateString, fPos);
michael@0 262 dateStart = relativeStringOffset;
michael@0 263 origDateLen = fDates[n].len;
michael@0 264 modDateLen = dateString.length();
michael@0 265 modifiedText.replace(dateStart, origDateLen, dateString);
michael@0 266 delete tempCal;
michael@0 267 break;
michael@0 268 }
michael@0 269 }
michael@0 270 UnicodeString combinedPattern;
michael@0 271 Formattable timeDatePatterns[] = { fTimePattern, fDatePattern };
michael@0 272 fCombinedFormat->format(timeDatePatterns, 2, combinedPattern, fPos, status); // pos is ignored by this
michael@0 273 fDateTimeFormatter->applyPattern(combinedPattern);
michael@0 274 fDateTimeFormatter->parse(modifiedText,cal,pos);
michael@0 275
michael@0 276 // Adjust offsets
michael@0 277 UBool noError = (pos.getErrorIndex() < 0);
michael@0 278 int32_t offset = (noError)? pos.getIndex(): pos.getErrorIndex();
michael@0 279 if (offset >= dateStart + modDateLen) {
michael@0 280 // offset at or after the end of the replaced text,
michael@0 281 // correct by the difference between original and replacement
michael@0 282 offset -= (modDateLen - origDateLen);
michael@0 283 } else if (offset >= dateStart) {
michael@0 284 // offset in the replaced text, set it to the beginning of that text
michael@0 285 // (i.e. the beginning of the relative day string)
michael@0 286 offset = dateStart;
michael@0 287 }
michael@0 288 if (noError) {
michael@0 289 pos.setIndex(offset);
michael@0 290 } else {
michael@0 291 pos.setErrorIndex(offset);
michael@0 292 }
michael@0 293 }
michael@0 294 }
michael@0 295
michael@0 296 UDate
michael@0 297 RelativeDateFormat::parse( const UnicodeString& text,
michael@0 298 ParsePosition& pos) const {
michael@0 299 // redefined here because the other parse() function hides this function's
michael@0 300 // cunterpart on DateFormat
michael@0 301 return DateFormat::parse(text, pos);
michael@0 302 }
michael@0 303
michael@0 304 UDate
michael@0 305 RelativeDateFormat::parse(const UnicodeString& text, UErrorCode& status) const
michael@0 306 {
michael@0 307 // redefined here because the other parse() function hides this function's
michael@0 308 // counterpart on DateFormat
michael@0 309 return DateFormat::parse(text, status);
michael@0 310 }
michael@0 311
michael@0 312
michael@0 313 const UChar *RelativeDateFormat::getStringForDay(int32_t day, int32_t &len, UErrorCode &status) const {
michael@0 314 if(U_FAILURE(status)) {
michael@0 315 return NULL;
michael@0 316 }
michael@0 317
michael@0 318 // Is it outside the resource bundle's range?
michael@0 319 if(day < fDayMin || day > fDayMax) {
michael@0 320 return NULL; // don't have it.
michael@0 321 }
michael@0 322
michael@0 323 // Linear search the held strings
michael@0 324 for(int n=0;n<fDatesLen;n++) {
michael@0 325 if(fDates[n].offset == day) {
michael@0 326 len = fDates[n].len;
michael@0 327 return fDates[n].string;
michael@0 328 }
michael@0 329 }
michael@0 330
michael@0 331 return NULL; // not found.
michael@0 332 }
michael@0 333
michael@0 334 UnicodeString&
michael@0 335 RelativeDateFormat::toPattern(UnicodeString& result, UErrorCode& status) const
michael@0 336 {
michael@0 337 if (!U_FAILURE(status)) {
michael@0 338 result.remove();
michael@0 339 if (fDatePattern.isEmpty()) {
michael@0 340 result.setTo(fTimePattern);
michael@0 341 } else if (fTimePattern.isEmpty() || fCombinedFormat == NULL) {
michael@0 342 result.setTo(fDatePattern);
michael@0 343 } else {
michael@0 344 Formattable timeDatePatterns[] = { fTimePattern, fDatePattern };
michael@0 345 FieldPosition pos;
michael@0 346 fCombinedFormat->format(timeDatePatterns, 2, result, pos, status);
michael@0 347 }
michael@0 348 }
michael@0 349 return result;
michael@0 350 }
michael@0 351
michael@0 352 UnicodeString&
michael@0 353 RelativeDateFormat::toPatternDate(UnicodeString& result, UErrorCode& status) const
michael@0 354 {
michael@0 355 if (!U_FAILURE(status)) {
michael@0 356 result.remove();
michael@0 357 result.setTo(fDatePattern);
michael@0 358 }
michael@0 359 return result;
michael@0 360 }
michael@0 361
michael@0 362 UnicodeString&
michael@0 363 RelativeDateFormat::toPatternTime(UnicodeString& result, UErrorCode& status) const
michael@0 364 {
michael@0 365 if (!U_FAILURE(status)) {
michael@0 366 result.remove();
michael@0 367 result.setTo(fTimePattern);
michael@0 368 }
michael@0 369 return result;
michael@0 370 }
michael@0 371
michael@0 372 void
michael@0 373 RelativeDateFormat::applyPatterns(const UnicodeString& datePattern, const UnicodeString& timePattern, UErrorCode &status)
michael@0 374 {
michael@0 375 if (!U_FAILURE(status)) {
michael@0 376 fDatePattern.setTo(datePattern);
michael@0 377 fTimePattern.setTo(timePattern);
michael@0 378 }
michael@0 379 }
michael@0 380
michael@0 381 const DateFormatSymbols*
michael@0 382 RelativeDateFormat::getDateFormatSymbols() const
michael@0 383 {
michael@0 384 return fDateTimeFormatter->getDateFormatSymbols();
michael@0 385 }
michael@0 386
michael@0 387 void RelativeDateFormat::loadDates(UErrorCode &status) {
michael@0 388 CalendarData calData(fLocale, "gregorian", status);
michael@0 389
michael@0 390 UErrorCode tempStatus = status;
michael@0 391 UResourceBundle *dateTimePatterns = calData.getByKey(DT_DateTimePatternsTag, tempStatus);
michael@0 392 if(U_SUCCESS(tempStatus)) {
michael@0 393 int32_t patternsSize = ures_getSize(dateTimePatterns);
michael@0 394 if (patternsSize > kDateTime) {
michael@0 395 int32_t resStrLen = 0;
michael@0 396
michael@0 397 int32_t glueIndex = kDateTime;
michael@0 398 if (patternsSize >= (DateFormat::kDateTimeOffset + DateFormat::kShort + 1)) {
michael@0 399 // Get proper date time format
michael@0 400 switch (fDateStyle) {
michael@0 401 case kFullRelative:
michael@0 402 case kFull:
michael@0 403 glueIndex = kDateTimeOffset + kFull;
michael@0 404 break;
michael@0 405 case kLongRelative:
michael@0 406 case kLong:
michael@0 407 glueIndex = kDateTimeOffset + kLong;
michael@0 408 break;
michael@0 409 case kMediumRelative:
michael@0 410 case kMedium:
michael@0 411 glueIndex = kDateTimeOffset + kMedium;
michael@0 412 break;
michael@0 413 case kShortRelative:
michael@0 414 case kShort:
michael@0 415 glueIndex = kDateTimeOffset + kShort;
michael@0 416 break;
michael@0 417 default:
michael@0 418 break;
michael@0 419 }
michael@0 420 }
michael@0 421
michael@0 422 const UChar *resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &tempStatus);
michael@0 423 fCombinedFormat = new MessageFormat(UnicodeString(TRUE, resStr, resStrLen), fLocale, tempStatus);
michael@0 424 }
michael@0 425 }
michael@0 426
michael@0 427 UResourceBundle *rb = ures_open(NULL, fLocale.getBaseName(), &status);
michael@0 428 UResourceBundle *sb = ures_getByKeyWithFallback(rb, "fields", NULL, &status);
michael@0 429 rb = ures_getByKeyWithFallback(sb, "day", rb, &status);
michael@0 430 sb = ures_getByKeyWithFallback(rb, "relative", sb, &status);
michael@0 431 ures_close(rb);
michael@0 432 // set up min/max
michael@0 433 fDayMin=-1;
michael@0 434 fDayMax=1;
michael@0 435
michael@0 436 if(U_FAILURE(status)) {
michael@0 437 fDatesLen=0;
michael@0 438 ures_close(sb);
michael@0 439 return;
michael@0 440 }
michael@0 441
michael@0 442 fDatesLen = ures_getSize(sb);
michael@0 443 fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen);
michael@0 444
michael@0 445 // Load in each item into the array...
michael@0 446 int n = 0;
michael@0 447
michael@0 448 UResourceBundle *subString = NULL;
michael@0 449
michael@0 450 while(ures_hasNext(sb) && U_SUCCESS(status)) { // iterate over items
michael@0 451 subString = ures_getNextResource(sb, subString, &status);
michael@0 452
michael@0 453 if(U_FAILURE(status) || (subString==NULL)) break;
michael@0 454
michael@0 455 // key = offset #
michael@0 456 const char *key = ures_getKey(subString);
michael@0 457
michael@0 458 // load the string and length
michael@0 459 int32_t aLen;
michael@0 460 const UChar* aString = ures_getString(subString, &aLen, &status);
michael@0 461
michael@0 462 if(U_FAILURE(status) || aString == NULL) break;
michael@0 463
michael@0 464 // calculate the offset
michael@0 465 int32_t offset = atoi(key);
michael@0 466
michael@0 467 // set min/max
michael@0 468 if(offset < fDayMin) {
michael@0 469 fDayMin = offset;
michael@0 470 }
michael@0 471 if(offset > fDayMax) {
michael@0 472 fDayMax = offset;
michael@0 473 }
michael@0 474
michael@0 475 // copy the string pointer
michael@0 476 fDates[n].offset = offset;
michael@0 477 fDates[n].string = aString;
michael@0 478 fDates[n].len = aLen;
michael@0 479
michael@0 480 n++;
michael@0 481 }
michael@0 482 ures_close(subString);
michael@0 483 ures_close(sb);
michael@0 484
michael@0 485 // the fDates[] array could be sorted here, for direct access.
michael@0 486 }
michael@0 487
michael@0 488
michael@0 489 // this should to be in DateFormat, instead it was copied from SimpleDateFormat.
michael@0 490
michael@0 491 Calendar*
michael@0 492 RelativeDateFormat::initializeCalendar(TimeZone* adoptZone, const Locale& locale, UErrorCode& status)
michael@0 493 {
michael@0 494 if(!U_FAILURE(status)) {
michael@0 495 fCalendar = Calendar::createInstance(adoptZone?adoptZone:TimeZone::createDefault(), locale, status);
michael@0 496 }
michael@0 497 if (U_SUCCESS(status) && fCalendar == NULL) {
michael@0 498 status = U_MEMORY_ALLOCATION_ERROR;
michael@0 499 }
michael@0 500 return fCalendar;
michael@0 501 }
michael@0 502
michael@0 503 int32_t RelativeDateFormat::dayDifference(Calendar &cal, UErrorCode &status) {
michael@0 504 if(U_FAILURE(status)) {
michael@0 505 return 0;
michael@0 506 }
michael@0 507 // TODO: Cache the nowCal to avoid heap allocs? Would be difficult, don't know the calendar type
michael@0 508 Calendar *nowCal = cal.clone();
michael@0 509 nowCal->setTime(Calendar::getNow(), status);
michael@0 510
michael@0 511 // For the day difference, we are interested in the difference in the (modified) julian day number
michael@0 512 // which is midnight to midnight. Using fieldDifference() is NOT correct here, because
michael@0 513 // 6pm Jan 4th to 10am Jan 5th should be considered "tomorrow".
michael@0 514 int32_t dayDiff = cal.get(UCAL_JULIAN_DAY, status) - nowCal->get(UCAL_JULIAN_DAY, status);
michael@0 515
michael@0 516 delete nowCal;
michael@0 517 return dayDiff;
michael@0 518 }
michael@0 519
michael@0 520 U_NAMESPACE_END
michael@0 521
michael@0 522 #endif
michael@0 523

mercurial