1 /* 2 * Copyright 2003, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2010-2011, Oliver Tappe, zooey@hirschkaefer.de. 4 * Copyright 2012, John Scipione, jscipione@gmail.com 5 * All rights reserved. Distributed under the terms of the OpenBeOS License. 6 */ 7 8 9 #include <AutoDeleter.h> 10 #include <Autolock.h> 11 #include <CalendarView.h> 12 #include <Catalog.h> 13 #include <FormattingConventionsPrivate.h> 14 #include <LanguagePrivate.h> 15 #include <Locale.h> 16 #include <LocaleRoster.h> 17 #include <TimeZone.h> 18 19 #include <ICUWrapper.h> 20 21 #include <unicode/datefmt.h> 22 #include <unicode/dcfmtsym.h> 23 #include <unicode/decimfmt.h> 24 #include <unicode/dtfmtsym.h> 25 #include <unicode/numfmt.h> 26 #include <unicode/smpdtfmt.h> 27 #include <unicode/ustring.h> 28 29 #include <vector> 30 31 32 using BPrivate::ObjectDeleter; 33 34 35 BLocale::BLocale(const BLanguage* language, 36 const BFormattingConventions* conventions) 37 { 38 if (conventions != NULL) 39 fConventions = *conventions; 40 else 41 BLocale::Default()->GetFormattingConventions(&fConventions); 42 43 if (language != NULL) 44 fLanguage = *language; 45 else 46 BLocale::Default()->GetLanguage(&fLanguage); 47 } 48 49 50 BLocale::BLocale(const BLocale& other) 51 : 52 fConventions(other.fConventions), 53 fLanguage(other.fLanguage) 54 { 55 } 56 57 58 /*static*/ const BLocale* 59 BLocale::Default() 60 { 61 return BLocaleRoster::Default()->GetDefaultLocale(); 62 } 63 64 65 BLocale& 66 BLocale::operator=(const BLocale& other) 67 { 68 if (this == &other) 69 return *this; 70 71 BAutolock lock(fLock); 72 BAutolock otherLock(other.fLock); 73 if (!lock.IsLocked() || !otherLock.IsLocked()) 74 return *this; 75 76 fConventions = other.fConventions; 77 fLanguage = other.fLanguage; 78 79 return *this; 80 } 81 82 83 BLocale::~BLocale() 84 { 85 } 86 87 88 status_t 89 BLocale::GetCollator(BCollator* collator) const 90 { 91 if (!collator) 92 return B_BAD_VALUE; 93 94 BAutolock lock(fLock); 95 if (!lock.IsLocked()) 96 return B_ERROR; 97 98 *collator = fCollator; 99 100 return B_OK; 101 } 102 103 104 status_t 105 BLocale::GetLanguage(BLanguage* language) const 106 { 107 if (!language) 108 return B_BAD_VALUE; 109 110 BAutolock lock(fLock); 111 if (!lock.IsLocked()) 112 return B_ERROR; 113 114 *language = fLanguage; 115 116 return B_OK; 117 } 118 119 120 status_t 121 BLocale::GetFormattingConventions(BFormattingConventions* conventions) const 122 { 123 if (!conventions) 124 return B_BAD_VALUE; 125 126 BAutolock lock(fLock); 127 if (!lock.IsLocked()) 128 return B_ERROR; 129 130 *conventions = fConventions; 131 132 return B_OK; 133 } 134 135 136 const char * 137 BLocale::GetString(uint32 id) const 138 { 139 // Note: this code assumes a certain order of the string bases 140 141 BAutolock lock(fLock); 142 if (!lock.IsLocked()) 143 return ""; 144 145 if (id >= B_OTHER_STRINGS_BASE) { 146 if (id == B_CODESET) 147 return "UTF-8"; 148 149 return ""; 150 } 151 return fLanguage.GetString(id); 152 } 153 154 155 void 156 BLocale::SetFormattingConventions(const BFormattingConventions& conventions) 157 { 158 BAutolock lock(fLock); 159 if (!lock.IsLocked()) 160 return; 161 162 fConventions = conventions; 163 } 164 165 166 void 167 BLocale::SetCollator(const BCollator& newCollator) 168 { 169 BAutolock lock(fLock); 170 if (!lock.IsLocked()) 171 return; 172 173 fCollator = newCollator; 174 } 175 176 177 void 178 BLocale::SetLanguage(const BLanguage& newLanguage) 179 { 180 BAutolock lock(fLock); 181 if (!lock.IsLocked()) 182 return; 183 184 fLanguage = newLanguage; 185 } 186 187 188 // #pragma mark - Date 189 190 191 ssize_t 192 BLocale::FormatDate(char* string, size_t maxSize, time_t time, 193 BDateFormatStyle style) const 194 { 195 BAutolock lock(fLock); 196 if (!lock.IsLocked()) 197 return B_ERROR; 198 199 BString format; 200 fConventions.GetDateFormat(style, format); 201 ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); 202 if (dateFormatter.Get() == NULL) 203 return B_NO_MEMORY; 204 205 UnicodeString icuString; 206 dateFormatter->format((UDate)time * 1000, icuString); 207 208 CheckedArrayByteSink stringConverter(string, maxSize); 209 icuString.toUTF8(stringConverter); 210 211 if (stringConverter.Overflowed()) 212 return B_BAD_VALUE; 213 214 return stringConverter.NumberOfBytesWritten(); 215 } 216 217 218 status_t 219 BLocale::FormatDate(BString *string, time_t time, BDateFormatStyle style, 220 const BTimeZone* timeZone) const 221 { 222 BAutolock lock(fLock); 223 if (!lock.IsLocked()) 224 return B_ERROR; 225 226 BString format; 227 fConventions.GetDateFormat(style, format); 228 ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); 229 if (dateFormatter.Get() == NULL) 230 return B_NO_MEMORY; 231 232 if (timeZone != NULL) { 233 ObjectDeleter<TimeZone> icuTimeZone( 234 TimeZone::createTimeZone(timeZone->ID().String())); 235 if (icuTimeZone.Get() == NULL) 236 return B_NO_MEMORY; 237 dateFormatter->setTimeZone(*icuTimeZone.Get()); 238 } 239 240 UnicodeString icuString; 241 dateFormatter->format((UDate)time * 1000, icuString); 242 243 string->Truncate(0); 244 BStringByteSink stringConverter(string); 245 icuString.toUTF8(stringConverter); 246 247 return B_OK; 248 } 249 250 251 status_t 252 BLocale::FormatDate(BString* string, int*& fieldPositions, int& fieldCount, 253 time_t time, BDateFormatStyle style) const 254 { 255 BAutolock lock(fLock); 256 if (!lock.IsLocked()) 257 return B_ERROR; 258 259 BString format; 260 fConventions.GetDateFormat(style, format); 261 ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); 262 if (dateFormatter.Get() == NULL) 263 return B_NO_MEMORY; 264 265 fieldPositions = NULL; 266 UErrorCode error = U_ZERO_ERROR; 267 icu::FieldPositionIterator positionIterator; 268 UnicodeString icuString; 269 dateFormatter->format((UDate)time * 1000, icuString, &positionIterator, 270 error); 271 272 if (error != U_ZERO_ERROR) 273 return B_BAD_VALUE; 274 275 icu::FieldPosition field; 276 std::vector<int> fieldPosStorage; 277 fieldCount = 0; 278 while (positionIterator.next(field)) { 279 fieldPosStorage.push_back(field.getBeginIndex()); 280 fieldPosStorage.push_back(field.getEndIndex()); 281 fieldCount += 2; 282 } 283 284 fieldPositions = (int*) malloc(fieldCount * sizeof(int)); 285 286 for (int i = 0 ; i < fieldCount ; i++ ) 287 fieldPositions[i] = fieldPosStorage[i]; 288 289 string->Truncate(0); 290 BStringByteSink stringConverter(string); 291 292 icuString.toUTF8(stringConverter); 293 294 return B_OK; 295 } 296 297 298 status_t 299 BLocale::GetDateFields(BDateElement*& fields, int& fieldCount, 300 BDateFormatStyle style) const 301 { 302 BAutolock lock(fLock); 303 if (!lock.IsLocked()) 304 return B_ERROR; 305 306 BString format; 307 fConventions.GetDateFormat(style, format); 308 ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); 309 if (dateFormatter.Get() == NULL) 310 return B_NO_MEMORY; 311 312 fields = NULL; 313 UErrorCode error = U_ZERO_ERROR; 314 icu::FieldPositionIterator positionIterator; 315 UnicodeString icuString; 316 time_t now; 317 dateFormatter->format((UDate)time(&now) * 1000, icuString, 318 &positionIterator, error); 319 320 if (U_FAILURE(error)) 321 return B_BAD_VALUE; 322 323 icu::FieldPosition field; 324 std::vector<int> fieldPosStorage; 325 fieldCount = 0; 326 while (positionIterator.next(field)) { 327 fieldPosStorage.push_back(field.getField()); 328 fieldCount ++; 329 } 330 331 fields = (BDateElement*) malloc(fieldCount * sizeof(BDateElement)); 332 333 for (int i = 0 ; i < fieldCount ; i++ ) { 334 switch (fieldPosStorage[i]) { 335 case UDAT_YEAR_FIELD: 336 fields[i] = B_DATE_ELEMENT_YEAR; 337 break; 338 case UDAT_MONTH_FIELD: 339 fields[i] = B_DATE_ELEMENT_MONTH; 340 break; 341 case UDAT_DATE_FIELD: 342 fields[i] = B_DATE_ELEMENT_DAY; 343 break; 344 default: 345 fields[i] = B_DATE_ELEMENT_INVALID; 346 break; 347 } 348 } 349 350 return B_OK; 351 } 352 353 354 status_t 355 BLocale::GetStartOfWeek(BWeekday* startOfWeek) const 356 { 357 if (startOfWeek == NULL) 358 return B_BAD_VALUE; 359 360 BAutolock lock(fLock); 361 if (!lock.IsLocked()) 362 return B_ERROR; 363 364 UErrorCode err = U_ZERO_ERROR; 365 ObjectDeleter<Calendar> calendar = Calendar::createInstance( 366 *BFormattingConventions::Private(&fConventions).ICULocale(), err); 367 368 if (U_FAILURE(err)) 369 return B_ERROR; 370 371 UCalendarDaysOfWeek icuWeekStart = calendar->getFirstDayOfWeek(err); 372 if (U_FAILURE(err)) 373 return B_ERROR; 374 375 switch (icuWeekStart) { 376 case UCAL_SUNDAY: 377 *startOfWeek = B_WEEKDAY_SUNDAY; 378 break; 379 case UCAL_MONDAY: 380 *startOfWeek = B_WEEKDAY_MONDAY; 381 break; 382 case UCAL_TUESDAY: 383 *startOfWeek = B_WEEKDAY_TUESDAY; 384 break; 385 case UCAL_WEDNESDAY: 386 *startOfWeek = B_WEEKDAY_WEDNESDAY; 387 break; 388 case UCAL_THURSDAY: 389 *startOfWeek = B_WEEKDAY_THURSDAY; 390 break; 391 case UCAL_FRIDAY: 392 *startOfWeek = B_WEEKDAY_FRIDAY; 393 break; 394 case UCAL_SATURDAY: 395 *startOfWeek = B_WEEKDAY_SATURDAY; 396 break; 397 default: 398 return B_ERROR; 399 } 400 401 return B_OK; 402 } 403 404 405 ssize_t 406 BLocale::FormatDateTime(char* target, size_t maxSize, time_t time, 407 BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle) const 408 { 409 BAutolock lock(fLock); 410 if (!lock.IsLocked()) 411 return B_ERROR; 412 413 BString format; 414 fConventions.GetDateFormat(dateStyle, format); 415 ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); 416 if (dateFormatter.Get() == NULL) 417 return B_NO_MEMORY; 418 419 fConventions.GetTimeFormat(timeStyle, format); 420 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); 421 if (timeFormatter.Get() == NULL) 422 return B_NO_MEMORY; 423 424 UnicodeString icuString; 425 dateFormatter->format((UDate)time * 1000, icuString); 426 427 icuString.append(UnicodeString::fromUTF8(", ")); 428 429 timeFormatter->format((UDate)time * 1000, icuString); 430 431 CheckedArrayByteSink stringConverter(target, maxSize); 432 icuString.toUTF8(stringConverter); 433 434 if (stringConverter.Overflowed()) 435 return B_BAD_VALUE; 436 437 return stringConverter.NumberOfBytesWritten(); 438 } 439 440 441 status_t 442 BLocale::FormatDateTime(BString* target, time_t time, 443 BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle, 444 const BTimeZone* timeZone) const 445 { 446 BAutolock lock(fLock); 447 if (!lock.IsLocked()) 448 return B_ERROR; 449 450 BString format; 451 fConventions.GetDateFormat(dateStyle, format); 452 ObjectDeleter<DateFormat> dateFormatter(_CreateDateFormatter(format)); 453 if (dateFormatter.Get() == NULL) 454 return B_NO_MEMORY; 455 456 fConventions.GetTimeFormat(timeStyle, format); 457 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); 458 if (timeFormatter.Get() == NULL) 459 return B_NO_MEMORY; 460 461 if (timeZone != NULL) { 462 ObjectDeleter<TimeZone> icuTimeZone( 463 TimeZone::createTimeZone(timeZone->ID().String())); 464 if (icuTimeZone.Get() == NULL) 465 return B_NO_MEMORY; 466 timeFormatter->setTimeZone(*icuTimeZone.Get()); 467 } 468 469 UnicodeString icuString; 470 dateFormatter->format((UDate)time * 1000, icuString); 471 icuString.append(UnicodeString::fromUTF8(", ")); 472 timeFormatter->format((UDate)time * 1000, icuString); 473 474 target->Truncate(0); 475 BStringByteSink stringConverter(target); 476 icuString.toUTF8(stringConverter); 477 478 return B_OK; 479 } 480 481 482 // #pragma mark - Time 483 484 485 ssize_t 486 BLocale::FormatTime(char* string, size_t maxSize, time_t time, 487 BTimeFormatStyle style) const 488 { 489 BAutolock lock(fLock); 490 if (!lock.IsLocked()) 491 return B_ERROR; 492 493 BString format; 494 fConventions.GetTimeFormat(style, format); 495 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); 496 if (timeFormatter.Get() == NULL) 497 return B_NO_MEMORY; 498 499 UnicodeString icuString; 500 timeFormatter->format((UDate)time * 1000, icuString); 501 502 CheckedArrayByteSink stringConverter(string, maxSize); 503 icuString.toUTF8(stringConverter); 504 505 if (stringConverter.Overflowed()) 506 return B_BAD_VALUE; 507 508 return stringConverter.NumberOfBytesWritten(); 509 } 510 511 512 ssize_t 513 BLocale::FormatTime(char* string, size_t maxSize, time_t time, 514 BString format) const 515 { 516 BAutolock lock(fLock); 517 if (!lock.IsLocked()) 518 return B_ERROR; 519 520 if (format == NULL || format.CountChars() <= 0) 521 return B_BAD_VALUE; 522 523 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); 524 if (timeFormatter.Get() == NULL) 525 return B_NO_MEMORY; 526 527 UnicodeString icuString; 528 timeFormatter->format((UDate)time * 1000, icuString); 529 530 CheckedArrayByteSink stringConverter(string, maxSize); 531 icuString.toUTF8(stringConverter); 532 533 if (stringConverter.Overflowed()) 534 return B_BAD_VALUE; 535 536 return stringConverter.NumberOfBytesWritten(); 537 } 538 539 540 status_t 541 BLocale::FormatTime(BString* string, time_t time, BTimeFormatStyle style, 542 const BTimeZone* timeZone) const 543 { 544 BAutolock lock(fLock); 545 if (!lock.IsLocked()) 546 return B_ERROR; 547 548 BString format; 549 fConventions.GetTimeFormat(style, format); 550 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); 551 if (timeFormatter.Get() == NULL) 552 return B_NO_MEMORY; 553 554 if (timeZone != NULL) { 555 ObjectDeleter<TimeZone> icuTimeZone( 556 TimeZone::createTimeZone(timeZone->ID().String())); 557 if (icuTimeZone.Get() == NULL) 558 return B_NO_MEMORY; 559 timeFormatter->setTimeZone(*icuTimeZone.Get()); 560 } 561 562 UnicodeString icuString; 563 timeFormatter->format((UDate)time * 1000, icuString); 564 565 string->Truncate(0); 566 BStringByteSink stringConverter(string); 567 icuString.toUTF8(stringConverter); 568 569 return B_OK; 570 } 571 572 573 status_t 574 BLocale::FormatTime(BString* string, time_t time, BString format, 575 const BTimeZone* timeZone) const 576 { 577 BAutolock lock(fLock); 578 if (!lock.IsLocked()) 579 return B_ERROR; 580 581 if (format == NULL || format.CountChars() <= 0) 582 return B_BAD_VALUE; 583 584 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); 585 if (timeFormatter.Get() == NULL) 586 return B_NO_MEMORY; 587 588 if (timeZone != NULL) { 589 ObjectDeleter<TimeZone> icuTimeZone( 590 TimeZone::createTimeZone(timeZone->ID().String())); 591 if (icuTimeZone.Get() == NULL) 592 return B_NO_MEMORY; 593 timeFormatter->setTimeZone(*icuTimeZone.Get()); 594 } 595 596 UnicodeString icuString; 597 timeFormatter->format((UDate)time * 1000, icuString); 598 599 string->Truncate(0); 600 BStringByteSink stringConverter(string); 601 icuString.toUTF8(stringConverter); 602 603 return B_OK; 604 } 605 606 607 status_t 608 BLocale::FormatTime(BString* string, int*& fieldPositions, int& fieldCount, 609 time_t time, BTimeFormatStyle style) const 610 { 611 BAutolock lock(fLock); 612 if (!lock.IsLocked()) 613 return B_ERROR; 614 615 BString format; 616 fConventions.GetTimeFormat(style, format); 617 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); 618 if (timeFormatter.Get() == NULL) 619 return B_NO_MEMORY; 620 621 fieldPositions = NULL; 622 UErrorCode error = U_ZERO_ERROR; 623 icu::FieldPositionIterator positionIterator; 624 UnicodeString icuString; 625 timeFormatter->format((UDate)time * 1000, icuString, &positionIterator, 626 error); 627 628 if (error != U_ZERO_ERROR) 629 return B_BAD_VALUE; 630 631 icu::FieldPosition field; 632 std::vector<int> fieldPosStorage; 633 fieldCount = 0; 634 while (positionIterator.next(field)) { 635 fieldPosStorage.push_back(field.getBeginIndex()); 636 fieldPosStorage.push_back(field.getEndIndex()); 637 fieldCount += 2; 638 } 639 640 fieldPositions = (int*) malloc(fieldCount * sizeof(int)); 641 642 for (int i = 0 ; i < fieldCount ; i++ ) 643 fieldPositions[i] = fieldPosStorage[i]; 644 645 string->Truncate(0); 646 BStringByteSink stringConverter(string); 647 icuString.toUTF8(stringConverter); 648 649 return B_OK; 650 } 651 652 653 status_t 654 BLocale::GetTimeFields(BDateElement*& fields, int& fieldCount, 655 BTimeFormatStyle style) const 656 { 657 BAutolock lock(fLock); 658 if (!lock.IsLocked()) 659 return B_ERROR; 660 661 BString format; 662 fConventions.GetTimeFormat(style, format); 663 ObjectDeleter<DateFormat> timeFormatter(_CreateTimeFormatter(format)); 664 if (timeFormatter.Get() == NULL) 665 return B_NO_MEMORY; 666 667 fields = NULL; 668 UErrorCode error = U_ZERO_ERROR; 669 icu::FieldPositionIterator positionIterator; 670 UnicodeString icuString; 671 time_t now; 672 timeFormatter->format((UDate)time(&now) * 1000, icuString, 673 &positionIterator, error); 674 675 if (error != U_ZERO_ERROR) 676 return B_BAD_VALUE; 677 678 icu::FieldPosition field; 679 std::vector<int> fieldPosStorage; 680 fieldCount = 0; 681 while (positionIterator.next(field)) { 682 fieldPosStorage.push_back(field.getField()); 683 fieldCount ++; 684 } 685 686 fields = (BDateElement*) malloc(fieldCount * sizeof(BDateElement)); 687 688 for (int i = 0 ; i < fieldCount ; i++ ) { 689 switch (fieldPosStorage[i]) { 690 case UDAT_HOUR_OF_DAY1_FIELD: 691 case UDAT_HOUR_OF_DAY0_FIELD: 692 case UDAT_HOUR1_FIELD: 693 case UDAT_HOUR0_FIELD: 694 fields[i] = B_DATE_ELEMENT_HOUR; 695 break; 696 case UDAT_MINUTE_FIELD: 697 fields[i] = B_DATE_ELEMENT_MINUTE; 698 break; 699 case UDAT_SECOND_FIELD: 700 fields[i] = B_DATE_ELEMENT_SECOND; 701 break; 702 case UDAT_AM_PM_FIELD: 703 fields[i] = B_DATE_ELEMENT_AM_PM; 704 break; 705 default: 706 fields[i] = B_DATE_ELEMENT_INVALID; 707 break; 708 } 709 } 710 711 return B_OK; 712 } 713 714 715 // #pragma mark - Numbers 716 717 718 ssize_t 719 BLocale::FormatNumber(char* string, size_t maxSize, double value) const 720 { 721 BString fullString; 722 status_t status = FormatNumber(&fullString, value); 723 if (status != B_OK) 724 return status; 725 726 return strlcpy(string, fullString.String(), maxSize); 727 } 728 729 730 status_t 731 BLocale::FormatNumber(BString* string, double value) const 732 { 733 BAutolock lock(fLock); 734 if (!lock.IsLocked()) 735 return B_ERROR; 736 737 UErrorCode err = U_ZERO_ERROR; 738 ObjectDeleter<NumberFormat> numberFormatter(NumberFormat::createInstance( 739 *BFormattingConventions::Private(&fConventions).ICULocale(), 740 UNUM_DECIMAL, err)); 741 742 if (numberFormatter.Get() == NULL) 743 return B_NO_MEMORY; 744 if (U_FAILURE(err)) 745 return B_BAD_VALUE; 746 747 UnicodeString icuString; 748 numberFormatter->format(value, icuString); 749 750 string->Truncate(0); 751 BStringByteSink stringConverter(string); 752 icuString.toUTF8(stringConverter); 753 754 return B_OK; 755 } 756 757 758 ssize_t 759 BLocale::FormatNumber(char* string, size_t maxSize, int32 value) const 760 { 761 BString fullString; 762 status_t status = FormatNumber(&fullString, value); 763 if (status != B_OK) 764 return status; 765 766 return strlcpy(string, fullString.String(), maxSize); 767 } 768 769 770 status_t 771 BLocale::FormatNumber(BString* string, int32 value) const 772 { 773 BAutolock lock(fLock); 774 if (!lock.IsLocked()) 775 return B_ERROR; 776 777 UErrorCode err = U_ZERO_ERROR; 778 ObjectDeleter<NumberFormat> numberFormatter(NumberFormat::createInstance( 779 *BFormattingConventions::Private(&fConventions).ICULocale(), 780 UNUM_DECIMAL, err)); 781 782 if (numberFormatter.Get() == NULL) 783 return B_NO_MEMORY; 784 if (U_FAILURE(err)) 785 return B_BAD_VALUE; 786 787 UnicodeString icuString; 788 numberFormatter->format((int32_t)value, icuString); 789 790 string->Truncate(0); 791 BStringByteSink stringConverter(string); 792 icuString.toUTF8(stringConverter); 793 794 return B_OK; 795 } 796 797 798 ssize_t 799 BLocale::FormatMonetary(char* string, size_t maxSize, double value) const 800 { 801 BString fullString; 802 status_t status = FormatMonetary(&fullString, value); 803 if (status != B_OK) 804 return status; 805 806 return strlcpy(string, fullString.String(), maxSize); 807 } 808 809 810 status_t 811 BLocale::FormatMonetary(BString* string, double value) const 812 { 813 if (string == NULL) 814 return B_BAD_VALUE; 815 816 BAutolock lock(fLock); 817 if (!lock.IsLocked()) 818 return B_ERROR; 819 820 UErrorCode err = U_ZERO_ERROR; 821 ObjectDeleter<NumberFormat> numberFormatter( 822 NumberFormat::createCurrencyInstance( 823 *BFormattingConventions::Private(&fConventions).ICULocale(), 824 err)); 825 826 if (numberFormatter.Get() == NULL) 827 return B_NO_MEMORY; 828 if (U_FAILURE(err)) 829 return B_BAD_VALUE; 830 831 UnicodeString icuString; 832 numberFormatter->format(value, icuString); 833 834 string->Truncate(0); 835 BStringByteSink stringConverter(string); 836 icuString.toUTF8(stringConverter); 837 838 return B_OK; 839 } 840 841 842 DateFormat* 843 BLocale::_CreateDateFormatter(const BString& format) const 844 { 845 Locale* icuLocale 846 = fConventions.UseStringsFromPreferredLanguage() 847 ? BLanguage::Private(&fLanguage).ICULocale() 848 : BFormattingConventions::Private(&fConventions).ICULocale(); 849 850 DateFormat* dateFormatter 851 = DateFormat::createDateInstance(DateFormat::kShort, *icuLocale); 852 if (dateFormatter == NULL) 853 return NULL; 854 855 SimpleDateFormat* dateFormatterImpl 856 = static_cast<SimpleDateFormat*>(dateFormatter); 857 858 UnicodeString pattern(format.String()); 859 dateFormatterImpl->applyPattern(pattern); 860 861 return dateFormatter; 862 } 863 864 865 DateFormat* 866 BLocale::_CreateTimeFormatter(const BString& format) const 867 { 868 Locale* icuLocale 869 = fConventions.UseStringsFromPreferredLanguage() 870 ? BLanguage::Private(&fLanguage).ICULocale() 871 : BFormattingConventions::Private(&fConventions).ICULocale(); 872 873 DateFormat* timeFormatter 874 = DateFormat::createTimeInstance(DateFormat::kShort, *icuLocale); 875 if (timeFormatter == NULL) 876 return NULL; 877 878 SimpleDateFormat* timeFormatterImpl 879 = static_cast<SimpleDateFormat*>(timeFormatter); 880 881 UnicodeString pattern(format.String()); 882 timeFormatterImpl->applyPattern(pattern); 883 884 return timeFormatter; 885 } 886