1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/datefmt.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,542 @@ 1.4 +/* 1.5 + ******************************************************************************* 1.6 + * Copyright (C) 1997-2013, International Business Machines Corporation and * 1.7 + * others. All Rights Reserved. * 1.8 + ******************************************************************************* 1.9 + * 1.10 + * File DATEFMT.CPP 1.11 + * 1.12 + * Modification History: 1.13 + * 1.14 + * Date Name Description 1.15 + * 02/19/97 aliu Converted from java. 1.16 + * 03/31/97 aliu Modified extensively to work with 50 locales. 1.17 + * 04/01/97 aliu Added support for centuries. 1.18 + * 08/12/97 aliu Fixed operator== to use Calendar::equivalentTo. 1.19 + * 07/20/98 stephen Changed ParsePosition initialization 1.20 + ******************************************************************************** 1.21 + */ 1.22 + 1.23 +#include "unicode/utypes.h" 1.24 + 1.25 +#if !UCONFIG_NO_FORMATTING 1.26 + 1.27 +#include "unicode/ures.h" 1.28 +#include "unicode/datefmt.h" 1.29 +#include "unicode/smpdtfmt.h" 1.30 +#include "unicode/dtptngen.h" 1.31 +#include "reldtfmt.h" 1.32 + 1.33 +#include "cstring.h" 1.34 +#include "windtfmt.h" 1.35 + 1.36 +#if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL) 1.37 +#include <stdio.h> 1.38 +#endif 1.39 + 1.40 +// ***************************************************************************** 1.41 +// class DateFormat 1.42 +// ***************************************************************************** 1.43 + 1.44 +U_NAMESPACE_BEGIN 1.45 + 1.46 +DateFormat::DateFormat() 1.47 +: fCalendar(0), 1.48 + fNumberFormat(0) 1.49 +{ 1.50 +} 1.51 + 1.52 +//---------------------------------------------------------------------- 1.53 + 1.54 +DateFormat::DateFormat(const DateFormat& other) 1.55 +: Format(other), 1.56 + fCalendar(0), 1.57 + fNumberFormat(0) 1.58 +{ 1.59 + *this = other; 1.60 +} 1.61 + 1.62 +//---------------------------------------------------------------------- 1.63 + 1.64 +DateFormat& DateFormat::operator=(const DateFormat& other) 1.65 +{ 1.66 + if (this != &other) 1.67 + { 1.68 + delete fCalendar; 1.69 + delete fNumberFormat; 1.70 + if(other.fCalendar) { 1.71 + fCalendar = other.fCalendar->clone(); 1.72 + } else { 1.73 + fCalendar = NULL; 1.74 + } 1.75 + if(other.fNumberFormat) { 1.76 + fNumberFormat = (NumberFormat*)other.fNumberFormat->clone(); 1.77 + } else { 1.78 + fNumberFormat = NULL; 1.79 + } 1.80 + fBoolFlags = other.fBoolFlags; 1.81 + } 1.82 + return *this; 1.83 +} 1.84 + 1.85 +//---------------------------------------------------------------------- 1.86 + 1.87 +DateFormat::~DateFormat() 1.88 +{ 1.89 + delete fCalendar; 1.90 + delete fNumberFormat; 1.91 +} 1.92 + 1.93 +//---------------------------------------------------------------------- 1.94 + 1.95 +UBool 1.96 +DateFormat::operator==(const Format& other) const 1.97 +{ 1.98 + // This protected comparison operator should only be called by subclasses 1.99 + // which have confirmed that the other object being compared against is 1.100 + // an instance of a sublcass of DateFormat. THIS IS IMPORTANT. 1.101 + 1.102 + // Format::operator== guarantees that this cast is safe 1.103 + DateFormat* fmt = (DateFormat*)&other; 1.104 + 1.105 + return (this == fmt) || 1.106 + (Format::operator==(other) && 1.107 + fCalendar&&(fCalendar->isEquivalentTo(*fmt->fCalendar)) && 1.108 + (fNumberFormat && *fNumberFormat == *fmt->fNumberFormat)); 1.109 +} 1.110 + 1.111 +//---------------------------------------------------------------------- 1.112 + 1.113 +UnicodeString& 1.114 +DateFormat::format(const Formattable& obj, 1.115 + UnicodeString& appendTo, 1.116 + FieldPosition& fieldPosition, 1.117 + UErrorCode& status) const 1.118 +{ 1.119 + if (U_FAILURE(status)) return appendTo; 1.120 + 1.121 + // if the type of the Formattable is double or long, treat it as if it were a Date 1.122 + UDate date = 0; 1.123 + switch (obj.getType()) 1.124 + { 1.125 + case Formattable::kDate: 1.126 + date = obj.getDate(); 1.127 + break; 1.128 + case Formattable::kDouble: 1.129 + date = (UDate)obj.getDouble(); 1.130 + break; 1.131 + case Formattable::kLong: 1.132 + date = (UDate)obj.getLong(); 1.133 + break; 1.134 + default: 1.135 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.136 + return appendTo; 1.137 + } 1.138 + 1.139 + // Is this right? 1.140 + //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex()) 1.141 + // status = U_ILLEGAL_ARGUMENT_ERROR; 1.142 + 1.143 + return format(date, appendTo, fieldPosition); 1.144 +} 1.145 + 1.146 +//---------------------------------------------------------------------- 1.147 + 1.148 +UnicodeString& 1.149 +DateFormat::format(const Formattable& obj, 1.150 + UnicodeString& appendTo, 1.151 + FieldPositionIterator* posIter, 1.152 + UErrorCode& status) const 1.153 +{ 1.154 + if (U_FAILURE(status)) return appendTo; 1.155 + 1.156 + // if the type of the Formattable is double or long, treat it as if it were a Date 1.157 + UDate date = 0; 1.158 + switch (obj.getType()) 1.159 + { 1.160 + case Formattable::kDate: 1.161 + date = obj.getDate(); 1.162 + break; 1.163 + case Formattable::kDouble: 1.164 + date = (UDate)obj.getDouble(); 1.165 + break; 1.166 + case Formattable::kLong: 1.167 + date = (UDate)obj.getLong(); 1.168 + break; 1.169 + default: 1.170 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.171 + return appendTo; 1.172 + } 1.173 + 1.174 + // Is this right? 1.175 + //if (fieldPosition.getBeginIndex() == fieldPosition.getEndIndex()) 1.176 + // status = U_ILLEGAL_ARGUMENT_ERROR; 1.177 + 1.178 + return format(date, appendTo, posIter, status); 1.179 +} 1.180 + 1.181 +//---------------------------------------------------------------------- 1.182 + 1.183 +// Default implementation for backwards compatibility, subclasses should implement. 1.184 +UnicodeString& 1.185 +DateFormat::format(Calendar& /* unused cal */, 1.186 + UnicodeString& appendTo, 1.187 + FieldPositionIterator* /* unused posIter */, 1.188 + UErrorCode& status) const { 1.189 + if (U_SUCCESS(status)) { 1.190 + status = U_UNSUPPORTED_ERROR; 1.191 + } 1.192 + return appendTo; 1.193 +} 1.194 + 1.195 +//---------------------------------------------------------------------- 1.196 + 1.197 +UnicodeString& 1.198 +DateFormat::format(UDate date, UnicodeString& appendTo, FieldPosition& fieldPosition) const { 1.199 + if (fCalendar != NULL) { 1.200 + // Use a clone of our calendar instance 1.201 + Calendar* calClone = fCalendar->clone(); 1.202 + if (calClone != NULL) { 1.203 + UErrorCode ec = U_ZERO_ERROR; 1.204 + calClone->setTime(date, ec); 1.205 + if (U_SUCCESS(ec)) { 1.206 + format(*calClone, appendTo, fieldPosition); 1.207 + } 1.208 + delete calClone; 1.209 + } 1.210 + } 1.211 + return appendTo; 1.212 +} 1.213 + 1.214 +//---------------------------------------------------------------------- 1.215 + 1.216 +UnicodeString& 1.217 +DateFormat::format(UDate date, UnicodeString& appendTo, FieldPositionIterator* posIter, 1.218 + UErrorCode& status) const { 1.219 + if (fCalendar != NULL) { 1.220 + Calendar* calClone = fCalendar->clone(); 1.221 + if (calClone != NULL) { 1.222 + calClone->setTime(date, status); 1.223 + if (U_SUCCESS(status)) { 1.224 + format(*calClone, appendTo, posIter, status); 1.225 + } 1.226 + delete calClone; 1.227 + } 1.228 + } 1.229 + return appendTo; 1.230 +} 1.231 + 1.232 +//---------------------------------------------------------------------- 1.233 + 1.234 +UnicodeString& 1.235 +DateFormat::format(UDate date, UnicodeString& appendTo) const 1.236 +{ 1.237 + // Note that any error information is just lost. That's okay 1.238 + // for this convenience method. 1.239 + FieldPosition fpos(0); 1.240 + return format(date, appendTo, fpos); 1.241 +} 1.242 + 1.243 +//---------------------------------------------------------------------- 1.244 + 1.245 +UDate 1.246 +DateFormat::parse(const UnicodeString& text, 1.247 + ParsePosition& pos) const 1.248 +{ 1.249 + UDate d = 0; // Error return UDate is 0 (the epoch) 1.250 + if (fCalendar != NULL) { 1.251 + Calendar* calClone = fCalendar->clone(); 1.252 + if (calClone != NULL) { 1.253 + int32_t start = pos.getIndex(); 1.254 + calClone->clear(); 1.255 + parse(text, *calClone, pos); 1.256 + if (pos.getIndex() != start) { 1.257 + UErrorCode ec = U_ZERO_ERROR; 1.258 + d = calClone->getTime(ec); 1.259 + if (U_FAILURE(ec)) { 1.260 + // We arrive here if fCalendar => calClone is non-lenient and 1.261 + // there is an out-of-range field. We don't know which field 1.262 + // was illegal so we set the error index to the start. 1.263 + pos.setIndex(start); 1.264 + pos.setErrorIndex(start); 1.265 + d = 0; 1.266 + } 1.267 + } 1.268 + delete calClone; 1.269 + } 1.270 + } 1.271 + return d; 1.272 +} 1.273 + 1.274 +//---------------------------------------------------------------------- 1.275 + 1.276 +UDate 1.277 +DateFormat::parse(const UnicodeString& text, 1.278 + UErrorCode& status) const 1.279 +{ 1.280 + if (U_FAILURE(status)) return 0; 1.281 + 1.282 + ParsePosition pos(0); 1.283 + UDate result = parse(text, pos); 1.284 + if (pos.getIndex() == 0) { 1.285 +#if defined (U_DEBUG_CAL) 1.286 + fprintf(stderr, "%s:%d - - failed to parse - err index %d\n" 1.287 + , __FILE__, __LINE__, pos.getErrorIndex() ); 1.288 +#endif 1.289 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.290 + } 1.291 + return result; 1.292 +} 1.293 + 1.294 +//---------------------------------------------------------------------- 1.295 + 1.296 +void 1.297 +DateFormat::parseObject(const UnicodeString& source, 1.298 + Formattable& result, 1.299 + ParsePosition& pos) const 1.300 +{ 1.301 + result.setDate(parse(source, pos)); 1.302 +} 1.303 + 1.304 +//---------------------------------------------------------------------- 1.305 + 1.306 +DateFormat* U_EXPORT2 1.307 +DateFormat::createTimeInstance(DateFormat::EStyle style, 1.308 + const Locale& aLocale) 1.309 +{ 1.310 + return create(style, kNone, aLocale); 1.311 +} 1.312 + 1.313 +//---------------------------------------------------------------------- 1.314 + 1.315 +DateFormat* U_EXPORT2 1.316 +DateFormat::createDateInstance(DateFormat::EStyle style, 1.317 + const Locale& aLocale) 1.318 +{ 1.319 + // +4 to set the correct index for getting data out of 1.320 + // LocaleElements. 1.321 + if(style != kNone) 1.322 + { 1.323 + style = (EStyle) (style + kDateOffset); 1.324 + } 1.325 + return create(kNone, (EStyle) (style), aLocale); 1.326 +} 1.327 + 1.328 +//---------------------------------------------------------------------- 1.329 + 1.330 +DateFormat* U_EXPORT2 1.331 +DateFormat::createDateTimeInstance(EStyle dateStyle, 1.332 + EStyle timeStyle, 1.333 + const Locale& aLocale) 1.334 +{ 1.335 + if(dateStyle != kNone) 1.336 + { 1.337 + dateStyle = (EStyle) (dateStyle + kDateOffset); 1.338 + } 1.339 + return create(timeStyle, dateStyle, aLocale); 1.340 +} 1.341 + 1.342 +//---------------------------------------------------------------------- 1.343 + 1.344 +DateFormat* U_EXPORT2 1.345 +DateFormat::createInstance() 1.346 +{ 1.347 + return create(kShort, (EStyle) (kShort + kDateOffset), Locale::getDefault()); 1.348 +} 1.349 + 1.350 +//---------------------------------------------------------------------- 1.351 + 1.352 +DateFormat* U_EXPORT2 1.353 +DateFormat::create(EStyle timeStyle, EStyle dateStyle, const Locale& locale) 1.354 +{ 1.355 + UErrorCode status = U_ZERO_ERROR; 1.356 +#if U_PLATFORM_HAS_WIN32_API 1.357 + char buffer[8]; 1.358 + int32_t count = locale.getKeywordValue("compat", buffer, sizeof(buffer), status); 1.359 + 1.360 + // if the locale has "@compat=host", create a host-specific DateFormat... 1.361 + if (count > 0 && uprv_strcmp(buffer, "host") == 0) { 1.362 + Win32DateFormat *f = new Win32DateFormat(timeStyle, dateStyle, locale, status); 1.363 + 1.364 + if (U_SUCCESS(status)) { 1.365 + return f; 1.366 + } 1.367 + 1.368 + delete f; 1.369 + } 1.370 +#endif 1.371 + 1.372 + // is it relative? 1.373 + if(/*((timeStyle!=UDAT_NONE)&&(timeStyle & UDAT_RELATIVE)) || */((dateStyle!=kNone)&&((dateStyle-kDateOffset) & UDAT_RELATIVE))) { 1.374 + RelativeDateFormat *r = new RelativeDateFormat((UDateFormatStyle)timeStyle, (UDateFormatStyle)(dateStyle-kDateOffset), locale, status); 1.375 + if(U_SUCCESS(status)) return r; 1.376 + delete r; 1.377 + status = U_ZERO_ERROR; 1.378 + } 1.379 + 1.380 + // Try to create a SimpleDateFormat of the desired style. 1.381 + SimpleDateFormat *f = new SimpleDateFormat(timeStyle, dateStyle, locale, status); 1.382 + if (U_SUCCESS(status)) return f; 1.383 + delete f; 1.384 + 1.385 + // If that fails, try to create a format using the default pattern and 1.386 + // the DateFormatSymbols for this locale. 1.387 + status = U_ZERO_ERROR; 1.388 + f = new SimpleDateFormat(locale, status); 1.389 + if (U_SUCCESS(status)) return f; 1.390 + delete f; 1.391 + 1.392 + // This should never really happen, because the preceding constructor 1.393 + // should always succeed. If the resource data is unavailable, a last 1.394 + // resort object should be returned. 1.395 + return 0; 1.396 +} 1.397 + 1.398 +//---------------------------------------------------------------------- 1.399 + 1.400 +const Locale* U_EXPORT2 1.401 +DateFormat::getAvailableLocales(int32_t& count) 1.402 +{ 1.403 + // Get the list of installed locales. 1.404 + // Even if root has the correct date format for this locale, 1.405 + // it's still a valid locale (we don't worry about data fallbacks). 1.406 + return Locale::getAvailableLocales(count); 1.407 +} 1.408 + 1.409 +//---------------------------------------------------------------------- 1.410 + 1.411 +void 1.412 +DateFormat::adoptCalendar(Calendar* newCalendar) 1.413 +{ 1.414 + delete fCalendar; 1.415 + fCalendar = newCalendar; 1.416 +} 1.417 + 1.418 +//---------------------------------------------------------------------- 1.419 +void 1.420 +DateFormat::setCalendar(const Calendar& newCalendar) 1.421 +{ 1.422 + Calendar* newCalClone = newCalendar.clone(); 1.423 + if (newCalClone != NULL) { 1.424 + adoptCalendar(newCalClone); 1.425 + } 1.426 +} 1.427 + 1.428 +//---------------------------------------------------------------------- 1.429 + 1.430 +const Calendar* 1.431 +DateFormat::getCalendar() const 1.432 +{ 1.433 + return fCalendar; 1.434 +} 1.435 + 1.436 +//---------------------------------------------------------------------- 1.437 + 1.438 +void 1.439 +DateFormat::adoptNumberFormat(NumberFormat* newNumberFormat) 1.440 +{ 1.441 + delete fNumberFormat; 1.442 + fNumberFormat = newNumberFormat; 1.443 + newNumberFormat->setParseIntegerOnly(TRUE); 1.444 +} 1.445 +//---------------------------------------------------------------------- 1.446 + 1.447 +void 1.448 +DateFormat::setNumberFormat(const NumberFormat& newNumberFormat) 1.449 +{ 1.450 + NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone(); 1.451 + if (newNumFmtClone != NULL) { 1.452 + adoptNumberFormat(newNumFmtClone); 1.453 + } 1.454 +} 1.455 + 1.456 +//---------------------------------------------------------------------- 1.457 + 1.458 +const NumberFormat* 1.459 +DateFormat::getNumberFormat() const 1.460 +{ 1.461 + return fNumberFormat; 1.462 +} 1.463 + 1.464 +//---------------------------------------------------------------------- 1.465 + 1.466 +void 1.467 +DateFormat::adoptTimeZone(TimeZone* zone) 1.468 +{ 1.469 + if (fCalendar != NULL) { 1.470 + fCalendar->adoptTimeZone(zone); 1.471 + } 1.472 +} 1.473 +//---------------------------------------------------------------------- 1.474 + 1.475 +void 1.476 +DateFormat::setTimeZone(const TimeZone& zone) 1.477 +{ 1.478 + if (fCalendar != NULL) { 1.479 + fCalendar->setTimeZone(zone); 1.480 + } 1.481 +} 1.482 + 1.483 +//---------------------------------------------------------------------- 1.484 + 1.485 +const TimeZone& 1.486 +DateFormat::getTimeZone() const 1.487 +{ 1.488 + if (fCalendar != NULL) { 1.489 + return fCalendar->getTimeZone(); 1.490 + } 1.491 + // If calendar doesn't exists, create default timezone. 1.492 + // fCalendar is rarely null 1.493 + return *(TimeZone::createDefault()); 1.494 +} 1.495 + 1.496 +//---------------------------------------------------------------------- 1.497 + 1.498 +void 1.499 +DateFormat::setLenient(UBool lenient) 1.500 +{ 1.501 + if (fCalendar != NULL) { 1.502 + fCalendar->setLenient(lenient); 1.503 + } 1.504 +} 1.505 + 1.506 +//---------------------------------------------------------------------- 1.507 + 1.508 +UBool 1.509 +DateFormat::isLenient() const 1.510 +{ 1.511 + if (fCalendar != NULL) { 1.512 + return fCalendar->isLenient(); 1.513 + } 1.514 + // fCalendar is rarely null 1.515 + return FALSE; 1.516 +} 1.517 + 1.518 +//---------------------------------------------------------------------- 1.519 + 1.520 +DateFormat& 1.521 +DateFormat::setBooleanAttribute(UDateFormatBooleanAttribute attr, 1.522 + UBool newValue, 1.523 + UErrorCode &status) { 1.524 + if(!fBoolFlags.isValidValue(newValue)) { 1.525 + status = U_ILLEGAL_ARGUMENT_ERROR; 1.526 + } else { 1.527 + fBoolFlags.set(attr, newValue); 1.528 + } 1.529 + 1.530 + return *this; 1.531 +} 1.532 + 1.533 +//---------------------------------------------------------------------- 1.534 + 1.535 +UBool 1.536 +DateFormat::getBooleanAttribute(UDateFormatBooleanAttribute attr, UErrorCode &/*status*/) const { 1.537 + 1.538 + return fBoolFlags.get(attr); 1.539 +} 1.540 + 1.541 +U_NAMESPACE_END 1.542 + 1.543 +#endif /* #if !UCONFIG_NO_FORMATTING */ 1.544 + 1.545 +//eof