138ac8defSOliver Tappe /* 2e3857211SAdrien Destugues * Copyright 2010-2014, Haiku, Inc. All Rights Reserved. 338ac8defSOliver Tappe * Distributed under the terms of the MIT License. 438ac8defSOliver Tappe * 538ac8defSOliver Tappe * Authors: 638ac8defSOliver Tappe * Oliver Tappe <zooey@hirschkaefer.de> 738ac8defSOliver Tappe */ 838ac8defSOliver Tappe 938ac8defSOliver Tappe #include <DateTimeFormat.h> 1038ac8defSOliver Tappe 11e3857211SAdrien Destugues #include <AutoDeleter.h> 12e3857211SAdrien Destugues #include <Autolock.h> 13e3857211SAdrien Destugues #include <FormattingConventionsPrivate.h> 14e3857211SAdrien Destugues #include <LanguagePrivate.h> 15e3857211SAdrien Destugues #include <TimeZone.h> 1638ac8defSOliver Tappe 17e3857211SAdrien Destugues #include <ICUWrapper.h> 18e3857211SAdrien Destugues 19e3857211SAdrien Destugues #include <unicode/datefmt.h> 204a3a4742SAdrien Destugues #include <unicode/dtptngen.h> 21e3857211SAdrien Destugues #include <unicode/smpdtfmt.h> 22e3857211SAdrien Destugues 23e3857211SAdrien Destugues 244a3a4742SAdrien Destugues BDateTimeFormat::BDateTimeFormat(const BLanguage* const language, 254a3a4742SAdrien Destugues const BFormattingConventions* const conventions) 2638ac8defSOliver Tappe { 274a3a4742SAdrien Destugues if (conventions != NULL) 284a3a4742SAdrien Destugues fConventions = *conventions; 294a3a4742SAdrien Destugues 304a3a4742SAdrien Destugues if (language != NULL) 314a3a4742SAdrien Destugues fLanguage = *language; 3238ac8defSOliver Tappe } 3338ac8defSOliver Tappe 34f3dd81abSOliver Tappe 3538ac8defSOliver Tappe BDateTimeFormat::BDateTimeFormat(const BDateTimeFormat &other) 3638ac8defSOliver Tappe : BFormat(other) 3738ac8defSOliver Tappe { 3838ac8defSOliver Tappe } 3938ac8defSOliver Tappe 40f3dd81abSOliver Tappe 4138ac8defSOliver Tappe BDateTimeFormat::~BDateTimeFormat() 4238ac8defSOliver Tappe { 4338ac8defSOliver Tappe } 4438ac8defSOliver Tappe 45f3dd81abSOliver Tappe 464a3a4742SAdrien Destugues void 474a3a4742SAdrien Destugues BDateTimeFormat::SetDateTimeFormat(BDateFormatStyle dateStyle, 484a3a4742SAdrien Destugues BTimeFormatStyle timeStyle, int32 elements) { 494a3a4742SAdrien Destugues UErrorCode error = U_ZERO_ERROR; 504a3a4742SAdrien Destugues DateTimePatternGenerator* generator 514a3a4742SAdrien Destugues = DateTimePatternGenerator::createInstance(error); 524a3a4742SAdrien Destugues 534a3a4742SAdrien Destugues BString skeleton; 544a3a4742SAdrien Destugues if (elements & B_DATE_ELEMENT_YEAR) 554a3a4742SAdrien Destugues skeleton << "yyyy"; 564a3a4742SAdrien Destugues if (elements & B_DATE_ELEMENT_MONTH) 574a3a4742SAdrien Destugues skeleton << "MM"; 584a3a4742SAdrien Destugues if (elements & B_DATE_ELEMENT_WEEKDAY) 594a3a4742SAdrien Destugues skeleton << "eee"; 604a3a4742SAdrien Destugues if (elements & B_DATE_ELEMENT_DAY) 614a3a4742SAdrien Destugues skeleton << "dd"; 624a3a4742SAdrien Destugues if (elements & B_DATE_ELEMENT_AM_PM) 634a3a4742SAdrien Destugues skeleton << "a"; 64*824cb460SAdrien Destugues if (elements & B_DATE_ELEMENT_HOUR) { 65*824cb460SAdrien Destugues if (fConventions.Use24HourClock()) 66*824cb460SAdrien Destugues skeleton << "HH"; 67*824cb460SAdrien Destugues else 68*824cb460SAdrien Destugues skeleton << "KK"; 69*824cb460SAdrien Destugues } 704a3a4742SAdrien Destugues if (elements & B_DATE_ELEMENT_MINUTE) 714a3a4742SAdrien Destugues skeleton << "mm"; 724a3a4742SAdrien Destugues if (elements & B_DATE_ELEMENT_SECOND) 734a3a4742SAdrien Destugues skeleton << "ss"; 744a3a4742SAdrien Destugues if (elements & B_DATE_ELEMENT_TIMEZONE) 75892f3b8bSAdrien Destugues skeleton << "z"; 764a3a4742SAdrien Destugues 774a3a4742SAdrien Destugues UnicodeString pattern = generator->getBestPattern( 784a3a4742SAdrien Destugues UnicodeString::fromUTF8(skeleton.String()), error); 794a3a4742SAdrien Destugues 804a3a4742SAdrien Destugues BString buffer; 814a3a4742SAdrien Destugues BStringByteSink stringConverter(&buffer); 824a3a4742SAdrien Destugues pattern.toUTF8(stringConverter); 834a3a4742SAdrien Destugues fConventions.SetExplicitDateTimeFormat(dateStyle, timeStyle, buffer); 844a3a4742SAdrien Destugues 854a3a4742SAdrien Destugues delete generator; 864a3a4742SAdrien Destugues } 874a3a4742SAdrien Destugues 884a3a4742SAdrien Destugues 89e3857211SAdrien Destugues // #pragma mark - Formatting 90e3857211SAdrien Destugues 91e3857211SAdrien Destugues 92e3857211SAdrien Destugues ssize_t 93e3857211SAdrien Destugues BDateTimeFormat::Format(char* target, size_t maxSize, time_t time, 94e3857211SAdrien Destugues BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle) const 9538ac8defSOliver Tappe { 96e3857211SAdrien Destugues BAutolock lock(fLock); 97e3857211SAdrien Destugues if (!lock.IsLocked()) 9838ac8defSOliver Tappe return B_ERROR; 99e3857211SAdrien Destugues 100e3857211SAdrien Destugues BString format; 1014a3a4742SAdrien Destugues fConventions.GetDateTimeFormat(dateStyle, timeStyle, format); 1024a3a4742SAdrien Destugues ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format)); 103e3857211SAdrien Destugues if (dateFormatter.Get() == NULL) 104e3857211SAdrien Destugues return B_NO_MEMORY; 105e3857211SAdrien Destugues 106e3857211SAdrien Destugues UnicodeString icuString; 107e3857211SAdrien Destugues dateFormatter->format((UDate)time * 1000, icuString); 108e3857211SAdrien Destugues 109e3857211SAdrien Destugues CheckedArrayByteSink stringConverter(target, maxSize); 110e3857211SAdrien Destugues icuString.toUTF8(stringConverter); 111e3857211SAdrien Destugues 112e3857211SAdrien Destugues if (stringConverter.Overflowed()) 113e3857211SAdrien Destugues return B_BAD_VALUE; 114e3857211SAdrien Destugues 115e3857211SAdrien Destugues return stringConverter.NumberOfBytesWritten(); 116e3857211SAdrien Destugues } 117e3857211SAdrien Destugues 118e3857211SAdrien Destugues 119e3857211SAdrien Destugues status_t 120e3857211SAdrien Destugues BDateTimeFormat::Format(BString& target, const time_t time, 121e3857211SAdrien Destugues BDateFormatStyle dateStyle, BTimeFormatStyle timeStyle, 122e3857211SAdrien Destugues const BTimeZone* timeZone) const 123e3857211SAdrien Destugues { 124e3857211SAdrien Destugues BAutolock lock(fLock); 125e3857211SAdrien Destugues if (!lock.IsLocked()) 126e3857211SAdrien Destugues return B_ERROR; 127e3857211SAdrien Destugues 128e3857211SAdrien Destugues BString format; 1294a3a4742SAdrien Destugues fConventions.GetDateTimeFormat(dateStyle, timeStyle, format); 1304a3a4742SAdrien Destugues ObjectDeleter<DateFormat> dateFormatter(_CreateDateTimeFormatter(format)); 131e3857211SAdrien Destugues if (dateFormatter.Get() == NULL) 132e3857211SAdrien Destugues return B_NO_MEMORY; 133e3857211SAdrien Destugues 134e3857211SAdrien Destugues if (timeZone != NULL) { 135e3857211SAdrien Destugues ObjectDeleter<TimeZone> icuTimeZone( 136e3857211SAdrien Destugues TimeZone::createTimeZone(timeZone->ID().String())); 137e3857211SAdrien Destugues if (icuTimeZone.Get() == NULL) 138e3857211SAdrien Destugues return B_NO_MEMORY; 1394a3a4742SAdrien Destugues dateFormatter->setTimeZone(*icuTimeZone.Get()); 140e3857211SAdrien Destugues } 141e3857211SAdrien Destugues 142e3857211SAdrien Destugues UnicodeString icuString; 143e3857211SAdrien Destugues dateFormatter->format((UDate)time * 1000, icuString); 144e3857211SAdrien Destugues 145e3857211SAdrien Destugues target.Truncate(0); 146e3857211SAdrien Destugues BStringByteSink stringConverter(&target); 147e3857211SAdrien Destugues icuString.toUTF8(stringConverter); 148e3857211SAdrien Destugues 149e3857211SAdrien Destugues return B_OK; 150e3857211SAdrien Destugues } 151e3857211SAdrien Destugues 152e3857211SAdrien Destugues 153e3857211SAdrien Destugues DateFormat* 1544a3a4742SAdrien Destugues BDateTimeFormat::_CreateDateTimeFormatter(const BString& format) const 155e3857211SAdrien Destugues { 156e3857211SAdrien Destugues Locale* icuLocale 157e3857211SAdrien Destugues = fConventions.UseStringsFromPreferredLanguage() 158e3857211SAdrien Destugues ? BLanguage::Private(&fLanguage).ICULocale() 159e3857211SAdrien Destugues : BFormattingConventions::Private(&fConventions).ICULocale(); 160e3857211SAdrien Destugues 1614a3a4742SAdrien Destugues icu::DateFormat* dateFormatter = icu::DateFormat::createDateTimeInstance( 1624a3a4742SAdrien Destugues DateFormat::kDefault, DateFormat::kDefault, *icuLocale); 163e3857211SAdrien Destugues if (dateFormatter == NULL) 164e3857211SAdrien Destugues return NULL; 165e3857211SAdrien Destugues 166e3857211SAdrien Destugues SimpleDateFormat* dateFormatterImpl 167e3857211SAdrien Destugues = static_cast<SimpleDateFormat*>(dateFormatter); 168e3857211SAdrien Destugues 169e3857211SAdrien Destugues UnicodeString pattern(format.String()); 170e3857211SAdrien Destugues dateFormatterImpl->applyPattern(pattern); 171e3857211SAdrien Destugues 172e3857211SAdrien Destugues return dateFormatter; 173e3857211SAdrien Destugues } 174